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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-08-12 14:52:49 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-08-12 14:52:49 +0300
commitdc2d841b7c50565302af2986d62ddbd29c332acd (patch)
tree324f234e56fde77fb80dfdef0c7c21f01968f71b
parent27b28e437d974ebbafa234205941c07aa0ab546c (diff)
parent4b6fa4d897a0bb3252b16383492b526d2cef3920 (diff)
Merge branch 'blender2.8' into hair_guideshair_guides
-rw-r--r--CMakeLists.txt106
-rw-r--r--build_files/build_environment/CMakeLists.txt27
-rw-r--r--build_files/build_environment/cmake/blosc.cmake1
-rw-r--r--build_files/build_environment/cmake/boost.cmake22
-rw-r--r--build_files/build_environment/cmake/clang.cmake11
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake11
-rw-r--r--build_files/build_environment/cmake/freetype.cmake18
-rw-r--r--build_files/build_environment/cmake/harvest.cmake12
-rw-r--r--build_files/build_environment/cmake/jpeg.cmake2
-rw-r--r--build_files/build_environment/cmake/llvm.cmake3
-rw-r--r--build_files/build_environment/cmake/numpy.cmake8
-rw-r--r--build_files/build_environment/cmake/openimageio.cmake4
-rw-r--r--build_files/build_environment/cmake/openjpeg.cmake2
-rw-r--r--build_files/build_environment/cmake/openmp.cmake (renamed from build_files/build_environment/cmake/orc.cmake)22
-rw-r--r--build_files/build_environment/cmake/options.cmake2
-rw-r--r--build_files/build_environment/cmake/python.cmake64
-rw-r--r--build_files/build_environment/cmake/schroedinger.cmake48
-rw-r--r--build_files/build_environment/cmake/setup_mingw32.cmake12
-rw-r--r--build_files/build_environment/cmake/setup_mingw64.cmake11
-rw-r--r--build_files/build_environment/cmake/versions.cmake94
-rw-r--r--build_files/build_environment/cmake/webp.cmake9
-rwxr-xr-xbuild_files/build_environment/install_deps.sh38
-rw-r--r--build_files/build_environment/patches/boost.diff37
-rw-r--r--build_files/build_environment/patches/clang.diff127
-rw-r--r--build_files/build_environment/patches/ffmpeg.diff27
-rw-r--r--build_files/build_environment/patches/freetype.diff18
-rw-r--r--build_files/build_environment/patches/llvm-alloca-fix.diff111
-rw-r--r--build_files/build_environment/patches/numpy.diff23
-rw-r--r--build_files/build_environment/patches/schroedinger.diff54
-rw-r--r--build_files/buildbot/slave_compile.py2
-rw-r--r--build_files/cmake/macros.cmake165
-rw-r--r--build_files/cmake/platform/platform_apple.cmake7
-rw-r--r--build_files/cmake/platform/platform_apple_xcode.cmake2
-rw-r--r--build_files/cmake/platform/platform_win32.cmake3
-rw-r--r--build_files/windows/autodetect_msvc.cmd7
-rw-r--r--build_files/windows/check_libraries.cmd3
-rw-r--r--build_files/windows/detect_msvc2013.cmd3
-rw-r--r--build_files/windows/detect_msvc2017.cmd2
-rw-r--r--build_files/windows/parse_arguments.cmd2
-rw-r--r--build_files/windows/show_help.cmd8
-rw-r--r--doc/python_api/sphinx_doc_gen.py6
-rw-r--r--extern/audaspace/blender_config.cmake37
-rw-r--r--intern/CMakeLists.txt1
-rw-r--r--intern/clog/clog.c4
-rw-r--r--intern/cycles/CMakeLists.txt25
-rw-r--r--intern/cycles/blender/addon/engine.py12
-rw-r--r--intern/cycles/blender/addon/ui.py14
-rw-r--r--intern/cycles/blender/blender_mesh.cpp27
-rw-r--r--intern/cycles/blender/blender_object.cpp29
-rw-r--r--intern/cycles/blender/blender_python.cpp9
-rw-r--r--intern/cycles/blender/blender_session.cpp18
-rw-r--r--intern/cycles/blender/blender_session.h2
-rw-r--r--intern/cycles/blender/blender_shader.cpp8
-rw-r--r--intern/cycles/blender/blender_sync.cpp43
-rw-r--r--intern/cycles/blender/blender_sync.h21
-rw-r--r--intern/cycles/device/device_opencl.cpp43
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp15
-rw-r--r--intern/cycles/graph/node.cpp85
-rw-r--r--intern/cycles/graph/node.h3
-rw-r--r--intern/cycles/graph/node_type.cpp2
-rw-r--r--intern/cycles/graph/node_type.h6
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume_all.h24
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume_all.h24
-rw-r--r--intern/cycles/kernel/closure/bsdf.h14
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair_principled.h502
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h27
-rw-r--r--intern/cycles/kernel/geom/geom_curve_intersect.h25
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h1
-rw-r--r--intern/cycles/kernel/kernel_light.h25
-rw-r--r--intern/cycles/kernel/kernel_montecarlo.h29
-rw-r--r--intern/cycles/kernel/kernel_types.h2
-rw-r--r--intern/cycles/kernel/kernel_volume.h6
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp61
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h1
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_bump.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl105
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h31
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h120
-rw-r--r--intern/cycles/kernel/svm/svm_displace.h2
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h2
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
-rw-r--r--intern/cycles/kernel/svm/svm_voronoi.h3
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/graph.cpp3
-rw-r--r--intern/cycles/render/image.cpp177
-rw-r--r--intern/cycles/render/image.h10
-rw-r--r--intern/cycles/render/mesh.cpp24
-rw-r--r--intern/cycles/render/mesh.h7
-rw-r--r--intern/cycles/render/mesh_volume.cpp91
-rw-r--r--intern/cycles/render/nodes.cpp133
-rw-r--r--intern/cycles/render/nodes.h39
-rw-r--r--intern/cycles/render/scene.cpp6
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/stats.cpp119
-rw-r--r--intern/cycles/render/stats.h104
-rw-r--r--intern/cycles/util/util_defines.h6
-rw-r--r--intern/cycles/util/util_foreach.h9
-rw-r--r--intern/cycles/util/util_function.h18
-rw-r--r--intern/cycles/util/util_half.h2
-rw-r--r--intern/cycles/util/util_image.h62
-rw-r--r--intern/cycles/util/util_image_impl.h66
-rw-r--r--intern/cycles/util/util_map.h27
-rw-r--r--intern/cycles/util/util_math.h19
-rw-r--r--intern/cycles/util/util_math_float3.h20
-rw-r--r--intern/cycles/util/util_set.h32
-rw-r--r--intern/cycles/util/util_static_assert.h22
-rw-r--r--intern/cycles/util/util_string.cpp5
-rw-r--r--intern/cycles/util/util_string.h2
-rw-r--r--intern/cycles/util/util_thread.cpp8
-rw-r--r--intern/cycles/util/util_thread.h24
-rw-r--r--intern/cycles/util/util_vector.h4
-rw-r--r--intern/gawain/CMakeLists.txt50
-rw-r--r--intern/gawain/gawain/gwn_attr_binding.h19
-rw-r--r--intern/gawain/gawain/gwn_attr_binding_private.h20
-rw-r--r--intern/gawain/gawain/gwn_batch.h169
-rw-r--r--intern/gawain/gawain/gwn_batch_private.h30
-rw-r--r--intern/gawain/gawain/gwn_buffer_id.h30
-rw-r--r--intern/gawain/gawain/gwn_common.h39
-rw-r--r--intern/gawain/gawain/gwn_context.h34
-rw-r--r--intern/gawain/gawain/gwn_element.h79
-rw-r--r--intern/gawain/gawain/gwn_imm_util.h22
-rw-r--r--intern/gawain/gawain/gwn_immediate.h120
-rw-r--r--intern/gawain/gawain/gwn_primitive.h42
-rw-r--r--intern/gawain/gawain/gwn_primitive_private.h14
-rw-r--r--intern/gawain/gawain/gwn_shader_interface.h81
-rw-r--r--intern/gawain/gawain/gwn_vertex_array_id.h34
-rw-r--r--intern/gawain/gawain/gwn_vertex_buffer.h125
-rw-r--r--intern/gawain/gawain/gwn_vertex_format.h78
-rw-r--r--intern/gawain/gawain/gwn_vertex_format_private.h16
-rw-r--r--intern/gawain/src/gwn_attr_binding.c70
-rw-r--r--intern/gawain/src/gwn_batch.c632
-rw-r--r--intern/gawain/src/gwn_buffer_id.cpp70
-rw-r--r--intern/gawain/src/gwn_element.c304
-rw-r--r--intern/gawain/src/gwn_imm_util.c80
-rw-r--r--intern/gawain/src/gwn_immediate.c923
-rw-r--r--intern/gawain/src/gwn_primitive.c67
-rw-r--r--intern/gawain/src/gwn_shader_interface.c362
-rw-r--r--intern/gawain/src/gwn_vertex_array_id.cpp174
-rw-r--r--intern/gawain/src/gwn_vertex_buffer.c258
-rw-r--r--intern/gawain/src/gwn_vertex_format.c291
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp20
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h1
-rw-r--r--intern/ghost/intern/GHOST_System.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp29
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp2
-rw-r--r--intern/ghost/intern/GHOST_TaskbarX11.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm28
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp4
-rw-r--r--intern/opencolorio/CMakeLists.txt2
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc16
-rw-r--r--intern/opensubdiv/CMakeLists.txt48
-rw-r--r--intern/opensubdiv/internal/opensubdiv.cc99
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_factory.cc469
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_factory.h37
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_internal.cc87
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_internal.h51
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient.cc66
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient.h50
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h66
-rw-r--r--intern/opensubdiv/internal/opensubdiv_device_context_cuda.cc226
-rw-r--r--intern/opensubdiv/internal/opensubdiv_device_context_cuda.h54
-rw-r--r--intern/opensubdiv/internal/opensubdiv_device_context_opencl.cc269
-rw-r--r--intern/opensubdiv/internal/opensubdiv_device_context_opencl.h52
-rw-r--r--intern/opensubdiv/internal/opensubdiv_evaluator.cc158
-rw-r--r--intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc835
-rw-r--r--intern/opensubdiv/internal/opensubdiv_evaluator_internal.h137
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh.cc287
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc587
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h39
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc175
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h57
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc32
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h43
-rw-r--r--intern/opensubdiv/internal/opensubdiv_internal.h35
-rw-r--r--intern/opensubdiv/internal/opensubdiv_topology_refiner.cc367
-rw-r--r--intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.cc26
-rw-r--r--intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.h47
-rw-r--r--intern/opensubdiv/internal/opensubdiv_util.cc61
-rw-r--r--intern/opensubdiv/internal/opensubdiv_util.h44
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc441
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h178
-rw-r--r--intern/opensubdiv/opensubdiv_capi_type.h56
-rw-r--r--intern/opensubdiv/opensubdiv_converter.cc764
-rw-r--r--intern/opensubdiv/opensubdiv_converter_capi.h284
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_cuda.cc237
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_cuda.h54
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_opencl.cc251
-rw-r--r--intern/opensubdiv/opensubdiv_device_context_opencl.h58
-rw-r--r--intern/opensubdiv/opensubdiv_evaluator_capi.cc516
-rw-r--r--intern/opensubdiv/opensubdiv_evaluator_capi.h120
-rw-r--r--intern/opensubdiv/opensubdiv_gl_mesh_capi.h92
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc788
-rw-r--r--intern/opensubdiv/opensubdiv_topology_refiner_capi.h151
-rw-r--r--intern/opensubdiv/opensubdiv_utils_capi.cc88
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl (renamed from intern/opensubdiv/gpu_shader_opensubdiv_fragment.glsl)0
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl (renamed from intern/opensubdiv/gpu_shader_opensubdiv_geometry.glsl)0
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl (renamed from intern/opensubdiv/gpu_shader_opensubdiv_vertex.glsl)0
-rw-r--r--intern/rigidbody/RBI_api.h9
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp55
-rw-r--r--release/datafiles/brushicons/gp_brush_block.pngbin0 -> 6088 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_clone.pngbin0 -> 2586 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_erase_hard.pngbin0 -> 6107 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_erase_soft.pngbin0 -> 6252 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_erase_stroke.pngbin0 -> 5955 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_fill.pngbin0 -> 5707 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_grab.pngbin0 -> 2741 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_ink.pngbin0 -> 4034 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_inknoise.pngbin0 -> 5591 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_marker.pngbin0 -> 5996 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_pen.pngbin0 -> 4920 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_pencil.pngbin0 -> 3965 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_pinch.pngbin0 -> 5432 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_push.pngbin0 -> 2914 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_randomize.pngbin0 -> 5726 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_smooth.pngbin0 -> 3105 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_strength.pngbin0 -> 3229 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_thickness.pngbin0 -> 5066 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_twist.pngbin0 -> 4776 bytes
-rw-r--r--release/datafiles/brushicons/gp_brush_weight.pngbin0 -> 2460 bytes
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rw-r--r--release/datafiles/icons/brush.gpencil.draw.eraser_hard.datbin0 -> 1736 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw.eraser_soft.datbin0 -> 1880 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw.eraser_stroke.datbin0 -> 2456 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_block.datbin0 -> 2006 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_fill.datbin0 -> 6326 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_ink.datbin0 -> 2240 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_marker.datbin0 -> 2690 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_noise.datbin0 -> 3086 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_pen.datbin0 -> 3158 bytes
-rw-r--r--release/datafiles/icons/brush.gpencil.draw_pencil.datbin0 -> 2780 bytes
-rw-r--r--release/datafiles/icons/brush.particle.add.datbin0 -> 2060 bytes
-rw-r--r--release/datafiles/icons/brush.particle.comb.datbin0 -> 3590 bytes
-rw-r--r--release/datafiles/icons/brush.particle.cut.datbin0 -> 6578 bytes
-rw-r--r--release/datafiles/icons/brush.particle.length.datbin0 -> 3824 bytes
-rw-r--r--release/datafiles/icons/brush.particle.puff.datbin0 -> 3644 bytes
-rw-r--r--release/datafiles/icons/brush.particle.smooth.datbin0 -> 2870 bytes
-rw-r--r--release/datafiles/icons/brush.particle.weight.datbin0 -> 3878 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.draw.datbin0 -> 2492 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.draw.eraser.datbin0 -> 2384 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.draw.line.datbin0 -> 1664 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.draw.poly.datbin0 -> 1736 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.edit_bend.datbin0 -> 2330 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.edit_mirror.datbin0 -> 620 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.edit_shear.datbin0 -> 332 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.edit_to_sphere.datbin0 -> 1790 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_clone.datbin0 -> 4328 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_grab.datbin0 -> 1664 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_pinch.datbin0 -> 3482 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_push.datbin0 -> 1664 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_randomize.datbin0 -> 6254 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_smooth.datbin0 -> 3788 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_strength.datbin0 -> 5228 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_thickness.datbin0 -> 1700 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_twist.datbin0 -> 2942 bytes
-rw-r--r--release/datafiles/icons/ops.gpencil.sculpt_weight.datbin0 -> 1736 bytes
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/preview_grease_pencil.blendbin0 -> 947876 bytes
-rw-r--r--release/datafiles/studiolights/matcap/basic_1.exrbin0 -> 44539 bytes
-rw-r--r--release/datafiles/studiolights/matcap/basic_2.exrbin0 -> 61142 bytes
-rw-r--r--release/datafiles/studiolights/matcap/basic_dark.exrbin0 -> 38734 bytes
-rw-r--r--release/datafiles/studiolights/matcap/basic_side.exrbin0 -> 41554 bytes
-rw-r--r--release/datafiles/studiolights/matcap/ceramic_dark.exrbin0 -> 63518 bytes
-rw-r--r--release/datafiles/studiolights/matcap/ceramic_lightbulb.exrbin0 -> 102212 bytes
-rw-r--r--release/datafiles/studiolights/matcap/check_normal+y.exrbin0 -> 87477 bytes
-rw-r--r--release/datafiles/studiolights/matcap/check_reflection.exrbin0 -> 151596 bytes
-rw-r--r--release/datafiles/studiolights/matcap/check_rim_dark.exrbin0 -> 50807 bytes
-rw-r--r--release/datafiles/studiolights/matcap/check_rim_light.exrbin0 -> 56757 bytes
-rw-r--r--release/datafiles/studiolights/matcap/clay_brown.exrbin0 -> 65156 bytes
-rw-r--r--release/datafiles/studiolights/matcap/clay_muddy.exrbin0 -> 53778 bytes
-rw-r--r--release/datafiles/studiolights/matcap/clay_studio.exrbin0 -> 51624 bytes
-rw-r--r--release/datafiles/studiolights/matcap/jade.exrbin0 -> 63103 bytes
-rw-r--r--release/datafiles/studiolights/matcap/license.txt4
-rw-r--r--release/datafiles/studiolights/matcap/mc01.jpgbin20830 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc02.jpgbin23428 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc03.jpgbin17550 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc04.jpgbin29197 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc05.jpgbin25454 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc06.jpgbin19864 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc07.jpgbin59262 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc08.jpgbin24133 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc09.jpgbin31101 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc10.jpgbin28973 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc11.jpgbin21395 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc12.jpgbin23797 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc13.jpgbin45661 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc14.jpgbin44762 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc15.jpgbin27456 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc16.jpgbin33401 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc17.jpgbin49292 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc18.jpgbin40254 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc19.jpgbin46330 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc20.jpgbin52893 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc21.jpgbin28717 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc22.jpgbin33801 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc23.jpgbin26688 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/mc24.jpgbin14149 -> 0 bytes
-rw-r--r--release/datafiles/studiolights/matcap/metal_anisotropic.exrbin0 -> 118909 bytes
-rw-r--r--release/datafiles/studiolights/matcap/metal_carpaint.exrbin0 -> 91775 bytes
-rw-r--r--release/datafiles/studiolights/matcap/metal_lead.exrbin0 -> 41455 bytes
-rw-r--r--release/datafiles/studiolights/matcap/metal_shiny.exrbin0 -> 126238 bytes
-rw-r--r--release/datafiles/studiolights/matcap/pearl.exrbin0 -> 70218 bytes
-rw-r--r--release/datafiles/studiolights/matcap/resin.exrbin0 -> 91009 bytes
-rw-r--r--release/datafiles/studiolights/matcap/skin.exrbin0 -> 55351 bytes
-rw-r--r--release/datafiles/studiolights/matcap/toon.exrbin0 -> 55733 bytes
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c10
m---------release/scripts/addons0
-rw-r--r--release/scripts/modules/addon_utils.py16
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py7
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py4
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py4
-rw-r--r--release/scripts/modules/bpy_types.py30
-rw-r--r--release/scripts/modules/rna_prop_ui.py17
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py9
-rw-r--r--release/scripts/startup/bl_operators/clip.py16
-rw-r--r--release/scripts/startup/bl_operators/mesh.py50
-rw-r--r--release/scripts/startup/bl_operators/object.py2
-rw-r--r--release/scripts/startup/bl_operators/object_align.py8
-rw-r--r--release/scripts/startup/bl_operators/presets.py39
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py14
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py2
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py8
-rw-r--r--release/scripts/startup/bl_operators/wm.py15
-rw-r--r--release/scripts/startup/bl_ui/__init__.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py31
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py404
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_light.py77
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lightprobe.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py30
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py496
-rw-r--r--release/scripts/startup/bl_ui/properties_data_shaderfx.py135
-rw-r--r--release/scripts/startup/bl_ui/properties_data_speaker.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py789
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_material_gpencil.py321
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py541
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py212
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py89
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py346
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py139
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py122
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py246
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py596
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py23
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py41
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py4
-rw-r--r--release/scripts/startup/bl_ui/space_image.py40
-rw-r--r--release/scripts/startup/bl_ui/space_node.py74
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py11
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py27
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py4
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py608
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py105
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py124
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py504
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py435
-rw-r--r--release/scripts/startup/nodeitems_builtins.py2
-rw-r--r--release/scripts/templates_py/batch_export.py8
-rw-r--r--release/scripts/templates_py/gizmo_custom_geometry.py4
-rw-r--r--release/scripts/templates_py/gizmo_operator.py6
-rw-r--r--release/scripts/templates_py/gizmo_operator_target.py4
-rw-r--r--release/scripts/templates_py/gizmo_simple.py4
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py2
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc9
-rw-r--r--source/blender/alembic/intern/abc_mball.cc2
-rw-r--r--source/blender/alembic/intern/abc_nurbs.cc4
-rw-r--r--source/blender/blenfont/BLF_api.h4
-rw-r--r--source/blender/blenfont/intern/blf.c23
-rw-r--r--source/blender/blenfont/intern/blf_font.c51
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c21
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h8
-rw-r--r--source/blender/blenkernel/BKE_action.h1
-rw-r--r--source/blender/blenkernel/BKE_animsys.h2
-rw-r--r--source/blender/blenkernel/BKE_armature.h13
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h9
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h8
-rw-r--r--source/blender/blenkernel/BKE_context.h14
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h106
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h256
-rw-r--r--source/blender/blenkernel/BKE_icons.h7
-rw-r--r--source/blender/blenkernel/BKE_lattice.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h14
-rw-r--r--source/blender/blenkernel/BKE_material.h4
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/BKE_mesh_mapping.h18
-rw-r--r--source/blender/blenkernel/BKE_node.h10
-rw-r--r--source/blender/blenkernel/BKE_object.h14
-rw-r--r--source/blender/blenkernel/BKE_paint.h3
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h4
-rw-r--r--source/blender/blenkernel/BKE_scene.h6
-rw-r--r--source/blender/blenkernel/BKE_screen.h3
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_shader_fx.h180
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h2
-rw-r--r--source/blender/blenkernel/BKE_subdiv.h214
-rw-r--r--source/blender/blenkernel/CMakeLists.txt16
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c6
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_intern.h4
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c139
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c105
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1
-rw-r--r--source/blender/blenkernel/intern/action.c61
-rw-r--r--source/blender/blenkernel/intern/anim.c28
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c6
-rw-r--r--source/blender/blenkernel/intern/armature.c34
-rw-r--r--source/blender/blenkernel/intern/armature_update.c70
-rw-r--r--source/blender/blenkernel/intern/blender_user_menu.c1
-rw-r--r--source/blender/blenkernel/intern/brush.c388
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c79
-rw-r--r--source/blender/blenkernel/intern/camera.c25
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/cloth.c4
-rw-r--r--source/blender/blenkernel/intern/collection.c2
-rw-r--r--source/blender/blenkernel/intern/colortools.c19
-rw-r--r--source/blender/blenkernel/intern/constraint.c40
-rw-r--r--source/blender/blenkernel/intern/context.c24
-rw-r--r--source/blender/blenkernel/intern/curve.c10
-rw-r--r--source/blender/blenkernel/intern/deform.c4
-rw-r--r--source/blender/blenkernel/intern/displist.c42
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh.c23
-rw-r--r--source/blender/blenkernel/intern/effect.c4
-rw-r--r--source/blender/blenkernel/intern/font.c6
-rw-r--r--source/blender/blenkernel/intern/gpencil.c1398
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c687
-rw-r--r--source/blender/blenkernel/intern/icons.c44
-rw-r--r--source/blender/blenkernel/intern/ipo.c5
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/lamp.c4
-rw-r--r--source/blender/blenkernel/intern/lattice.c30
-rw-r--r--source/blender/blenkernel/intern/layer.c16
-rw-r--r--source/blender/blenkernel/intern/library.c13
-rw-r--r--source/blender/blenkernel/intern/library_query.c34
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c1
-rw-r--r--source/blender/blenkernel/intern/material.c82
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c24
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c17
-rw-r--r--source/blender/blenkernel/intern/node.c2
-rw-r--r--source/blender/blenkernel/intern/object.c247
-rw-r--r--source/blender/blenkernel/intern/object_deform.c16
-rw-r--r--source/blender/blenkernel/intern/object_update.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c13
-rw-r--r--source/blender/blenkernel/intern/particle_system.c2
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c66
-rw-r--r--source/blender/blenkernel/intern/scene.c121
-rw-r--r--source/blender/blenkernel/intern/screen.c19
-rw-r--r--source/blender/blenkernel/intern/sequencer.c1
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c245
-rw-r--r--source/blender/blenkernel/intern/sound.c22
-rw-r--r--source/blender/blenkernel/intern/studiolight.c44
-rw-r--r--source/blender/blenkernel/intern/subdiv.c114
-rw-r--r--source/blender/blenkernel/intern/subdiv_converter.c65
-rw-r--r--source/blender/blenkernel/intern/subdiv_converter.h57
-rw-r--r--source/blender/blenkernel/intern/subdiv_converter_mesh.c406
-rw-r--r--source/blender/blenkernel/intern/subdiv_eval.c361
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c2432
-rw-r--r--source/blender/blenkernel/intern/subdiv_stats.c84
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c21
-rw-r--r--source/blender/blenkernel/intern/undo_system.c11
-rw-r--r--source/blender/blenkernel/intern/world.c1
-rw-r--r--source/blender/blenlib/BLI_array_utils.h2
-rw-r--r--source/blender/blenlib/BLI_bitmap.h6
-rw-r--r--source/blender/blenlib/BLI_compiler_compat.h6
-rw-r--r--source/blender/blenlib/BLI_hash_mm3.h40
-rw-r--r--source/blender/blenlib/BLI_math_vector.h6
-rw-r--r--source/blender/blenlib/BLI_rand.h3
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_kdtree.c10
-rw-r--r--source/blender/blenlib/intern/hash_mm3.c147
-rw-r--r--source/blender/blenlib/intern/listbase.c3
-rw-r--r--source/blender/blenlib/intern/math_geom.c38
-rw-r--r--source/blender/blenlib/intern/math_vector.c21
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c23
-rw-r--r--source/blender/blenlib/intern/rand.c12
-rw-r--r--source/blender/blenloader/BLO_readfile.h2
-rw-r--r--source/blender/blenloader/BLO_writefile.h2
-rw-r--r--source/blender/blenloader/CMakeLists.txt2
-rw-r--r--source/blender/blenloader/intern/blend_validate.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c316
-rw-r--r--source/blender/blenloader/intern/runtime.c141
-rw-r--r--source/blender/blenloader/intern/versioning_250.c18
-rw-r--r--source/blender/blenloader/intern/versioning_260.c4
-rw-r--r--source/blender/blenloader/intern/versioning_270.c85
-rw-r--r--source/blender/blenloader/intern/versioning_280.c286
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c67
-rw-r--r--source/blender/blenloader/intern/writefile.c127
-rw-r--r--source/blender/bmesh/bmesh_class.h29
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c448
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h21
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h7
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c7
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c385
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h3
-rw-r--r--source/blender/collada/SceneExporter.cpp2
-rw-r--r--source/blender/compositor/CMakeLists.txt5
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.h4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.h4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrderHotspot.h4
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h4
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp4
-rw-r--r--source/blender/compositor/intern/COM_Converter.h4
-rw-r--r--source/blender/compositor/intern/COM_Debug.h4
-rw-r--r--source/blender/compositor/intern/COM_Device.h4
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h4
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h6
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h4
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.h6
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h6
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h6
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h4
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.h4
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h6
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.h4
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.h6
-rw-r--r--source/blender/compositor/nodes/COM_AlphaOverNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BilateralBlurNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BokehImageNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BoxMaskNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_BrightnessNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorBalanceNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorCorrectionNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorRampNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorSpillNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ColorToBWNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_CornerPinNode.h6
-rw-r--r--source/blender/compositor/nodes/COM_CropNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.cpp121
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.h37
-rw-r--r--source/blender/compositor/nodes/COM_DefocusNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DespeckleNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DifferenceMatteNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DilateErodeNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DirectionalBlurNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DisplaceNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_EllipseMaskNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_FlipNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_GammaNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_GlareNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_IDMaskNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_InpaintNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_InvertNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_MapUVNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_MovieDistortionNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_NormalizeNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_PixelateNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_RotateNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ScaleNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SetAlphaNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_Stabilize2dNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SwitchNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_TimeNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_TonemapNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_VectorBlurNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_VectorCurveNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ViewLevelsNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_ZCombineNode.h4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BoxMaskOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BrightnessOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_CalculateMeanOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorCurveOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorRampOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorProfileOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.cpp75
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.h40
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DespeckleOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DotproductOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_EllipseMaskOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GammaCorrectOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GammaOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareThresholdOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_IDMaskOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_InpaintOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_InvertOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MapRangeOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MapValueOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_PixelateOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_QualityStepHelper.h4
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h4
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetSamplerOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.h4
-rw-r--r--source/blender/depsgraph/CMakeLists.txt22
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h12
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.cc15
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc45
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc20
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc143
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc9
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc7
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc9
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc37
-rw-r--r--source/blender/depsgraph/util/deg_util_foreach.h9
-rw-r--r--source/blender/depsgraph/util/deg_util_function.h14
-rw-r--r--source/blender/draw/CMakeLists.txt39
-rw-r--r--source/blender/draw/DRW_engine.h11
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c69
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c23
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c40
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.h2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c36
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c25
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c116
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h12
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c7
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c13
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl23
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl2
-rw-r--r--source/blender/draw/engines/external/external_engine.c6
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c297
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c751
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c1384
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c813
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h361
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c356
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c852
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl60
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl86
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl37
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl70
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl50
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl64
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl98
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl70
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl40
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl12
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl17
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl48
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl15
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl143
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl14
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl9
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl49
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl82
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl37
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl15
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl46
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl208
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl37
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl45
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl181
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl31
-rw-r--r--source/blender/draw/engines/workbench/solid_mode.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c59
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c60
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_aa.c31
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_taa.c16
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c12
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.h2
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c53
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h37
-rw-r--r--source/blender/draw/engines/workbench/workbench_render.c172
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c152
-rw-r--r--source/blender/draw/intern/DRW_render.h60
-rw-r--r--source/blender/draw/intern/draw_anim_viz.c39
-rw-r--r--source/blender/draw/intern/draw_armature.c49
-rw-r--r--source/blender/draw/intern/draw_cache.c1738
-rw-r--r--source/blender/draw/intern/draw_cache.h211
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h112
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c260
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c98
-rw-r--r--source/blender/draw/intern/draw_cache_impl_hair.c118
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c86
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c1167
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c22
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c314
-rw-r--r--source/blender/draw/intern/draw_common.c97
-rw-r--r--source/blender/draw/intern/draw_common.h40
-rw-r--r--source/blender/draw/intern/draw_debug.c82
-rw-r--r--source/blender/draw/intern/draw_debug.h2
-rw-r--r--source/blender/draw/intern/draw_hair.c18
-rw-r--r--source/blender/draw/intern/draw_hair_private.h20
-rw-r--r--source/blender/draw/intern/draw_instance_data.c68
-rw-r--r--source/blender/draw/intern/draw_instance_data.h8
-rw-r--r--source/blender/draw/intern/draw_manager.c365
-rw-r--r--source/blender/draw/intern/draw_manager.h37
-rw-r--r--source/blender/draw/intern/draw_manager_data.c163
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c71
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.c2
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c27
-rw-r--r--source/blender/draw/intern/draw_manager_text.c10
-rw-r--r--source/blender/draw/intern/draw_view.c71
-rw-r--r--source/blender/draw/modes/draw_mode_engines.h1
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c25
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c2
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c2
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c10
-rw-r--r--source/blender/draw/modes/edit_surface_mode.c2
-rw-r--r--source/blender/draw/modes/edit_text_mode.c2
-rw-r--r--source/blender/draw/modes/object_mode.c269
-rw-r--r--source/blender/draw/modes/overlay_mode.c2
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c12
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c7
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c4
-rw-r--r--source/blender/draw/modes/particle_mode.c6
-rw-r--r--source/blender/draw/modes/pose_mode.c14
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl4
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl4
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl4
-rw-r--r--source/blender/draw/modes/shaders/volume_velocity_vert.glsl115
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c25
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c3
-rw-r--r--source/blender/editors/animation/anim_deps.c10
-rw-r--r--source/blender/editors/animation/anim_draw.c26
-rw-r--r--source/blender/editors/animation/anim_filter.c13
-rw-r--r--source/blender/editors/animation/anim_markers.c14
-rw-r--r--source/blender/editors/animation/anim_ops.c10
-rw-r--r--source/blender/editors/animation/keyframes_draw.c29
-rw-r--r--source/blender/editors/animation/keyframes_general.c19
-rw-r--r--source/blender/editors/armature/armature_select.c4
-rw-r--r--source/blender/editors/armature/armature_utils.c2
-rw-r--r--source/blender/editors/armature/pose_edit.c23
-rw-r--r--source/blender/editors/curve/editcurve.c4
-rw-r--r--source/blender/editors/curve/editcurve_paint.c32
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt59
-rw-r--r--source/blender/editors/gizmo_library/CMakeLists.txt1
-rw-r--r--source/blender/editors/gizmo_library/gizmo_draw_utils.c34
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_intern.h10
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_presets.c36
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_utils.c36
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c84
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c154
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c89
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c128
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c290
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c206
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c160
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/grab3d_gizmo.c146
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c68
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt7
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c1066
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c2393
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1069
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c1566
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c248
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c711
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c87
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c1824
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1596
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c1258
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h272
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c71
-rw-r--r--source/blender/editors/gpencil/gpencil_old.c219
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c543
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c1370
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c716
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c301
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c1264
-rw-r--r--source/blender/editors/include/ED_anim_api.h5
-rw-r--r--source/blender/editors/include/ED_datafiles.h63
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h16
-rw-r--r--source/blender/editors/include/ED_gpencil.h189
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h7
-rw-r--r--source/blender/editors/include/ED_object.h36
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_transform.h14
-rw-r--r--source/blender/editors/include/ED_view3d.h4
-rw-r--r--source/blender/editors/include/UI_icons.h24
-rw-r--r--source/blender/editors/include/UI_interface.h18
-rw-r--r--source/blender/editors/include/UI_interface_icons.h2
-rw-r--r--source/blender/editors/interface/interface.c12
-rw-r--r--source/blender/editors/interface/interface_context_menu.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c288
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c1
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c93
-rw-r--r--source/blender/editors/interface/interface_icons.c131
-rw-r--r--source/blender/editors/interface/interface_icons_event.c6
-rw-r--r--source/blender/editors/interface/interface_intern.h11
-rw-r--r--source/blender/editors/interface/interface_layout.c8
-rw-r--r--source/blender/editors/interface/interface_ops.c3
-rw-r--r--source/blender/editors/interface/interface_panel.c42
-rw-r--r--source/blender/editors/interface/interface_query.c14
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c26
-rw-r--r--source/blender/editors/interface/interface_style.c29
-rw-r--r--source/blender/editors/interface/interface_templates.c359
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c183
-rw-r--r--source/blender/editors/interface/resources.c22
-rw-r--r--source/blender/editors/interface/view2d.c26
-rw-r--r--source/blender/editors/interface/view2d_ops.c4
-rw-r--r--source/blender/editors/mask/mask_draw.c54
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c100
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c154
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c110
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c68
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin.c118
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c8
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c86
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c12
-rw-r--r--source/blender/editors/mesh/editmesh_select.c12
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c1360
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c2
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c23
-rw-r--r--source/blender/editors/mesh/mesh_intern.h10
-rw-r--r--source/blender/editors/mesh/mesh_ops.c30
-rw-r--r--source/blender/editors/object/CMakeLists.txt4
-rw-r--r--source/blender/editors/object/object_add.c152
-rw-r--r--source/blender/editors/object/object_bake_api.c24
-rw-r--r--source/blender/editors/object/object_data_transfer.c20
-rw-r--r--source/blender/editors/object/object_edit.c45
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c637
-rw-r--r--source/blender/editors/object/object_group.c11
-rw-r--r--source/blender/editors/object/object_intern.h15
-rw-r--r--source/blender/editors/object/object_modes.c18
-rw-r--r--source/blender/editors/object/object_modifier.c229
-rw-r--r--source/blender/editors/object/object_ops.c39
-rw-r--r--source/blender/editors/object/object_relations.c53
-rw-r--r--source/blender/editors/object/object_select.c5
-rw-r--r--source/blender/editors/object/object_shader_fx.c469
-rw-r--r--source/blender/editors/object/object_shapekey.c6
-rw-r--r--source/blender/editors/object/object_transform.c103
-rw-r--r--source/blender/editors/physics/particle_edit.c2
-rw-r--r--source/blender/editors/render/render_opengl.c98
-rw-r--r--source/blender/editors/render/render_preview.c221
-rw-r--r--source/blender/editors/render/render_shading.c8
-rw-r--r--source/blender/editors/render/render_update.c2
-rw-r--r--source/blender/editors/screen/area.c94
-rw-r--r--source/blender/editors/screen/glutil.c20
-rw-r--r--source/blender/editors/screen/screen_context.c86
-rw-r--r--source/blender/editors/screen/screen_draw.c38
-rw-r--r--source/blender/editors/screen/screen_intern.h2
-rw-r--r--source/blender/editors/screen/screen_ops.c19
-rw-r--r--source/blender/editors/screen/screendump.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c70
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c46
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c2
-rw-r--r--source/blender/editors/sound/sound_ops.c4
-rw-r--r--source/blender/editors/space_action/action_draw.c18
-rw-r--r--source/blender/editors/space_action/action_select.c69
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c44
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c17
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c43
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c18
-rw-r--r--source/blender/editors/space_clip/clip_draw.c144
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c20
-rw-r--r--source/blender/editors/space_clip/clip_utils.c4
-rw-r--r--source/blender/editors/space_clip/space_clip.c20
-rw-r--r--source/blender/editors/space_console/console_draw.c4
-rw-r--r--source/blender/editors/space_console/space_console.c19
-rw-r--r--source/blender/editors/space_file/file_draw.c14
-rw-r--r--source/blender/editors/space_file/file_panels.c33
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c78
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c26
-rw-r--r--source/blender/editors/space_image/image_ops.c8
-rw-r--r--source/blender/editors/space_image/space_image.c22
-rw-r--r--source/blender/editors/space_info/info_stats.c36
-rw-r--r--source/blender/editors/space_info/textview.c12
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c3
-rw-r--r--source/blender/editors/space_nla/nla_channels.c1
-rw-r--r--source/blender/editors/space_nla/nla_draw.c38
-rw-r--r--source/blender/editors/space_node/drawnode.c206
-rw-r--r--source/blender/editors/space_node/node_draw.c40
-rw-r--r--source/blender/editors/space_node/node_edit.c90
-rw-r--r--source/blender/editors/space_node/node_gizmo.c202
-rw-r--r--source/blender/editors/space_node/node_intern.h12
-rw-r--r--source/blender/editors/space_node/node_ops.c3
-rw-r--r--source/blender/editors/space_node/space_node.c47
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c151
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c954
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c904
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c541
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h60
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c388
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c30
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c179
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c190
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c50
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c6
-rw-r--r--source/blender/editors/space_text/space_text.c11
-rw-r--r--source/blender/editors/space_text/text_draw.c22
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c113
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c145
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c66
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c28
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c66
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c180
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c80
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c54
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_lamp.c148
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c140
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c125
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c212
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h28
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c49
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c33
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c68
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c6
-rw-r--r--source/blender/editors/transform/transform.c387
-rw-r--r--source/blender/editors/transform/transform.h6
-rw-r--r--source/blender/editors/transform/transform_constraints.c18
-rw-r--r--source/blender/editors/transform/transform_conversions.c332
-rw-r--r--source/blender/editors/transform/transform_generics.c36
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c28
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c234
-rw-r--r--source/blender/editors/transform/transform_ops.c70
-rw-r--r--source/blender/editors/transform/transform_snap.c8
-rw-r--r--source/blender/editors/transform/transform_snap_object.c203
-rw-r--r--source/blender/editors/undo/ed_undo.c37
-rw-r--r--source/blender/editors/util/ed_util.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c130
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c41
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c1010
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt70
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h51
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c189
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h54
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c558
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c164
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c355
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c360
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c213
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c210
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c285
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c143
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c183
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c123
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c152
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c193
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c171
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c171
-rw-r--r--source/blender/gpu/CMakeLists.txt30
-rw-r--r--source/blender/gpu/GPU_attr_binding.h (renamed from intern/opensubdiv/opensubdiv_gl_mesh.h)30
-rw-r--r--source/blender/gpu/GPU_batch.h178
-rw-r--r--source/blender/gpu/GPU_batch_presets.h12
-rw-r--r--source/blender/gpu/GPU_batch_utils.h6
-rw-r--r--source/blender/gpu/GPU_buffers.h2
-rw-r--r--source/blender/gpu/GPU_common.h (renamed from intern/opensubdiv/opensubdiv_intern.h)51
-rw-r--r--source/blender/gpu/GPU_context.h55
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/GPU_element.h102
-rw-r--r--source/blender/gpu/GPU_extensions.h1
-rw-r--r--source/blender/gpu/GPU_framebuffer.h6
-rw-r--r--source/blender/gpu/GPU_immediate.h112
-rw-r--r--source/blender/gpu/GPU_immediate_util.h11
-rw-r--r--source/blender/gpu/GPU_material.h27
-rw-r--r--source/blender/gpu/GPU_matrix.h92
-rw-r--r--source/blender/gpu/GPU_primitive.h65
-rw-r--r--source/blender/gpu/GPU_shader.h27
-rw-r--r--source/blender/gpu/GPU_shader_interface.h104
-rw-r--r--source/blender/gpu/GPU_state.h2
-rw-r--r--source/blender/gpu/GPU_texture.h11
-rw-r--r--source/blender/gpu/GPU_vertex_buffer.h144
-rw-r--r--source/blender/gpu/GPU_vertex_format.h103
-rw-r--r--source/blender/gpu/intern/gpu_attr_binding.c85
-rw-r--r--source/blender/gpu/intern/gpu_attr_binding_private.h45
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c21
-rw-r--r--source/blender/gpu/intern/gpu_batch.c632
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c76
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.h50
-rw-r--r--source/blender/gpu/intern/gpu_batch_utils.c54
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c200
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c240
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h3
-rw-r--r--source/blender/gpu/intern/gpu_context.cpp329
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h71
-rw-r--r--source/blender/gpu/intern/gpu_draw.c184
-rw-r--r--source/blender/gpu/intern/gpu_element.c311
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c7
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c112
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c848
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c154
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c5
-rw-r--r--source/blender/gpu/intern/gpu_material.c176
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c134
-rw-r--r--source/blender/gpu/intern/gpu_primitive.c84
-rw-r--r--source/blender/gpu/intern/gpu_primitive_private.h (renamed from intern/opensubdiv/opensubdiv_topology_refiner.h)26
-rw-r--r--source/blender/gpu/intern/gpu_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_select.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader.c177
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c368
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h7
-rw-r--r--source/blender/gpu/intern/gpu_state.c9
-rw-r--r--source/blender/gpu/intern/gpu_texture.c118
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c12
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.c272
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c312
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format_private.h39
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl166
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl196
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl33
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl53
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl551
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h5
-rw-r--r--source/blender/imbuf/intern/anim_movie.c34
-rw-r--r--source/blender/imbuf/intern/filetype.c2
-rw-r--r--source/blender/imbuf/intern/jp2.c1253
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_action_types.h6
-rw-r--r--source/blender/makesdna/DNA_brush_types.h109
-rw-r--r--source/blender/makesdna/DNA_color_types.h1
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h415
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h319
-rw-r--r--source/blender/makesdna/DNA_layer_types.h4
-rw-r--r--source/blender/makesdna/DNA_lightprobe_types.h4
-rw-r--r--source/blender/makesdna/DNA_material_types.h78
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h72
-rw-r--r--source/blender/makesdna/DNA_node_types.h13
-rw-r--r--source/blender/makesdna/DNA_object_enums.h5
-rw-r--r--source/blender/makesdna/DNA_object_types.h28
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h4
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h11
-rw-r--r--source/blender/makesdna/DNA_scene_types.h135
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h196
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h3
-rw-r--r--source/blender/makesdna/DNA_sound_types.h12
-rw-r--r--source/blender/makesdna/DNA_space_types.h3
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h9
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h67
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h2
-rw-r--r--source/blender/makesdna/intern/makesdna.c4
-rw-r--r--source/blender/makesrna/RNA_access.h31
-rw-r--r--source/blender/makesrna/RNA_enum_types.h7
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/makesrna.c2
-rw-r--r--source/blender/makesrna/intern/rna_access.c2
-rw-r--r--source/blender/makesrna/intern/rna_brush.c441
-rw-r--r--source/blender/makesrna/intern/rna_camera.c9
-rw-r--r--source/blender/makesrna/intern/rna_context.c5
-rw-r--r--source/blender/makesrna/intern/rna_define.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c1008
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c1340
-rw-r--r--source/blender/makesrna/intern/rna_internal.h7
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c24
-rw-r--r--source/blender/makesrna/intern/rna_layer.c12
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c17
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c28
-rw-r--r--source/blender/makesrna/intern/rna_material.c343
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c4
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c106
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c92
-rw-r--r--source/blender/makesrna/intern/rna_object.c221
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c73
-rw-r--r--source/blender/makesrna/intern/rna_palette.c4
-rw-r--r--source/blender/makesrna/intern/rna_particle.c3
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c102
-rw-r--r--source/blender/makesrna/intern/rna_scene.c525
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c180
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c537
-rw-r--r--source/blender/makesrna/intern/rna_space.c371
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c1
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c26
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c36
-rw-r--r--source/blender/makesrna/intern/rna_wm.c6
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c20
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c393
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo_api.c66
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c6
-rw-r--r--source/blender/makesrna/intern/rna_workspace_api.c49
-rw-r--r--source/blender/makesrna/intern/rna_world.c7
-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_array.c5
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c279
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c72
-rw-r--r--source/blender/modifiers/intern/MOD_util.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c671
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c12
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c13
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c21
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_cryptomatte.c302
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c8
-rw-r--r--source/blender/nodes/shader/node_shader_util.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_blackbody.c7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c132
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c59
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_eevee_specular.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c53
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.c14
-rw-r--r--source/blender/python/CMakeLists.txt2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c7
-rw-r--r--source/blender/python/generic/blf_py_api.c1
-rw-r--r--source/blender/python/generic/idprop_py_api.c10
-rw-r--r--source/blender/python/generic/imbuf_py_api.h2
-rw-r--r--source/blender/python/gpu/CMakeLists.txt (renamed from source/blender/python/gawain/CMakeLists.txt)11
-rw-r--r--source/blender/python/gpu/gpu_py_api.c (renamed from source/blender/python/gawain/gwn_py_api.c)32
-rw-r--r--source/blender/python/gpu/gpu_py_api.h (renamed from source/blender/python/gawain/gwn_py_api.h)12
-rw-r--r--source/blender/python/gpu/gpu_py_types.c (renamed from source/blender/python/gawain/gwn_py_types.c)336
-rw-r--r--source/blender/python/gpu/gpu_py_types.h (renamed from source/blender/python/gawain/gwn_py_types.h)52
-rw-r--r--source/blender/python/intern/bpy_driver.c2
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.c56
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.h4
-rw-r--r--source/blender/python/intern/bpy_interface.c4
-rw-r--r--source/blender/python/intern/bpy_rna.c3
-rw-r--r--source/blender/python/intern/bpy_rna_gizmo.c94
-rw-r--r--source/blender/python/intern/gpu_py_matrix.c40
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c195
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c150
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c182
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/include/render_result.h2
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/source/external_engine.c9
-rw-r--r--source/blender/render/intern/source/pipeline.c18
-rw-r--r--source/blender/shader_fx/CMakeLists.txt64
-rw-r--r--source/blender/shader_fx/FX_shader_types.h47
-rw-r--r--source/blender/shader_fx/intern/FX_shader_blur.c66
-rw-r--r--source/blender/shader_fx/intern/FX_shader_colorize.c69
-rw-r--r--source/blender/shader_fx/intern/FX_shader_flip.c69
-rw-r--r--source/blender/shader_fx/intern/FX_shader_light.c104
-rw-r--r--source/blender/shader_fx/intern/FX_shader_pixel.c66
-rw-r--r--source/blender/shader_fx/intern/FX_shader_rim.c70
-rw-r--r--source/blender/shader_fx/intern/FX_shader_swirl.c103
-rw-r--r--source/blender/shader_fx/intern/FX_shader_util.c55
-rw-r--r--source/blender/shader_fx/intern/FX_shader_util.h (renamed from source/blender/blenloader/BLO_runtime.h)29
-rw-r--r--source/blender/shader_fx/intern/FX_shader_wave.c71
-rw-r--r--source/blender/windowmanager/WM_api.h8
-rw-r--r--source/blender/windowmanager/WM_keymap.h4
-rw-r--r--source/blender/windowmanager/WM_types.h18
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_api.h192
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h6
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo.c352
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c424
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c82
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h38
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c647
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c216
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c80
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_fn.h2
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h20
-rw-r--r--source/blender/windowmanager/intern/wm.c59
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c86
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c128
-rw-r--r--source/blender/windowmanager/intern/wm_files.c18
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c18
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c19
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c19
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c53
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c39
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c24
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c8
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c58
-rw-r--r--source/blender/windowmanager/intern/wm_window.c40
-rw-r--r--source/blender/windowmanager/wm_window.h1
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/creator/creator_args.c10
-rw-r--r--tests/python/bl_pyapi_mathutils.py102
1337 files changed, 80011 insertions, 29582 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2961aafe908..708e5192c19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,11 @@ if(NOT DEFINED CMAKE_BUILD_TYPE_INIT)
set(CMAKE_BUILD_TYPE_INIT "Release")
endif()
+# Omit superfluous "Up-to-date" messages.
+if(NOT DEFINED CMAKE_INSTALL_MESSAGE)
+ set(CMAKE_INSTALL_MESSAGE "LAZY")
+endif()
+
# quiet output for Makefiles, 'make -s' helps too
# set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
@@ -485,26 +490,6 @@ if(WIN32)
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
endif()
-# Experimental support of C11 and C++11
-#
-# We default options to whatever default standard in the current compiler.
-if(APPLE)
- set(_c11_init ON)
- set(_cxx11_init ON)
- set(WITH_C11 ON)
- set(WITH_CXX11 ON)
-elseif(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
- set(_c11_init ON)
-else()
- set(_c11_init OFF)
-endif()
-set(_cxx11_init ON)
-
-option(WITH_C11 "Build with C11 standard enabled, for development use only!" ${_c11_init})
-mark_as_advanced(WITH_C11)
-option(WITH_CXX11 "Build with C++11 standard enabled, for development use only!" ${_cxx11_init})
-mark_as_advanced(WITH_CXX11)
-
# Compiler toolchain
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
@@ -616,12 +601,6 @@ if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE)
)
endif()
-if(NOT WITH_CXX11)
- if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
- message(FATAL_ERROR "WITH_AUDASPACE requires WITH_CXX11")
- endif()
-endif()
-
if(NOT WITH_AUDASPACE)
if(WITH_OPENAL)
message(WARNING "WITH_OPENAL requires WITH_AUDASPACE which is disabled")
@@ -672,11 +651,8 @@ elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
WITH_OPENVDB OR WITH_OPENCOLORIO)
# Keep enabled
else()
- # New dependency graph needs either Boost or C++11 for function bindings.
- if(NOT WITH_CXX11)
- # Enabled but we don't need it
- set(WITH_BOOST OFF)
- endif()
+ # Disable boost if not needed.
+ set(WITH_BOOST OFF)
endif()
# auto enable openimageio for cycles
@@ -733,9 +709,6 @@ if(WITH_BUILDINFO)
endif()
endif()
-TEST_SHARED_PTR_SUPPORT()
-TEST_UNORDERED_MAP_SUPPORT()
-
if(WITH_AUDASPACE)
if(NOT WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_C_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/audaspace/bindings/C" "${CMAKE_BINARY_DIR}/extern/audaspace")
@@ -1292,42 +1265,8 @@ endif()
# Configure Ceres
if(WITH_LIBMV)
- set(CERES_DEFINES)
-
- if(WITH_CXX11)
- # nothing to be done
- elseif(SHARED_PTR_FOUND)
- if(SHARED_PTR_TR1_MEMORY_HEADER)
- list(APPEND CERES_DEFINES -DCERES_TR1_MEMORY_HEADER)
- endif()
- if(SHARED_PTR_TR1_NAMESPACE)
- list(APPEND CERES_DEFINES -DCERES_TR1_SHARED_PTR)
- endif()
- else()
- message(FATAL_ERROR "Ceres: Unable to find shared_ptr.")
- endif()
-
- if(WITH_CXX11)
- list(APPEND CERES_DEFINES -DCERES_STD_UNORDERED_MAP)
- elseif(HAVE_STD_UNORDERED_MAP_HEADER)
- if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
- list(APPEND CERES_DEFINES -DCERES_STD_UNORDERED_MAP)
- else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- list(APPEND CERES_DEFINES -DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
- else()
- list(APPEND CERES_DEFINES -DCERES_NO_UNORDERED_MAP)
- message(STATUS "Ceres: Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
- endif()
- else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- list(APPEND CERES_DEFINES -DCERES_TR1_UNORDERED_MAP)
- else()
- list(APPEND CERES_DEFINES -DCERES_NO_UNORDERED_MAP)
- message(STATUS "Ceres: Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
- endif()
+ # We always have C++11 which includes unordered_map.
+ set(CERES_DEFINES -DCERES_STD_UNORDERED_MAP)
endif()
#-----------------------------------------------------------------------------
@@ -1554,24 +1493,17 @@ if(WITH_PYTHON)
endif()
endif()
-if(WITH_CXX11)
- if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
- # TODO(sergey): Do we want c++11 or gnu-c++11 here?
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- elseif(MSVC)
- # Nothing special is needed, C++11 features are available by default.
- else()
- message(FATAL_ERROR "Compiler ${CMAKE_C_COMPILER_ID} is not supported for C++11 build yet")
- endif()
+if(
+ CMAKE_COMPILER_IS_GNUCC OR
+ CMAKE_C_COMPILER_ID MATCHES "Clang" OR
+ CMAKE_C_COMPILER_ID MATCHES "Intel"
+)
+ # TODO(sergey): Do we want c++11 or gnu-c++11 here?
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+elseif(MSVC)
+ # Nothing special is needed, C++11 features are available by default.
else()
- # GCC-6 switched to C++11 by default, which would break linking with existing libraries
- # by default. So we explicitly disable C++11 for a new GCC so no linking issues happens.
- if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0"))
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++98")
- # We also disable any of C++11 ABI from usage, so we wouldn't even try to
- # link to stuff from std::__cxx11 namespace.
- add_definitions("-D_GLIBCXX_USE_CXX11_ABI=0")
- endif()
+ message(FATAL_ERROR "Unknown compiler ${CMAKE_C_COMPILER_ID}, can't enable C++11 build")
endif()
# Visual Studio has all standards it supports available by default
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index f177560c5f6..1ca102508e1 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -45,6 +45,17 @@ cmake_minimum_required(VERSION 3.5)
include(ExternalProject)
include(cmake/options.cmake)
include(cmake/versions.cmake)
+
+if(ENABLE_MINGW64)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+ include(cmake/setup_mingw64.cmake)
+ else()
+ include(cmake/setup_mingw32.cmake)
+ endif()
+else()
+ set(mingw_LIBDIR ${LIBDIR})
+endif()
+
include(cmake/zlib.cmake)
include(cmake/blendthumb.cmake)
include(cmake/openal.cmake)
@@ -68,6 +79,9 @@ include(cmake/opencollada.cmake)
include(cmake/opencolorio.cmake)
include(cmake/llvm.cmake)
include(cmake/clang.cmake)
+if(APPLE)
+ include(cmake/openmp.cmake)
+endif()
include(cmake/openimageio.cmake)
include(cmake/tiff.cmake)
include(cmake/flexbison.cmake)
@@ -77,6 +91,7 @@ include(cmake/openvdb.cmake)
include(cmake/python.cmake)
include(cmake/python_site_packages.cmake)
include(cmake/numpy.cmake)
+
if(WITH_WEBP)
include(cmake/webp.cmake)
endif()
@@ -84,16 +99,6 @@ if(WIN32)
include(cmake/hidapi.cmake)
endif()
-if(ENABLE_MINGW64)
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
- include(cmake/setup_mingw64.cmake)
- else()
- include(cmake/setup_mingw32.cmake)
- endif()
-else()
- set(mingw_LIBDIR ${LIBDIR})
-endif()
-
if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/openjpeg.cmake)
if(BUILD_MODE STREQUAL Release)
@@ -105,8 +110,6 @@ if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/vorbis.cmake)
include(cmake/theora.cmake)
include(cmake/vpx.cmake)
- include(cmake/orc.cmake)
- include(cmake/schroedinger.cmake)
include(cmake/x264.cmake)
include(cmake/xvidcore.cmake)
include(cmake/faad.cmake)
diff --git a/build_files/build_environment/cmake/blosc.cmake b/build_files/build_environment/cmake/blosc.cmake
index 606fe8c61cc..9a5ef745985 100644
--- a/build_files/build_environment/cmake/blosc.cmake
+++ b/build_files/build_environment/cmake/blosc.cmake
@@ -25,6 +25,7 @@ set(BLOSC_EXTRA_ARGS
-DThreads_FOUND=1
-DPTHREAD_LIBS=${LIBDIR}/pthreads/lib/pthreadVC2.lib
-DPTHREAD_INCLUDE_DIR=${LIBDIR}/pthreads/inc
+ -DDEACTIVATE_SNAPPY=ON
)
ExternalProject_Add(external_blosc
diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake
index 46840b7ead4..9be6ea9f011 100644
--- a/build_files/build_environment/cmake/boost.cmake
+++ b/build_files/build_environment/cmake/boost.cmake
@@ -26,15 +26,9 @@ if(WIN32)
set(PYTHON_ARCH2 win32)
set(PYTHON_OUTPUTDIR ${BUILD_DIR}/python/src/external_python/pcbuild/win32/)
endif()
- if(MSVC12)
- set(BOOST_TOOLSET toolset=msvc-12.0)
- set(BOOST_COMPILER_STRING -vc120)
- set(PYTHON_COMPILER_STRING v120)
- endif()
if(MSVC14)
set(BOOST_TOOLSET toolset=msvc-14.0)
set(BOOST_COMPILER_STRING -vc140)
- set(PYTHON_COMPILER_STRING v140)
endif()
set(JAM_FILE ${BUILD_DIR}/boost/src/external_boost/user-config.jam)
set(semi_path "${PATCH_DIR}/semi.txt")
@@ -53,18 +47,17 @@ if(WIN32)
if(BUILD_MODE STREQUAL Release)
set(BOOST_HARVEST_CMD ${BOOST_HARVEST_CMD} && ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/include/boost-1_60/ ${HARVEST_TARGET}/boost/include/)
endif()
- set(BOOST_PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/boost/src/external_boost < ${PATCH_DIR}/boost.diff)
elseif(APPLE)
set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh)
- set(BOOST_BUILD_COMMAND ./bjam)
- set(BOOST_BUILD_OPTIONS toolset=clang cxxflags=${PLATFORM_CXXFLAGS} linkflags=${PLATFORM_LDFLAGS} --disable-icu boost.locale.icu=off)
+ set(BOOST_BUILD_COMMAND ./b2)
+ set(BOOST_BUILD_OPTIONS toolset=darwin cxxflags=${PLATFORM_CXXFLAGS} linkflags=${PLATFORM_LDFLAGS} --disable-icu boost.locale.icu=off)
set(BOOST_HARVEST_CMD echo .)
set(BOOST_PATCH_COMMAND echo .)
else()
set(BOOST_HARVEST_CMD echo .)
set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh)
- set(BOOST_BUILD_COMMAND ./bjam)
+ set(BOOST_BUILD_COMMAND ./b2)
set(BOOST_BUILD_OPTIONS cxxflags=${PLATFORM_CXXFLAGS} --disable-icu boost.locale.icu=off)
set(BOOST_PATCH_COMMAND echo .)
endif()
@@ -85,23 +78,20 @@ set(BOOST_OPTIONS
${BOOST_TOOLSET}
)
-if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(BOOST_ADDRESS_MODEL 64)
-else()
- set(BOOST_ADDRESS_MODEL 32)
-endif()
+
string(TOLOWER ${BUILD_MODE} BOOST_BUILD_TYPE)
ExternalProject_Add(external_boost
URL ${BOOST_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH MD5=${BOOST_MD5}
+ URL_HASH MD5=${BOOST_HASH}
PREFIX ${BUILD_DIR}/boost
UPDATE_COMMAND ""
PATCH_COMMAND ${BOOST_PATCH_COMMAND}
CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND}
- BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=x86 address-model=${BOOST_ADDRESS_MODEL} variant=${BOOST_BUILD_TYPE} link=static threading=multi ${BOOST_OPTIONS} --prefix=${LIBDIR}/boost install
+ BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=x86 address-model=${BOOST_ADDRESS_MODEL} link=static threading=multi ${BOOST_OPTIONS} --prefix=${LIBDIR}/boost install
BUILD_IN_SOURCE 1
INSTALL_COMMAND "${BOOST_HARVEST_CMD}"
)
diff --git a/build_files/build_environment/cmake/clang.cmake b/build_files/build_environment/cmake/clang.cmake
index 9a2705bc8be..699c38a293a 100644
--- a/build_files/build_environment/cmake/clang.cmake
+++ b/build_files/build_environment/cmake/clang.cmake
@@ -21,13 +21,22 @@ set(CLANG_EXTRA_ARGS
-DCLANG_PATH_TO_LLVM_BUILD=${LIBDIR}/llvm
-DLLVM_USE_CRT_RELEASE=MT
-DLLVM_USE_CRT_DEBUG=MTd
+ -DLLVM_CONFIG=${LIBDIR}/llvm/bin/llvm-config
)
+
+if(WIN32)
+ set(CLANG_GENERATOR "Ninja")
+else()
+ set(CLANG_GENERATOR "Unix Makefiles")
+endif()
+
+
ExternalProject_Add(external_clang
URL ${CLANG_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${CLANG_HASH}
- PATCH_COMMAND ${PATCH_CMD} -p 2 -N -R -d ${BUILD_DIR}/clang/src/external_clang < ${PATCH_DIR}/clang.diff
PREFIX ${BUILD_DIR}/clang
+ CMAKE_GENERATOR ${CLANG_GENERATOR}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/clang ${DEFAULT_CMAKE_FLAGS} ${CLANG_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/clang
)
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
index 3ea1b282d9a..42504e8120b 100644
--- a/build_files/build_environment/cmake/ffmpeg.cmake
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -16,10 +16,10 @@
#
# ***** END GPL LICENSE BLOCK *****
-set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/dirac/include/dirac -I${mingw_LIBDIR}/schroedinger/include/schroedinger-1.0 -I${mingw_LIBDIR}/zlib/include")
-set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/dirac/lib -L${mingw_LIBDIR}/schroedinger/lib -L${mingw_LIBDIR}/orc/lib -L${mingw_LIBDIR}/zlib/lib")
+set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/zlib/include")
+set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/zlib/lib")
set(FFMPEG_EXTRA_FLAGS --extra-cflags=${FFMPEG_CFLAGS} --extra-ldflags=${FFMPEG_LDFLAGS})
-set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/schroedinger/lib/pkgconfig:${mingw_LIBDIR}/orc/lib/pkgconfig:${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR})
+set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR}/vorbis/lib/pkgconfig:${mingw_LIBDIR}/ogg/lib/pkgconfig:${mingw_LIBDIR})
if(WIN32)
set(FFMPEG_ENV set ${FFMPEG_ENV} &&)
@@ -63,7 +63,6 @@ ExternalProject_Add(external_ffmpeg
--disable-libspeex
--enable-libvpx
--prefix=${LIBDIR}/ffmpeg
- --enable-libschroedinger
--enable-libtheora
--enable-libvorbis
--enable-zlib
@@ -73,7 +72,6 @@ ExternalProject_Add(external_ffmpeg
--disable-nonfree
--enable-gpl
--disable-postproc
- --disable-x11grab
--enable-libmp3lame
--disable-librtmp
--enable-libx264
@@ -91,7 +89,7 @@ ExternalProject_Add(external_ffmpeg
--disable-securetransport
--disable-indev=avfoundation
--disable-indev=qtkit
- --disable-sdl
+ --disable-sdl2
--disable-gnutls
--disable-vda
--disable-videotoolbox
@@ -122,7 +120,6 @@ add_dependencies(
external_openjpeg
external_xvidcore
external_x264
- external_schroedinger
external_vpx
external_theora
external_vorbis
diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake
index 751b2b1f383..1034e9f2029 100644
--- a/build_files/build_environment/cmake/freetype.cmake
+++ b/build_files/build_environment/cmake/freetype.cmake
@@ -16,7 +16,15 @@
#
# ***** END GPL LICENSE BLOCK *****
-set(FREETYPE_EXTRA_ARGS -DCMAKE_RELEASE_POSTFIX:STRING=2ST -DCMAKE_DEBUG_POSTFIX:STRING=2ST_d -DWITH_BZip2=OFF -DWITH_HarfBuzz=OFF)
+set(FREETYPE_EXTRA_ARGS
+ -DCMAKE_RELEASE_POSTFIX:STRING=2ST
+ -DCMAKE_DEBUG_POSTFIX:STRING=2ST_d
+ -DWITH_BZip2=OFF
+ -DWITH_HarfBuzz=OFF
+ -DFT_WITH_HARFBUZZ=OFF
+ -DFT_WITH_BZIP2=OFF
+ -DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
+ -DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE)
ExternalProject_Add(external_freetype
URL ${FREETYPE_URI}
@@ -24,5 +32,13 @@ ExternalProject_Add(external_freetype
URL_HASH MD5=${FREETYPE_HASH}
PREFIX ${BUILD_DIR}/freetype
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/freetype ${DEFAULT_CMAKE_FLAGS} ${FREETYPE_EXTRA_ARGS}
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/freetype/src/external_freetype < ${PATCH_DIR}/freetype.diff
INSTALL_DIR ${LIBDIR}/freetype
)
+
+if(BUILD_MODE STREQUAL Release AND WIN32)
+ ExternalProject_Add_Step(external_freetype after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
index 9ebd5206d27..4bbe01974f6 100644
--- a/build_files/build_environment/cmake/harvest.cmake
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -35,8 +35,6 @@ if(BUILD_MODE STREQUAL Release)
# jpeg rename libfile + copy include
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
- # FreeType, straight up copy
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype &&
# pthreads, rename include dir
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/inc/ ${HARVEST_TARGET}/pthreads/include/ &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/lib/ ${HARVEST_TARGET}/pthreads/lib &&
@@ -98,17 +96,11 @@ if(BUILD_MODE STREQUAL Release)
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/ ${HARVEST_TARGET}/opencollada/ &&
# opensubdiv
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opensubdiv ${HARVEST_TARGET}/opensubdiv &&
- # python
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/python/ ${HARVEST_TARGET}/python/ &&
# alembic
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/alembic ${HARVEST_TARGET}/alembic &&
# BlendThumb
${CMAKE_COMMAND} -E copy ${LIBDIR}/BlendThumb64/bin/blendthumb.dll ${HARVEST_TARGET}/ThumbHandler/lib/BlendThumb64.dll &&
${CMAKE_COMMAND} -E copy ${LIBDIR}/BlendThumb32/bin/blendthumb.dll ${HARVEST_TARGET}/ThumbHandler/lib/BlendThumb.dll &&
- # python
- ${CMAKE_COMMAND} -E copy ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}.tar.gz ${HARVEST_TARGET}/Release/python${PYTHON_SHORT_VERSION_NO_DOTS}.tar.gz &&
- # numpy
- ${CMAKE_COMMAND} -E copy ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}_numpy_${NUMPY_SHORT_VERSION}.tar.gz ${HARVEST_TARGET}/Release/python${PYTHON_SHORT_VERSION_NO_DOTS}_numpy_${NUMPY_SHORT_VERSION}.tar.gz &&
# hidapi
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hidapi/ ${HARVEST_TARGET}/hidapi/ &&
# webp, straight up copy
@@ -238,13 +230,12 @@ harvest(openimageio/bin openimageio/bin "maketx")
harvest(openimageio/bin openimageio/bin "oiiotool")
harvest(openimageio/include openimageio/include "*")
harvest(openimageio/lib openimageio/lib "*.a")
-harvest(openjpeg/include/openjpeg-1.5 openjpeg/include "*.h")
+harvest(openjpeg/include/openjpeg-2.3 openjpeg/include "*.h")
harvest(openjpeg/lib openjpeg/lib "*.a")
harvest(opensubdiv/include opensubdiv/include "*.h")
harvest(opensubdiv/lib opensubdiv/lib "*.a")
harvest(openvdb/include/openvdb/openvdb openvdb/include/openvdb "*.h")
harvest(openvdb/lib openvdb/lib "*.a")
-harvest(orc/lib/liborc-0.4.a ffmpeg/lib/liborc.a)
harvest(osl/bin osl/bin "oslc")
harvest(osl/include osl/include "*.h")
harvest(osl/lib osl/lib "*.a")
@@ -254,7 +245,6 @@ harvest(png/lib png/lib "*.a")
harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}m")
harvest(python/include python/include "*h")
harvest(python/lib python/lib "*")
-harvest(schroedinger/lib/libschroedinger-1.0.a ffmpeg/lib/libschroedinger.a)
harvest(sdl/include/SDL2 sdl/include "*.h")
harvest(sdl/lib sdl/lib "libSDL2.a")
harvest(sndfile/include sndfile/include "*.h")
diff --git a/build_files/build_environment/cmake/jpeg.cmake b/build_files/build_environment/cmake/jpeg.cmake
index 1f2b04387f0..9975bb9c4f6 100644
--- a/build_files/build_environment/cmake/jpeg.cmake
+++ b/build_files/build_environment/cmake/jpeg.cmake
@@ -18,7 +18,7 @@
if(WIN32)
# cmake for windows
- set(JPEG_EXTRA_ARGS -DWITH_JPEG8=ON -DCMAKE_DEBUG_POSTFIX=d)
+ set(JPEG_EXTRA_ARGS -DNASM=${NASM_PATH} -DWITH_JPEG8=ON -DCMAKE_DEBUG_POSTFIX=d)
ExternalProject_Add(external_jpeg
URL ${JPEG_URI}
diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake
index 6c59101f543..7390b1bf011 100644
--- a/build_files/build_environment/cmake/llvm.cmake
+++ b/build_files/build_environment/cmake/llvm.cmake
@@ -26,7 +26,7 @@ set(LLVM_EXTRA_ARGS
)
if(WIN32)
- set(LLVM_GENERATOR "NMake Makefiles")
+ set(LLVM_GENERATOR "Ninja")
else()
set(LLVM_GENERATOR "Unix Makefiles")
endif()
@@ -38,7 +38,6 @@ ExternalProject_Add(ll
URL_HASH MD5=${LLVM_HASH}
CMAKE_GENERATOR ${LLVM_GENERATOR}
PREFIX ${BUILD_DIR}/ll
- PATCH_COMMAND ${PATCH_CMD} -p 0 -d ${BUILD_DIR}/ll/src/ll < ${PATCH_DIR}/llvm-alloca-fix.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/llvm ${DEFAULT_CMAKE_FLAGS} ${LLVM_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/llvm
)
diff --git a/build_files/build_environment/cmake/numpy.cmake b/build_files/build_environment/cmake/numpy.cmake
index 0d5d8abf7ab..fa8d9ebccba 100644
--- a/build_files/build_environment/cmake/numpy.cmake
+++ b/build_files/build_environment/cmake/numpy.cmake
@@ -36,7 +36,6 @@ if(WIN32)
${CMAKE_COMMAND} -E chdir "${BUILD_DIR}/numpy/src/external_numpy/build/lib.${PYTHON_ARCH2}-${PYTHON_SHORT_VERSION}${NUMPY_DIR_POSTFIX}"
${CMAKE_COMMAND} -E tar "cfvz" "${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}_numpy_${NUMPY_SHORT_VERSION}${NUMPY_ARCHIVE_POSTFIX}.tar.gz" "."
)
- set(NUMPY_PATCH ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/numpy/src/external_numpy < ${PATCH_DIR}/numpy.diff )
else()
set(NUMPY_INSTALL echo .)
set(NUMPY_PATCH echo .)
@@ -54,6 +53,13 @@ ExternalProject_Add(external_numpy
INSTALL_COMMAND ${NUMPY_INSTALL}
)
+if(WIN32)
+ ExternalProject_Add_Step(external_numpy after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}_numpy_${NUMPY_SHORT_VERSION}.tar.gz ${HARVEST_TARGET}/Release/python${PYTHON_SHORT_VERSION_NO_DOTS}_numpy_${NUMPY_SHORT_VERSION}.tar.gz
+ DEPENDEES install
+ )
+endif()
+
add_dependencies(
external_numpy
Make_Python_Environment
diff --git a/build_files/build_environment/cmake/openimageio.cmake b/build_files/build_environment/cmake/openimageio.cmake
index fdc71508e47..5e7449fe079 100644
--- a/build_files/build_environment/cmake/openimageio.cmake
+++ b/build_files/build_environment/cmake/openimageio.cmake
@@ -51,8 +51,8 @@ if(MSVC)
set(OPENJPEG_FLAGS
-DOPENJPEG_HOME=${LIBDIR}/openjpeg_msvc
-DOPENJPEG_INCLUDE_DIR=${LIBDIR}/openjpeg_msvc/include/openjpeg-${OPENJPEG_SHORT_VERSION}
- -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg_msvc/lib/openjpeg${LIBEXT}
- -DOPENJPEG_LIBRARY_DEBUG=${LIBDIR}/openjpeg_msvc/lib/openjpeg${LIBEXT}
+ -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT}
+ -DOPENJPEG_LIBRARY_DEBUG=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT}
)
else()
set(OPENJPEG_FLAGS
diff --git a/build_files/build_environment/cmake/openjpeg.cmake b/build_files/build_environment/cmake/openjpeg.cmake
index 5cc49b1e519..df30783de40 100644
--- a/build_files/build_environment/cmake/openjpeg.cmake
+++ b/build_files/build_environment/cmake/openjpeg.cmake
@@ -58,7 +58,7 @@ if(MSVC)
endif()
endif()
-set(OPENJPEG_LIBRARY libopenjpeg${LIBEXT})
+set(OPENJPEG_LIBRARY libopenjp2${LIBEXT})
if(MSVC)
set_target_properties(external_openjpeg PROPERTIES FOLDER Mingw)
endif()
diff --git a/build_files/build_environment/cmake/orc.cmake b/build_files/build_environment/cmake/openmp.cmake
index aac7884f49e..ba8e6248126 100644
--- a/build_files/build_environment/cmake/orc.cmake
+++ b/build_files/build_environment/cmake/openmp.cmake
@@ -16,17 +16,17 @@
#
# ***** END GPL LICENSE BLOCK *****
-ExternalProject_Add(external_orc
- URL ${ORC_URI}
+
+ExternalProject_Add(external_openmp
+ URL ${OPENMP_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH SHA256=${ORC_HASH}
- PREFIX ${BUILD_DIR}/orc
- CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/orc --disable-shared --enable-static
- BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && make -j${MAKE_THREADS}
- INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/orc/src/external_orc/ && make install
- INSTALL_DIR ${LIBDIR}/orc
+ URL_HASH MD5=${OPENMP_HASH}
+ PREFIX ${BUILD_DIR}/openmp
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openmp ${DEFAULT_CMAKE_FLAGS}
+ INSTALL_DIR ${LIBDIR}/clang
)
-if(MSVC)
- set_target_properties(external_orc PROPERTIES FOLDER Mingw)
-endif()
+add_dependencies(
+ external_openmp
+ external_clang
+)
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index 08d43d6a0a2..c4dcf212e68 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -126,7 +126,7 @@ else()
)
set(OSX_ARCHITECTURES x86_64)
set(OSX_DEPLOYMENT_TARGET 10.9)
- set(OSX_SDK_VERSION 10.12)
+ set(OSX_SDK_VERSION 10.13)
set(OSX_SYSROOT ${XCODE_DEV_PATH}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OSX_SDK_VERSION}.sdk)
set(PLATFORM_CFLAGS "-isysroot ${OSX_SYSROOT} -mmacosx-version-min=${OSX_DEPLOYMENT_TARGET}")
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
index 693ab1896ba..7de498bc126 100644
--- a/build_files/build_environment/cmake/python.cmake
+++ b/build_files/build_environment/cmake/python.cmake
@@ -46,13 +46,12 @@ if(WIN32)
PREFIX ${BUILD_DIR}/python
PATCH_COMMAND
echo mklink /D "${PYTHON_EXTERNALS_FOLDER_DOS}" "${DOWNLOADS_EXTERNALS_FOLDER_DOS}" &&
- mklink /D "${PYTHON_EXTERNALS_FOLDER_DOS}" "${DOWNLOADS_EXTERNALS_FOLDER_DOS}" &&
- ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python.diff &&
- ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python/pc < ${PATCH_DIR}/pyshell.diff
+ mklink /D "${PYTHON_EXTERNALS_FOLDER_DOS}" "${DOWNLOADS_EXTERNALS_FOLDER_DOS}"
CONFIGURE_COMMAND ""
- BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p ${PYTHON_ARCH} -c ${BUILD_MODE} -k ${PYTHON_COMPILER_STRING}
+ BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p ${PYTHON_ARCH} -c ${BUILD_MODE}
INSTALL_COMMAND COMMAND
${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.dll ${LIBDIR}/python/lib/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.dll &&
+ ${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.pdb ${LIBDIR}/python/lib/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.pdb &&
${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib ${LIBDIR}/python/lib/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib &&
${CMAKE_COMMAND} -E copy ${PYTHON_OUTPUTDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.exp ${LIBDIR}/python/lib/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.exp &&
${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/include ${LIBDIR}/python/include/Python${PYTHON_SHORT_VERSION} &&
@@ -62,12 +61,27 @@ if(WIN32)
message("POutput = ${PYTHON_OUTPUTDIR}")
else()
if(APPLE)
- # we need to manually add homebrew headers to get ssl module building
- set(PYTHON_CFLAGS "-I/usr/local/opt/openssl/include -I${OSX_SYSROOT}/usr/include ${PLATFORM_CFLAGS}")
- set(PYTHON_LDFLAGS "-L/usr/local/opt/openssl/lib ${PLATFORM_LDFLAGS}")
- set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV} && export CFLAGS=${PYTHON_CFLAGS} && export LDFLAGS=${PYTHON_LDFLAGS})
+ # we need to add homebrew pkgconfig directories to get ssl, xz
+
+ set(BREW_PKG_CONFIG "/usr/local/opt/openssl/lib/pkgconfig:/usr/local/opt/xz/lib/pkgconfig")
+ # disable functions that can be in 10.13 sdk but aren't available on 10.9 target
+ set(PYTHON_FUNC_CONFIGS
+ export ac_cv_func_futimens=no &&
+ export ac_cv_func_utimensat=no &&
+ export ac_cv_func_basename_r=no &&
+ export ac_cv_func_clock_getres=no &&
+ export ac_cv_func_clock_gettime=no &&
+ export ac_cv_func_clock_settime=no &&
+ export ac_cv_func_dirname_r=no &&
+ export ac_cv_func_getentropy=no &&
+ export ac_cv_func_mkostemp=no &&
+ export ac_cv_func_mkostemps=no &&
+ export ac_cv_func_timingsafe_bcmp=no)
+
+ set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV} && export PKG_CONFIG_PATH=${BREW_PKG_CONFIG} && ${PYTHON_FUNC_CONFIGS})
set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python.exe)
- set(PYTHON_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_apple.diff)
+ #set(PYTHON_PATCH ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_apple.diff)
+ set(PYTHON_PATCH echo .)
else()
set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV})
set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python)
@@ -92,39 +106,40 @@ if(MSVC)
OUTPUT ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.tar.gz
OUTPUT ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe
COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/lib ${BUILD_DIR}/python/src/external_python/redist/lib
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_POSTFIX}.exe" ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_asyncio${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_asyncio${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_bz2${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_bz2${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_hashlib${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_hashlib${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_lzma${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_lzma${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_sqlite3${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_sqlite3${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ssl${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ssl${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/pyexpat${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/pyexpat${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/select${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/select${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/unicodedata${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/unicodedata${PYTHON_POSTFIX}.pyd
- COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/winsound${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/winsound${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_contextvars${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_contextvars${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ctypes${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ctypes${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ctypes_test${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ctypes_test${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_decimal${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_decimal${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_distutils_findvs${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_distutils_findvs${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_elementtree${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_elementtree${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_hashlib${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_hashlib${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_lzma${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_lzma${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_msi${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_msi${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_multiprocessing${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_multiprocessing${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_overlapped${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_overlapped${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_queue${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_queue${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_socket${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_socket${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_sqlite3${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_sqlite3${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_ssl${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_ssl${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testbuffer${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testbuffer${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testcapi${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testcapi${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testimportmultiple${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testimportmultiple${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/_testmultiphase${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/_testmultiphase${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/pyexpat${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/pyexpat${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_POSTFIX}.exe" ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/select${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/select${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/unicodedata${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/unicodedata${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/winsound${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/winsound${PYTHON_POSTFIX}.pyd
+ COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/xxlimited${PYTHON_POSTFIX}.pyd" ${BUILD_DIR}/python/src/external_python/redist/lib/xxlimited${PYTHON_POSTFIX}.pyd
COMMAND ${CMAKE_COMMAND} -E chdir "${BUILD_DIR}/python/src/external_python/redist" ${CMAKE_COMMAND} -E tar "cfvz" "${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.tar.gz" "."
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/python/ ${HARVEST_TARGET}/python/
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}.tar.gz ${HARVEST_TARGET}/Release/python${PYTHON_SHORT_VERSION_NO_DOTS}.tar.gz
)
add_custom_target(Package_Python ALL DEPENDS external_python ${LIBDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.tar.gz ${BUILD_DIR}/python/src/external_python/redist/bin/python${PYTHON_POSTFIX}.exe)
- if(MSVC12)
- set(PYTHON_DISTUTIL_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/python/src/external_python/run/lib/distutils < ${PATCH_DIR}/python_runtime_vc2013.diff)
- else()
- set(PYTHON_DISTUTIL_PATCH echo "No patch needed")
- endif()
-
add_custom_command(OUTPUT ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe
COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/redist ${BUILD_DIR}/python/src/external_python/run
COMMAND ${CMAKE_COMMAND} -E copy_directory ${BUILD_DIR}/python/src/external_python/include ${BUILD_DIR}/python/src/external_python/run/include
@@ -134,7 +149,6 @@ if(MSVC)
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib" ${BUILD_DIR}/python/src/external_python/run/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}.lib #other things like numpy still want it though.
COMMAND ${CMAKE_COMMAND} -E copy "${PYTHON_OUTPUTDIR}/python${PYTHON_POSTFIX}.exe" ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe
COMMAND ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe -m ensurepip --upgrade
- COMMAND ${PYTHON_DISTUTIL_PATCH}
)
add_custom_target(Make_Python_Environment ALL DEPENDS ${BUILD_DIR}/python/src/external_python/run/python${PYTHON_POSTFIX}.exe Package_Python)
endif()
diff --git a/build_files/build_environment/cmake/schroedinger.cmake b/build_files/build_environment/cmake/schroedinger.cmake
deleted file mode 100644
index 80bf84b06d7..00000000000
--- a/build_files/build_environment/cmake/schroedinger.cmake
+++ /dev/null
@@ -1,48 +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 *****
-
-if(WIN32)
- set(SCHROEDINGER_EXTRA_FLAGS "CFLAGS=-g -I./ -I${LIBDIR}/orc/include/orc-0.4" "LDFLAGS=-Wl,--as-needed -static-libgcc -L${LIBDIR}/orc/lib" ORC_CFLAGS=-I${LIBDIR}/orc/include/orc-0.4 ORC_LDFLAGS=-L${LIBDIR}/orc/lib ORC_LIBS=${LIBDIR}/orc/lib/liborc-0.4.a ORCC=${LIBDIR}/orc/bin/orcc.exe)
-else()
- set(SCHROEDINGER_CFLAGS "${PLATFORM_CFLAGS} -I./ -I${LIBDIR}/orc/include/orc-0.4")
- set(SCHROEDINGER_LDFLAGS "${PLATFORM_LDFLAGS} -L${LIBDIR}/orc/lib")
- set(SCHROEDINGER_EXTRA_FLAGS CFLAGS=${SCHROEDINGER_CFLAGS} LDFLAGS=${SCHROEDINGER_LDFLAGS} ORC_CFLAGS=-I${LIBDIR}/orc/include/orc-0.4 ORC_LDFLAGS=-L${LIBDIR}/orc/lib ORCC=${LIBDIR}/orc/bin/orcc) # ORC_LIBS=${LIBDIR}/orc/lib/liborc-0.4.a
-endif()
-
-ExternalProject_Add(external_schroedinger
- URL ${SCHROEDINGER_URI}
- DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH SHA256=${SCHROEDINGER_HASH}
- PREFIX ${BUILD_DIR}/schroedinger
- PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/schroedinger/src/external_schroedinger < ${PATCH_DIR}/schroedinger.diff
- CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
- cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ &&
- ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/schroedinger --disable-shared --enable-static ${SCHROEDINGER_EXTRA_FLAGS}
- BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ && make -j${MAKE_THREADS}
- INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/schroedinger/src/external_schroedinger/ && make install
- INSTALL_DIR ${LIBDIR}/schroedinger
-)
-
-add_dependencies(
- external_schroedinger
- external_orc
-)
-
-if(MSVC)
- set_target_properties(external_schroedinger PROPERTIES FOLDER Mingw)
-endif()
diff --git a/build_files/build_environment/cmake/setup_mingw32.cmake b/build_files/build_environment/cmake/setup_mingw32.cmake
index 96221bb5e10..b3df59f93c8 100644
--- a/build_files/build_environment/cmake/setup_mingw32.cmake
+++ b/build_files/build_environment/cmake/setup_mingw32.cmake
@@ -78,24 +78,24 @@ if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/pkg-config.exe") AND (EXISTS "
endif()
message("Checking for nasm")
-if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip")
+if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip")
message("Downloading nasm")
- file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win32/nasm-2.12.01-win32.zip" "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip")
+ file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.13.02/win32/nasm-2.13.02-win32.zip" "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip")
endif()
# extract nasm
-if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip"))
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip"))
message("Extracting nasm")
execute_process(
- COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.12.01-win32.zip"
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip"
WORKING_DIRECTORY ${DOWNLOAD_DIR}/
)
execute_process(
- COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.12.01/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe"
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.13.02/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe"
)
endif()
-
+SET(NASM_PATH ${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe)
message("Checking for mingwGet")
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
message("Downloading mingw-get")
diff --git a/build_files/build_environment/cmake/setup_mingw64.cmake b/build_files/build_environment/cmake/setup_mingw64.cmake
index 9a45051ebf6..fbc0c91404c 100644
--- a/build_files/build_environment/cmake/setup_mingw64.cmake
+++ b/build_files/build_environment/cmake/setup_mingw64.cmake
@@ -78,23 +78,24 @@ if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/pkg-config.exe") AND (EXISTS "
endif()
message("Checking for nasm")
-if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip")
+if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win64.zip")
message("Downloading nasm")
- file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip" "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip")
+ file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.13.02/win64/nasm-2.13.02-win64.zip" "${DOWNLOAD_DIR}/nasm-2.13.02-win64.zip")
endif()
# extract nasm
-if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip"))
+if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win64.zip"))
message("Extracting nasm")
execute_process(
- COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.12.01-win64.zip"
+ COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.13.02-win64.zip"
WORKING_DIRECTORY ${DOWNLOAD_DIR}/
)
execute_process(
- COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.12.01/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe"
+ COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.13.02/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe"
)
endif()
+SET(NASM_PATH ${DOWNLOAD_DIR}/mingw/mingw64/bin/nasm.exe)
message("Checking for mingwGet")
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index 361787fa956..eac8e94b539 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -24,19 +24,19 @@ set(OPENAL_VERSION 1.17.2)
set(OPENAL_URI http://kcat.strangesoft.net/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
set(OPENAL_HASH 1764e0d8fec499589b47ebc724e0913d)
-set(PNG_VERSION 1.6.21)
-set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.gz)
-set(PNG_HASH aca36ec8e0a3b406a5912243bc243717)
+set(PNG_VERSION 1.6.35)
+set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.xz)
+set(PNG_HASH 678b7e696a62a193ed3503b04bf449d6)
-set(JPEG_VERSION 1.4.2)
+set(JPEG_VERSION 1.5.3)
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
-set(JPEG_HASH f9804884c1c41eb7f4febb9353a2cb27)
-
-set(BOOST_VERSION 1.60.0)
-set(BOOST_VERSION_NODOTS 1_60_0)
-set(BOOST_URI http://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/boost_${BOOST_VERSION_NODOTS}.tar.bz2/download)
-set(BOOST_MD5 65a840e1a0b13a558ff19eeb2c4f0cbe)
+set(JPEG_HASH 5b7549d440b86c98a517355c102d155e)
+set(BOOST_VERSION 1.68.0)
+set(BOOST_VERSION_NODOTS 1_68_0)
+set(BOOST_URI https://dl.bintray.com/boostorg/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_NODOTS}.tar.gz)
+set(BOOST_HASH 5d8b4503582fffa9eefdb9045359c239)
+
set(BLOSC_VERSION 1.7.1)
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.zip)
set(BLOSC_HASH ff5cc729a5a25934ef714217218eed26)
@@ -45,17 +45,17 @@ set(PTHREADS_VERSION 2-9-1)
set(PTHREADS_URI ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-${PTHREADS_VERSION}-release.tar.gz)
set(PTHREADS_SHA512 9c06e85310766834370c3dceb83faafd397da18a32411ca7645c8eb6b9495fea54ca2872f4a3e8d83cb5fdc5dea7f3f0464be5bb9af3222a6534574a184bd551)
-set(ILMBASE_VERSION 2.2.0)
+set(ILMBASE_VERSION 2.2.1)
set(ILMBASE_URI http://download.savannah.nongnu.org/releases/openexr/ilmbase-${ILMBASE_VERSION}.tar.gz)
-set(ILMBASE_HASH b540db502c5fa42078249f43d18a4652)
+set(ILMBASE_HASH 7b86128b04f0541b6bb33633e299cb44)
-set(OPENEXR_VERSION 2.2.0)
-set(OPENEXR_URI http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz)
-set(OPENEXR_HASH b64e931c82aa3790329c21418373db4e)
+set(OPENEXR_VERSION 2.2.1)
+set(OPENEXR_URI http://download.savannah.nongnu.org/releases/openexr/openexr-${OPENEXR_VERSION}.tar.gz)
+set(OPENEXR_HASH 421815c32989e1b98fc4798ee754c433)
-set(FREETYPE_VERSION 263)
-set(FREETYPE_URI http://download.savannah.gnu.org/releases/freetype/ft${FREETYPE_VERSION}.zip)
-set(FREETYPE_HASH 0db2a43301572e5c2b4a0864f237aeeb)
+set(FREETYPE_VERSION 2.9.1)
+set(FREETYPE_URI http://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
+set(FREETYPE_HASH 3adb0e35d3c100c456357345ccfa8056)
set(GLEW_VERSION 1.13.0)
set(GLEW_URI http://prdownloads.sourceforge.net/glew/glew/${GLEW_VERSION}/glew-${GLEW_VERSION}.tgz)
@@ -103,12 +103,15 @@ set(OPENCOLLADA_HASH 23db5087faed4bc4cc1dfe456c0d4701)
set(OPENCOLORIO_URI https://github.com/imageworks/OpenColorIO/archive/6de971097c7f552300f669ed69ca0b6cf5a70843.zip)
set(OPENCOLORIO_HASH c9de0fd98f26ce6f2e08d617ca68b8e4)
-set(LLVM_VERSION 3.4.2)
-set(LLVM_URI http://releases.llvm.org/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.gz)
-set(LLVM_HASH a20669f75967440de949ac3b1bad439c)
+set(LLVM_VERSION 6.0.1)
+set(LLVM_URI http://releases.llvm.org/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
+set(LLVM_HASH c88c98709300ce2c285391f387fecce0)
+
+set(CLANG_URI http://releases.llvm.org/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.xz)
+set(CLANG_HASH 4e419bd4e3b55aa06d872320f754bd85)
-set(CLANG_URI http://releases.llvm.org/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.gz)
-set(CLANG_HASH 87945973b7c73038871c5f849a818588)
+set(OPENMP_URI http://releases.llvm.org/${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz)
+set(OPENMP_HASH 4826402ae3633c36c51ba4d0e5527d30)
set(OPENIMAGEIO_VERSION 1.7.15)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.zip)
@@ -119,9 +122,9 @@ set(OPENIMAGEIO_HASH_1715 e2ece0f62c013d64c478f82265988b0b)
set(OPENIMAGEIO_HASH ${OPENIMAGEIO_HASH_1715})
-set(TIFF_VERSION 4.0.6)
+set(TIFF_VERSION 4.0.9)
set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
-set(TIFF_HASH d1d2e940dea0b5ad435f21f03d96dd72)
+set(TIFF_HASH 54bad211279cc93eb4fca31ba9bfdc79)
set(FLEXBISON_VERSION 2.5.5)
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison//win_flex_bison-2.5.5.zip)
@@ -131,11 +134,11 @@ set(OSL_VERSION 1.7.5)
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.zip)
set(OSL_HASH 6924dd5d453159e7b6eb106a08c358cf)
-set(PYTHON_VERSION 3.6.2)
-set(PYTHON_SHORT_VERSION 3.6)
-set(PYTHON_SHORT_VERSION_NO_DOTS 36)
+set(PYTHON_VERSION 3.7.0)
+set(PYTHON_SHORT_VERSION 3.7)
+set(PYTHON_SHORT_VERSION_NO_DOTS 37)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
-set(PYTHON_HASH 2c68846471994897278364fc18730dd9)
+set(PYTHON_HASH eb8c2a6b1447d50813c02714af4681f3)
if(UNIX AND NOT APPLE)
# Needed to be compatible with GCC 7, other platforms can upgrade later
@@ -158,10 +161,10 @@ set(URLLIB3_VERSION 1.22)
set(CERTIFI_VERSION 2017.7.27.1)
set(REQUESTS_VERSION 2.18.4)
-set(NUMPY_VERSION v1.13.1)
-set(NUMPY_SHORT_VERSION 1.13)
-set(NUMPY_URI https://pypi.python.org/packages/c0/3a/40967d9f5675fbb097ffec170f59c2ba19fc96373e73ad47c2cae9a30aed/numpy-1.13.1.zip)
-set(NUMPY_HASH 2c3c0f4edf720c3a7b525dacc825b9ae)
+set(NUMPY_VERSION v1.15.0)
+set(NUMPY_SHORT_VERSION 1.15)
+set(NUMPY_URI https://files.pythonhosted.org/packages/3a/20/c81632328b1a4e1db65f45c0a1350a9c5341fd4bbb8ea66cdd98da56fe2e/numpy-1.15.0.zip)
+set(NUMPY_HASH 20e13185089011116a98e11c9bf8aa07)
set(LAME_VERSION 3.99.5)
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.99/lame-${LAME_VERSION}.tar.gz)
@@ -187,14 +190,6 @@ set(VPX_VERSION 1.5.0)
set(VPX_URI http://storage.googleapis.com/downloads.webmproject.org/releases/webm/libvpx-${VPX_VERSION}.tar.bz2)
set(VPX_HASH 306d67908625675f8e188d37a81fbfafdf5068b09d9aa52702b6fbe601c76797)
-set(ORC_VERSION 0.4.25)
-set(ORC_URI https://gstreamer.freedesktop.org/src/orc/orc-${ORC_VERSION}.tar.xz)
-set(ORC_HASH c1b1d54a58f26d483f0b3881538984789fe5d5460ab8fab74a1cacbd3d1c53d1)
-
-set(SCHROEDINGER_VERSION 1.0.11)
-set(SCHROEDINGER_URI https://download.videolan.org/contrib/schroedinger/schroedinger-${SCHROEDINGER_VERSION}.tar.gz)
-set(SCHROEDINGER_HASH 1e572a0735b92aca5746c4528f9bebd35aa0ccf8619b22fa2756137a8cc9f912)
-
set(X264_URI http://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20160401-2245-stable.tar.bz2)
set(X264_HASH 1e9a7b835e80313aade53a9b6ff353e099de3856bf5f30a4d8dfc91281f786f5)
@@ -203,18 +198,19 @@ set(XVIDCORE_URI http://downloads.xvid.org/downloads/xvidcore-${XVIDCORE_VERSION
set(XVIDCORE_HASH 4e9fd62728885855bc5007fe1be58df42e5e274497591fec37249e1052ae316f)
#this has to be in sync with the version in blenders /extern folder
-set(OPENJPEG_VERSION 1.5.2)
-set(OPENJPEG_SHORT_VERSION 1.5)
-set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/version.${OPENJPEG_VERSION}.tar.gz)
-set(OPENJPEG_HASH 3734e95edd0bef6e056815591755efd822228dc3cd866894e00a2c929026b16d)
+set(OPENJPEG_VERSION 2.3.0)
+set(OPENJPEG_SHORT_VERSION 2.3)
+# Use slightly newer commit after release which includes a cmake fix
+set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/66297f07a43.zip)
+set(OPENJPEG_HASH 8242b18d908c7c42174e4231a741cfa7ce7c26b6ed5c9644feb9df7b3054310b)
set(FAAD_VERSION 2-2.7)
set(FAAD_URI http://downloads.sourceforge.net/faac/faad${FAAD_VERSION}.tar.bz2)
set(FAAD_HASH 4c332fa23febc0e4648064685a3d4332)
-set(FFMPEG_VERSION 3.2.1)
+set(FFMPEG_VERSION 3.4.1)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
-set(FFMPEG_HASH cede174178e61f882844f5870c35ce72)
+set(FFMPEG_HASH bbf3fcded80c33968c91bf323a744286)
set(FFTW_VERSION 3.3.4)
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
@@ -240,9 +236,9 @@ set(HIDAPI_UID 89a6c75dc6f45ecabd4ddfbd2bf5ba6ad8ba38b5)
set(HIDAPI_URI https://github.com/TheOnlyJoey/hidapi/archive/${HIDAPI_UID}.zip)
set(HIDAPI_HASH b6e22f6b514f8bcf594989f20ffc46fb)
-set(WEBP_VERSION 0.5.1)
+set(WEBP_VERSION 0.6.1)
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
-set(WEBP_HASH 3d7db92ebba5b4f679413d25c6040881)
+set(WEBP_HASH b49ce9c3e3e9acae4d91bca44bb85a72)
set(SPNAV_VERSION 0.2.3)
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
diff --git a/build_files/build_environment/cmake/webp.cmake b/build_files/build_environment/cmake/webp.cmake
index 0504988a088..92cd41b96ff 100644
--- a/build_files/build_environment/cmake/webp.cmake
+++ b/build_files/build_environment/cmake/webp.cmake
@@ -37,14 +37,5 @@ ExternalProject_Add(external_webp
URL_HASH MD5=${WEBP_HASH}
PREFIX ${BUILD_DIR}/webp
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/webp -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${WEBP_EXTRA_ARGS}
- INSTALL_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp-build/${WEBP_BUILD_DIR}${LIBPREFIX}webp${LIBEXT} ${LIBDIR}/webp/lib/${LIBPREFIX}webp${LIBEXT} &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/decode.h ${LIBDIR}/webp/include/webp/decode.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/encode.h ${LIBDIR}/webp/include/webp/encode.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/demux.h ${LIBDIR}/webp/include/webp/demux.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/extras.h ${LIBDIR}/webp/include/webp/extras.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/format_constants.h ${LIBDIR}/webp/include/webp/format_constants.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/mux.h ${LIBDIR}/webp/include/webp/mux.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/mux_types.h ${LIBDIR}/webp/include/webp/mux_types.h &&
- ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/webp/src/external_webp/src/webp/types.h ${LIBDIR}/webp/include/webp/types.h
INSTALL_DIR ${LIBDIR}/webp
)
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index c474c39d910..d590a80bcac 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -285,7 +285,7 @@ SUDO="sudo"
NO_BUILD=false
NO_CONFIRM=false
-USE_CXX11=true # Mandatory in blender2.8
+USE_CXX11=true
PYTHON_VERSION="3.6.2"
PYTHON_VERSION_MIN="3.6"
@@ -794,20 +794,10 @@ OPENCOLLADA_REPO_BRANCH="master"
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
+# C++11 is required now
CXXFLAGS_BACK=$CXXFLAGS
-if [ "$USE_CXX11" = true ]; then
- WARNING "C++11 is now mandatory for blender2.8, this *should* go smoothly with any very recent distribution.
-However, if you are experiencing linking errors (also when building Blender itself), please try the following:
- * Re-run this script with '--build-all --force-all' options.
- * Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above.
-
-Please note that until the transition to C++11-built libraries if completed in your distribution, situation will
-remain fuzzy and incompatibilities may happen..."
- PRINT ""
- PRINT ""
- CXXFLAGS="$CXXFLAGS -std=c++11"
- export CXXFLAGS
-fi
+CXXFLAGS="$CXXFLAGS -std=c++11"
+export CXXFLAGS
#### Show Dependencies ####
@@ -1682,9 +1672,7 @@ compile_OIIO() {
# fi
cmake_d="$cmake_d -D USE_OCIO=OFF"
- if [ "$USE_CXX11" = true ]; then
- cmake_d="$cmake_d -D OIIO_BUILD_CPP11=ON"
- fi
+ cmake_d="$cmake_d -D OIIO_BUILD_CPP11=ON"
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"
@@ -1897,9 +1885,7 @@ compile_OSL() {
cmake_d="$cmake_d -D OSL_BUILD_PLUGINS=OFF"
cmake_d="$cmake_d -D OSL_BUILD_TESTS=OFF"
cmake_d="$cmake_d -D USE_SIMD=sse2"
- if [ "$USE_CXX11" = true ]; then
- cmake_d="$cmake_d -D OSL_BUILD_CPP11=1"
- fi
+ cmake_d="$cmake_d -D OSL_BUILD_CPP11=1"
#~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
@@ -2285,12 +2271,6 @@ 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
if [ -d $INST/boost ]; then
cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost"
@@ -4227,12 +4207,6 @@ print_info() {
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
- if [ "$USE_CXX11" = true ]; then
- _1="-D WITH_CXX11=ON"
- PRINT " $_1"
- _buildargs="$_buildargs $_1"
- fi
-
_1="-D WITH_CODEC_SNDFILE=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
diff --git a/build_files/build_environment/patches/boost.diff b/build_files/build_environment/patches/boost.diff
deleted file mode 100644
index 41b40d7a915..00000000000
--- a/build_files/build_environment/patches/boost.diff
+++ /dev/null
@@ -1,37 +0,0 @@
---- a/boost/config/compiler/visualc.hpp 2015-12-08 11:55:19 -0700
-+++ b/boost/config/compiler/visualc.hpp 2018-03-17 10:29:52 -0600
-@@ -287,12 +287,3 @@
- # define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)
- #endif
-
--//
--// last known and checked version is 19.00.23026 (VC++ 2015 RTM):
--#if (_MSC_VER > 1900)
--# if defined(BOOST_ASSERT_CONFIG)
--# error "Unknown compiler version - please run the configure tests and report the results"
--# else
--# pragma message("Unknown compiler version - please run the configure tests and report the results")
--# endif
--#endif
---- a/boost/type_traits/has_nothrow_assign.hpp 2015-12-13 05:49:42 -0700
-+++ b/boost/type_traits/has_nothrow_assign.hpp 2018-05-27 11:11:02 -0600
-@@ -24,7 +24,7 @@
- #include <boost/type_traits/remove_reference.hpp>
- #endif
- #endif
--#if defined(__GNUC__) || defined(__SUNPRO_CC)
-+#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__)
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/is_volatile.hpp>
- #include <boost/type_traits/is_assignable.hpp>
---- a/boost/type_traits/has_nothrow_constructor.hpp 2015-12-13 05:49:42 -0700
-+++ b/boost/type_traits/has_nothrow_constructor.hpp 2018-05-27 11:11:02 -0600
-@@ -17,7 +17,7 @@
- #if defined(BOOST_MSVC) || defined(BOOST_INTEL)
- #include <boost/type_traits/has_trivial_constructor.hpp>
- #endif
--#if defined(__GNUC__ ) || defined(__SUNPRO_CC)
-+#if defined(__GNUC__ ) || defined(__SUNPRO_CC) || defined(__clang__)
- #include <boost/type_traits/is_default_constructible.hpp>
- #endif
-
diff --git a/build_files/build_environment/patches/clang.diff b/build_files/build_environment/patches/clang.diff
deleted file mode 100644
index 724e92f8163..00000000000
--- a/build_files/build_environment/patches/clang.diff
+++ /dev/null
@@ -1,127 +0,0 @@
---- cfe/trunk/lib/Serialization/ASTWriter.cpp
-+++ cfe/trunk/lib/Serialization/ASTWriter.cpp
-@@ -56,14 +56,14 @@
- using namespace clang::serialization;
-
- template <typename T, typename Allocator>
--static StringRef bytes(const std::vector<T, Allocator> &v) {
-+static StringRef data(const std::vector<T, Allocator> &v) {
- if (v.empty()) return StringRef();
- return StringRef(reinterpret_cast<const char*>(&v[0]),
- sizeof(T) * v.size());
- }
-
- template <typename T>
--static StringRef bytes(const SmallVectorImpl<T> &v) {
-+static StringRef data(const SmallVectorImpl<T> &v) {
- return StringRef(reinterpret_cast<const char*>(v.data()),
- sizeof(T) * v.size());
- }
-@@ -1385,7 +1385,7 @@
- Record.push_back(INPUT_FILE_OFFSETS);
- Record.push_back(InputFileOffsets.size());
- Record.push_back(UserFilesNum);
-- Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));
-+ Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets));
- }
-
- //===----------------------------------------------------------------------===//
-@@ -1771,7 +1771,7 @@
- Record.push_back(SOURCE_LOCATION_OFFSETS);
- Record.push_back(SLocEntryOffsets.size());
- Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy
-- Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets));
-+ Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets));
-
- // Write the source location entry preloads array, telling the AST
- // reader which source locations entries it should load eagerly.
-@@ -2087,7 +2087,7 @@
- Record.push_back(MacroOffsets.size());
- Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS);
- Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record,
-- bytes(MacroOffsets));
-+ data(MacroOffsets));
- }
-
- void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
-@@ -2185,7 +2185,7 @@
- Record.push_back(PPD_ENTITIES_OFFSETS);
- Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS);
- Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
-- bytes(PreprocessedEntityOffsets));
-+ data(PreprocessedEntityOffsets));
- }
- }
-
-@@ -2548,7 +2548,7 @@
- Record.push_back(CXX_BASE_SPECIFIER_OFFSETS);
- Record.push_back(CXXBaseSpecifiersOffsets.size());
- Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record,
-- bytes(CXXBaseSpecifiersOffsets));
-+ data(CXXBaseSpecifiersOffsets));
- }
-
- //===----------------------------------------------------------------------===//
-@@ -2623,7 +2623,7 @@
- Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D)));
-
- ++NumLexicalDeclContexts;
-- Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls));
-+ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls));
- return Offset;
- }
-
-@@ -2642,7 +2642,7 @@
- Record.push_back(TYPE_OFFSET);
- Record.push_back(TypeOffsets.size());
- Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS);
-- Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
-+ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets));
-
- // Write the declaration offsets array
- Abbrev = new BitCodeAbbrev();
-@@ -2655,7 +2655,7 @@
- Record.push_back(DECL_OFFSET);
- Record.push_back(DeclOffsets.size());
- Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS);
-- Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
-+ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets));
- }
-
- void ASTWriter::WriteFileDeclIDsMap() {
-@@ -2680,7 +2680,7 @@
- unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
- Record.push_back(FILE_SORTED_DECLS);
- Record.push_back(FileSortedIDs.size());
-- Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileSortedIDs));
-+ Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs));
- }
-
- void ASTWriter::WriteComments() {
-@@ -2893,7 +2893,7 @@
- Record.push_back(SelectorOffsets.size());
- Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS);
- Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
-- bytes(SelectorOffsets));
-+ data(SelectorOffsets));
- }
- }
-
-@@ -3253,7 +3253,7 @@
- Record.push_back(IdentifierOffsets.size());
- Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS);
- Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
-- bytes(IdentifierOffsets));
-+ data(IdentifierOffsets));
- }
-
- //===----------------------------------------------------------------------===//
-@@ -4046,7 +4046,7 @@
- Record.clear();
- Record.push_back(TU_UPDATE_LEXICAL);
- Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
-- bytes(NewGlobalDecls));
-+ data(NewGlobalDecls));
-
- // And a visible updates block for the translation unit.
- Abv = new llvm::BitCodeAbbrev();
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
index 75fc6490031..6e925399c95 100644
--- a/build_files/build_environment/patches/ffmpeg.diff
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -1,32 +1,11 @@
---- libavutil/common.h 2016-02-14 19:29:42 -0700
-+++ libavutil/common.h 2016-03-30 09:50:29 -0600
-@@ -99,6 +99,11 @@
- #define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
- #define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
-
-+//msvc helper
-+#ifdef _MSC_VER
-+#define inline __inline
-+#endif
-+
- /* misc math functions */
-
- #ifdef HAVE_AV_CONFIG_H
--- configure 2016-11-26 03:12:05.000000000 +0100
+++ configure 2017-04-05 03:24:35.000000000 +0200
-@@ -1899,7 +1899,6 @@
- access
- aligned_malloc
- arc4random
-- clock_gettime
- closesocket
- CommandLineToArgvW
- CoTaskMemFree
-@@ -5494,7 +5493,6 @@
+@@ -5494,7 +5493,5 @@
check_func access
check_func_headers stdlib.h arc4random
--check_func_headers time.h clock_gettime || { check_func_headers time.h clock_gettime -lrt && add_extralibs -lrt && LIBRT="-lrt"; }
+-check_func_headers time.h clock_gettime ||
+- { check_lib clock_gettime time.h clock_gettime -lrt && LIBRT="-lrt"; }
check_func fcntl
check_func fork
check_func gethrtime
diff --git a/build_files/build_environment/patches/freetype.diff b/build_files/build_environment/patches/freetype.diff
new file mode 100644
index 00000000000..cf952234795
--- /dev/null
+++ b/build_files/build_environment/patches/freetype.diff
@@ -0,0 +1,18 @@
+diff -NaurBb b/CMakeLists.txt a/CMakeLists.txt
+--- b/CMakeLists.txt 2018-05-01 12:45:46 -0600
++++ a/CMakeLists.txt 2018-08-08 13:03:22 -0600
+@@ -229,9 +229,12 @@
+ endif ()
+ string(REPLACE "/undef " "#undef "
+ FTCONFIG_H "${FTCONFIG_H}")
+- file(WRITE "${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h"
+- "${FTCONFIG_H}")
++else()
++ file(READ "${PROJECT_SOURCE_DIR}/include/freetype/config/ftconfig.h"
++ FTCONFIG_H)
+ endif ()
++file(WRITE "${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h"
++ "${FTCONFIG_H}")
+
+
+ # Create the options file
diff --git a/build_files/build_environment/patches/llvm-alloca-fix.diff b/build_files/build_environment/patches/llvm-alloca-fix.diff
deleted file mode 100644
index 5394a472167..00000000000
--- a/build_files/build_environment/patches/llvm-alloca-fix.diff
+++ /dev/null
@@ -1,111 +0,0 @@
-Index: lib/Target/X86/X86ISelLowering.cpp
-===================================================================
---- lib/Target/X86/X86ISelLowering.cpp 2014-04-11 23:04:44.000000000 +0200
-+++ lib/Target/X86/X86ISelLowering.cpp (working copy)
-@@ -15493,12 +15493,36 @@
- // non-trivial part is impdef of ESP.
-
- if (Subtarget->isTargetWin64()) {
-+ const char *StackProbeSymbol =
-+ Subtarget->isTargetCygMing() ? "___chkstk" : "__chkstk";
-+
-+ MachineInstrBuilder MIB;
-+
-+ if (getTargetMachine().getCodeModel() == CodeModel::Large) {
-+ // For large code model we need to do indirect call to __chkstk.
-+
-+ // R11 will be used to contain the address of __chkstk.
-+ // R11 is a volotiale register and assumed to be destoyed by the callee,
-+ // so there is no need to save and restore it.
-+ BuildMI(*BB, MI, DL, TII->get(X86::MOV64ri), X86::R11)
-+ .addExternalSymbol(StackProbeSymbol);
-+ // Create a call to __chkstk function which address contained in R11.
-+ MIB = BuildMI(*BB, MI, DL, TII->get(X86::CALL64r))
-+ .addReg(X86::R11, RegState::Kill);
-+
-+ } else {
-+
-+ // For non-large code model we can do direct call to __chkstk.
-+
-+ MIB = BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
-+ .addExternalSymbol(StackProbeSymbol);
-+ }
-+
- if (Subtarget->isTargetCygMing()) {
- // ___chkstk(Mingw64):
- // Clobbers R10, R11, RAX and EFLAGS.
- // Updates RSP.
-- BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
-- .addExternalSymbol("___chkstk")
-+ MIB
- .addReg(X86::RAX, RegState::Implicit)
- .addReg(X86::RSP, RegState::Implicit)
- .addReg(X86::RAX, RegState::Define | RegState::Implicit)
-@@ -15507,8 +15531,7 @@
- } else {
- // __chkstk(MSVCRT): does not update stack pointer.
- // Clobbers R10, R11 and EFLAGS.
-- BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA))
-- .addExternalSymbol("__chkstk")
-+ MIB
- .addReg(X86::RAX, RegState::Implicit)
- .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
- // RAX has the offset to be subtracted from RSP.
-Index: lib/Target/X86/X86FrameLowering.cpp
-===================================================================
---- lib/Target/X86/X86FrameLowering.cpp 2013-10-24 01:37:01.000000000 +0200
-+++ lib/Target/X86/X86FrameLowering.cpp (working copy)
-@@ -635,25 +635,49 @@
- .addReg(X86::EAX, RegState::Kill)
- .setMIFlag(MachineInstr::FrameSetup);
- }
-+
-+ MachineInstrBuilder MIB;
-
- if (Is64Bit) {
-+
- // Handle the 64-bit Windows ABI case where we need to call __chkstk.
- // Function prologue is responsible for adjusting the stack pointer.
- BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::RAX)
- .addImm(NumBytes)
- .setMIFlag(MachineInstr::FrameSetup);
-+
-+ if (TM.getCodeModel() == CodeModel::Large) {
-+ // For large code model we need to do indirect call to __chkstk.
-+
-+
-+ // R11 will be used to contain the address of __chkstk.
-+ // R11 is a volotiale register and assumed to be destoyed by the callee,
-+ // so there is no need to save and restore it.
-+ BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::R11)
-+ .addExternalSymbol(StackProbeSymbol);
-+ // Create a call to __chkstk function which address contained in R11.
-+ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALL64r))
-+ .addReg(X86::R11, RegState::Kill);
-+ } else {
-+
-+ // For non-large code model we can do direct call to __chkstk.
-+
-+ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::W64ALLOCA))
-+ .addExternalSymbol(StackProbeSymbol);
-+ }
- } else {
- // Allocate NumBytes-4 bytes on stack in case of isEAXAlive.
- // We'll also use 4 already allocated bytes for EAX.
- BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
- .addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
- .setMIFlag(MachineInstr::FrameSetup);
-+
-+ MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
-+ .addExternalSymbol(StackProbeSymbol);
- }
-
-- BuildMI(MBB, MBBI, DL,
-- TII.get(Is64Bit ? X86::W64ALLOCA : X86::CALLpcrel32))
-- .addExternalSymbol(StackProbeSymbol)
-- .addReg(StackPtr, RegState::Define | RegState::Implicit)
-+
-+ MIB.addReg(StackPtr, RegState::Define | RegState::Implicit)
- .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit)
- .setMIFlag(MachineInstr::FrameSetup);
-
diff --git a/build_files/build_environment/patches/numpy.diff b/build_files/build_environment/patches/numpy.diff
deleted file mode 100644
index c4c57222838..00000000000
--- a/build_files/build_environment/patches/numpy.diff
+++ /dev/null
@@ -1,23 +0,0 @@
-diff -Naur numpy-1.11.1/numpy/distutils/ccompiler.py numpy-1.11.1/numpy/distutils/ccompiler.py
---- numpy-1.11.1/numpy/distutils/ccompiler.py 2016-06-25 08:38:34 -0600
-+++ numpy-1.11.1/numpy/distutils/ccompiler.py 2016-08-04 12:33:43 -0600
-@@ -29,6 +29,7 @@
-
- # Using customized CCompiler.spawn.
- def CCompiler_spawn(self, cmd, display=None):
-+ cmd = quote_args(cmd)
- """
- Execute a command in a sub-process.
-
-diff -Naur numpy-1.11.1/numpy/distutils/misc_util.py numpy-1.11.1/numpy/distutils/misc_util.py
---- numpy-1.11.1/numpy/distutils/misc_util.py 2016-06-25 08:38:34 -0600
-+++ numpy-1.11.1/numpy/distutils/misc_util.py 2016-08-04 12:34:56 -0600
-@@ -116,7 +116,7 @@
- args = list(args)
- for i in range(len(args)):
- a = args[i]
-- if ' ' in a and a[0] not in '"\'':
-+ if ' ' in a and a[0] not in '"\'' and a[len(a)-1] not in '"\'':
- args[i] = '"%s"' % (a)
- return args
-
diff --git a/build_files/build_environment/patches/schroedinger.diff b/build_files/build_environment/patches/schroedinger.diff
deleted file mode 100644
index 6acb35f2a7b..00000000000
--- a/build_files/build_environment/patches/schroedinger.diff
+++ /dev/null
@@ -1,54 +0,0 @@
---- configure.orig 2012-01-22 19:06:43 -0700
-+++ configure 2016-04-06 20:00:50 -0600
-@@ -16492,10 +16492,10 @@
- HAVE_ORC=yes
- fi
- if test "x${HAVE_ORC}" != xyes ; then
-- as_fn_error $? "orc-0.4 >= $ORC_VER is required" "$LINENO" 5
-+ $as_echo "orc-0.4 >= $ORC_VER is required"
- fi
- SCHRO_PKG_DEPS="$SCHRO_PKG_DEPS orc-0.4 >= $ORC_VER"
--ORCC=`$PKG_CONFIG --variable=orcc orc-0.4`
-+#ORCC=`$PKG_CONFIG --variable=orcc orc-0.4`
-
- if test "x$cross_compiling" != xyes; then
- HAVE_ORCC_TRUE=
---- Makefile.in 2012-01-22 18:06:42 -0700
-+++ Makefile.in 2016-04-06 20:30:09 -0600
-@@ -291,7 +291,7 @@
- top_builddir = @top_builddir@
- top_srcdir = @top_srcdir@
- AUTOMAKE_OPTIONS = foreign
--SUBDIRS = schroedinger doc tools testsuite
-+SUBDIRS = schroedinger doc tools
- DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
- DIST_SUBDIRS = schroedinger doc tools testsuite
- EXTRA_DIST = COPYING COPYING.GPL COPYING.LGPL COPYING.MIT COPYING.MPL \
-
---- schroedinger.pc.in 2011-03-21 17:08:39 -0600
-+++ schroedinger.pc.in 2016-04-08 13:30:42 -0600
-@@ -7,9 +7,9 @@
-
- Name: schroedinger-@SCHRO_MAJORMINOR@
- Description: Dirac codec library
--Requires.private: @SCHRO_PKG_DEPS@
-+Requires: @SCHRO_PKG_DEPS@
- Version: @VERSION@
--Libs: -L${libdir} -lschroedinger-@SCHRO_MAJORMINOR@
-+Libs: -L${libdir} -lschroedinger-@SCHRO_MAJORMINOR@ -lorc-0.4
- Libs.private: @PTHREAD_LIBS@ @LIBM@
- Cflags: -I${includedir}
-
---- ./schroedinger/schrodecoder.c 2012-01-23 00:38:57.000000000 +0100
-+++ ./schroedinger/schrodecoder.c 2016-05-15 06:07:24.000000000 +0200
-@@ -70,8 +70,8 @@
- };
-
-
--int _schro_decode_prediction_only;
--int _schro_telemetry;
-+int _schro_decode_prediction_only = 0;
-+int _schro_telemetry = 0;
-
- static void schro_decoder_x_decode_motion (SchroAsyncStage * stage);
- static void schro_decoder_x_render_motion (SchroAsyncStage * stage);
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 59b35a535aa..a77f237e978 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -77,7 +77,7 @@ if 'cmake' in builder:
# cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/nvcc')
elif builder.startswith('win'):
- if builder.endswith('_vc2017'):
+ if builder.endswith('_vs2017'):
if builder.startswith('win64'):
cmake_options.extend(['-G', 'Visual Studio 15 2017 Win64'])
elif builder.startswith('win32'):
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index b2ec8f6e7a9..65f962d2dd9 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -598,12 +598,12 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_editor_util
bf_editor_uvedit
bf_editor_curve
- bf_editor_gpencil
bf_editor_interface
bf_editor_gizmo_library
bf_editor_mesh
bf_editor_metaball
bf_editor_object
+ bf_editor_gpencil
bf_editor_lattice
bf_editor_armature
bf_editor_physics
@@ -621,17 +621,20 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_python
bf_python_ext
bf_python_mathutils
- bf_python_gawain
+ bf_python_gpu
bf_python_bmesh
bf_freestyle
bf_ikplugin
bf_modifiers
+ bf_gpencil_modifiers
bf_alembic
bf_bmesh
bf_gpu
bf_draw
bf_blenloader
bf_blenkernel
+ bf_shader_fx
+ bf_gpencil_modifiers
bf_physics
bf_nodes
bf_rna
@@ -874,164 +877,6 @@ macro(message_first_run)
endif()
endmacro()
-macro(TEST_UNORDERED_MAP_SUPPORT)
- # - Detect unordered_map availability
- # Test if a valid implementation of unordered_map exists
- # and define the include path
- # This module defines
- # HAVE_UNORDERED_MAP, whether unordered_map implementation was found
- #
- # HAVE_STD_UNORDERED_MAP_HEADER, <unordered_map.h> was found
- # HAVE_UNORDERED_MAP_IN_STD_NAMESPACE, unordered_map is in namespace std
- # HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE, unordered_map is in namespace std::tr1
- #
- # UNORDERED_MAP_INCLUDE_PREFIX, include path prefix for unordered_map, if found
- # UNORDERED_MAP_NAMESPACE, namespace for unordered_map, if found
-
- include(CheckIncludeFileCXX)
-
- # Workaround for newer GCC (6.x+) where C++11 was enabled by default, which lead us
- # to a situation when there is <unordered_map> include but which can't be used uless
- # C++11 is enabled.
- if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
- set(HAVE_STD_UNORDERED_MAP_HEADER False)
- else()
- CHECK_INCLUDE_FILE_CXX("unordered_map" HAVE_STD_UNORDERED_MAP_HEADER)
- endif()
- if(HAVE_STD_UNORDERED_MAP_HEADER)
- # Even so we've found unordered_map header file it doesn't
- # mean unordered_map and unordered_set will be declared in
- # std namespace.
- #
- # Namely, MSVC 2008 have unordered_map header which declares
- # unordered_map class in std::tr1 namespace. In order to support
- # this, we do extra check to see which exactly namespace is
- # to be used.
-
- include(CheckCXXSourceCompiles)
- CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
- int main() {
- std::unordered_map<int, int> map;
- return 0;
- }"
- HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
- if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
- message_first_run(STATUS "Found unordered_map/set in std namespace.")
-
- set(HAVE_UNORDERED_MAP "TRUE")
- set(UNORDERED_MAP_INCLUDE_PREFIX "")
- set(UNORDERED_MAP_NAMESPACE "std")
- else()
- CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
- int main() {
- std::tr1::unordered_map<int, int> map;
- return 0;
- }"
- HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- message_first_run(STATUS "Found unordered_map/set in std::tr1 namespace.")
-
- set(HAVE_UNORDERED_MAP "TRUE")
- set(UNORDERED_MAP_INCLUDE_PREFIX "")
- set(UNORDERED_MAP_NAMESPACE "std::tr1")
- else()
- message_first_run(STATUS "Found <unordered_map> but cannot find either std::unordered_map "
- "or std::tr1::unordered_map.")
- endif()
- endif()
- else()
- CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- message_first_run(STATUS "Found unordered_map/set in std::tr1 namespace.")
-
- set(HAVE_UNORDERED_MAP "TRUE")
- set(UNORDERED_MAP_INCLUDE_PREFIX "tr1")
- set(UNORDERED_MAP_NAMESPACE "std::tr1")
- else()
- message_first_run(STATUS "Unable to find <unordered_map> or <tr1/unordered_map>. ")
- endif()
- endif()
-endmacro()
-
-macro(TEST_SHARED_PTR_SUPPORT)
- # This check are coming from Ceres library.
- #
- # Find shared pointer header and namespace.
- #
- # This module defines the following variables:
- #
- # SHARED_PTR_FOUND: TRUE if shared_ptr found.
- # SHARED_PTR_TR1_MEMORY_HEADER: True if <tr1/memory> header is to be used
- # for the shared_ptr object, otherwise use <memory>.
- # SHARED_PTR_TR1_NAMESPACE: TRUE if shared_ptr is defined in std::tr1 namespace,
- # otherwise it's assumed to be defined in std namespace.
-
- include(CheckIncludeFileCXX)
- include(CheckCXXSourceCompiles)
- set(SHARED_PTR_FOUND FALSE)
- # Workaround for newer GCC (6.x+) where C++11 was enabled by default, which lead us
- # to a situation when there is <unordered_map> include but which can't be used uless
- # C++11 is enabled.
- if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
- set(HAVE_STD_MEMORY_HEADER False)
- else()
- CHECK_INCLUDE_FILE_CXX(memory HAVE_STD_MEMORY_HEADER)
- endif()
- if(HAVE_STD_MEMORY_HEADER)
- # Finding the memory header doesn't mean that shared_ptr is in std
- # namespace.
- #
- # In particular, MSVC 2008 has shared_ptr declared in std::tr1. In
- # order to support this, we do an extra check to see which namespace
- # should be used.
- CHECK_CXX_SOURCE_COMPILES("#include <memory>
- int main() {
- std::shared_ptr<int> int_ptr;
- return 0;
- }"
- HAVE_SHARED_PTR_IN_STD_NAMESPACE)
-
- if(HAVE_SHARED_PTR_IN_STD_NAMESPACE)
- message_first_run("-- Found shared_ptr in std namespace using <memory> header.")
- set(SHARED_PTR_FOUND TRUE)
- else()
- CHECK_CXX_SOURCE_COMPILES("#include <memory>
- int main() {
- std::tr1::shared_ptr<int> int_ptr;
- return 0;
- }"
- HAVE_SHARED_PTR_IN_TR1_NAMESPACE)
- if(HAVE_SHARED_PTR_IN_TR1_NAMESPACE)
- message_first_run("-- Found shared_ptr in std::tr1 namespace using <memory> header.")
- set(SHARED_PTR_TR1_NAMESPACE TRUE)
- set(SHARED_PTR_FOUND TRUE)
- endif()
- endif()
- endif()
-
- if(NOT SHARED_PTR_FOUND)
- # Further, gcc defines shared_ptr in std::tr1 namespace and
- # <tr1/memory> is to be included for this. And what makes things
- # even more tricky is that gcc does have <memory> header, so
- # all the checks above wouldn't find shared_ptr.
- CHECK_INCLUDE_FILE_CXX("tr1/memory" HAVE_TR1_MEMORY_HEADER)
- if(HAVE_TR1_MEMORY_HEADER)
- CHECK_CXX_SOURCE_COMPILES("#include <tr1/memory>
- int main() {
- std::tr1::shared_ptr<int> int_ptr;
- return 0;
- }"
- HAVE_SHARED_PTR_IN_TR1_NAMESPACE_FROM_TR1_MEMORY_HEADER)
- if(HAVE_SHARED_PTR_IN_TR1_NAMESPACE_FROM_TR1_MEMORY_HEADER)
- message_first_run("-- Found shared_ptr in std::tr1 namespace using <tr1/memory> header.")
- set(SHARED_PTR_TR1_MEMORY_HEADER TRUE)
- set(SHARED_PTR_TR1_NAMESPACE TRUE)
- set(SHARED_PTR_FOUND TRUE)
- endif()
- endif()
- endif()
-endmacro()
-
# when we have warnings as errors applied globally this
# needs to be removed for some external libs which we dont maintain.
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 2cb9e07add9..047b1fa3b5b 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -161,7 +161,10 @@ if(WITH_CODEC_FFMPEG)
set(FFMPEG_LIBRARIES
avcodec avdevice avformat avutil
mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg
- )
+ )
+ # commenting out until libs are updated on svn. schroedinger and orc
+ # will be removed then
+ # set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} vpx webp swresample)
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} schroedinger orc vpx webp swresample)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
@@ -171,6 +174,8 @@ if(WITH_IMAGE_OPENJPEG OR WITH_CODEC_FFMPEG)
set(OPENJPEG ${LIBDIR}/openjpeg)
set(WITH_SYSTEM_OPENJPEG ON)
set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include)
+ # same as with ffmpeg libs, update when svn are updated
+ #set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/libopenjp2.a)
set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/libopenjpeg.a)
endif()
diff --git a/build_files/cmake/platform/platform_apple_xcode.cmake b/build_files/cmake/platform/platform_apple_xcode.cmake
index 1b8e13a0623..7af69c092cc 100644
--- a/build_files/cmake/platform/platform_apple_xcode.cmake
+++ b/build_files/cmake/platform/platform_apple_xcode.cmake
@@ -104,7 +104,7 @@ endif()
# 10.9 is our min. target, if you use higher sdk, weak linking happens
if(CMAKE_OSX_DEPLOYMENT_TARGET)
if(${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS 10.9)
- message(STATUS "Setting deployment target to 10.9, lower versions are incompatible with WITH_CXX11")
+ message(STATUS "Setting deployment target to 10.9, lower versions are not supported")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "" FORCE)
endif()
else()
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 468e82e8dac..c45e8ad533d 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -131,9 +131,6 @@ include(InstallRequiredSystemLibraries)
remove_cc_flag("/MDd" "/MD")
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
- if(NOT WITH_CXX11) # C++11 is on by default in clang-cl and can't be turned off, if c++11 is not enabled in blender repress some c++11 related warnings.
- set(CXX_WARN_FLAGS "-Wno-inconsistent-missing-override")
- endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
else()
diff --git a/build_files/windows/autodetect_msvc.cmd b/build_files/windows/autodetect_msvc.cmd
index 6fce3829e7b..4dbe009a890 100644
--- a/build_files/windows/autodetect_msvc.cmd
+++ b/build_files/windows/autodetect_msvc.cmd
@@ -1,17 +1,14 @@
echo No explicit msvc version requested, autodetecting version.
-call "%~dp0\detect_msvc2013.cmd"
+call "%~dp0\detect_msvc2017.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
call "%~dp0\detect_msvc2015.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
-call "%~dp0\detect_msvc2017.cmd"
-if %ERRORLEVEL% EQU 0 goto DetectionComplete
-
echo Compiler Detection failed. Use verbose switch for more information.
exit /b 1
:DetectionComplete
-echo Compiler Detection successfull, detected VS%BUILD_VS_YEAR%
+echo Compiler Detection successful, detected VS%BUILD_VS_YEAR%
exit /b 0 \ No newline at end of file
diff --git a/build_files/windows/check_libraries.cmd b/build_files/windows/check_libraries.cmd
index c8aad7c9adb..90c50293720 100644
--- a/build_files/windows/check_libraries.cmd
+++ b/build_files/windows/check_libraries.cmd
@@ -1,4 +1,3 @@
-if "%BUILD_VS_YEAR%"=="2013" set BUILD_VS_LIBDIRPOST=vc12
if "%BUILD_VS_YEAR%"=="2015" set BUILD_VS_LIBDIRPOST=vc14
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc14
@@ -37,7 +36,7 @@ if NOT EXIST %BUILD_VS_LIBDIR% (
echo.
echo Error: Download of external libraries failed.
echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
- echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successfull blender build
+ echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
echo.
exit /b 1
)
diff --git a/build_files/windows/detect_msvc2013.cmd b/build_files/windows/detect_msvc2013.cmd
deleted file mode 100644
index 5688d31c4b6..00000000000
--- a/build_files/windows/detect_msvc2013.cmd
+++ /dev/null
@@ -1,3 +0,0 @@
-set BUILD_VS_VER=12
-set BUILD_VS_YEAR=2013
-call "%~dp0\detect_msvc_classic.cmd" \ No newline at end of file
diff --git a/build_files/windows/detect_msvc2017.cmd b/build_files/windows/detect_msvc2017.cmd
index 7695dc8d5a2..029f98cbe1e 100644
--- a/build_files/windows/detect_msvc2017.cmd
+++ b/build_files/windows/detect_msvc2017.cmd
@@ -10,8 +10,8 @@ set vs_where=%ProgramFilesX86%\Microsoft Visual Studio\Installer\vswhere.exe
if not exist "%vs_where%" (
if NOT "%verbose%" == "" (
echo Visual Studio 2017 ^(15.2 or newer^) is not detected
- goto FAIL
)
+ goto FAIL
)
if NOT "%verbose%" == "" (
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
index 8a6d743978d..e8caddaf4ea 100644
--- a/build_files/windows/parse_arguments.cmd
+++ b/build_files/windows/parse_arguments.cmd
@@ -59,8 +59,6 @@ if NOT "%1" == "" (
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
) else if "%1" == "2015" (
set BUILD_VS_YEAR=2015
- ) else if "%1" == "2013" (
- set BUILD_VS_YEAR=2013
) else if "%1" == "packagename" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
shift /1
diff --git a/build_files/windows/show_help.cmd b/build_files/windows/show_help.cmd
index 2b297120f4b..694b28c88ed 100644
--- a/build_files/windows/show_help.cmd
+++ b/build_files/windows/show_help.cmd
@@ -22,13 +22,13 @@ echo - packagename [newname] ^(override default cpack package name^)
echo - buildir [newdir] ^(override default build folder^)
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.
-echo Experimental options
-echo - 2015 ^(build with visual studio 2015^)
echo - 2017 ^(build with visual studio 2017^)
echo - 2017pre ^(build with visual studio 2017 pre-release^)
echo - 2017b ^(build with visual studio 2017 Build Tools^)
+
+echo.
+echo Experimental options
+echo - 2015 ^(build with visual studio 2015^)
echo - clang ^(enable building with clang^)
echo - asan ^(enable asan when building with clang^)
echo - ninja ^(enable building with ninja instead of msbuild^)
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index bfa8a295f5b..6c631891418 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -334,9 +334,9 @@ except ImportError:
# to avoid having to match Blender's source tree.
EXTRA_SOURCE_FILES = (
"../../../release/scripts/templates_py/bmesh_simple.py",
- "../../../release/scripts/templates_py/manipulator_operator.py",
- "../../../release/scripts/templates_py/manipulator_operator_target.py",
- "../../../release/scripts/templates_py/manipulator_simple.py",
+ "../../../release/scripts/templates_py/gizmo_operator.py",
+ "../../../release/scripts/templates_py/gizmo_operator_target.py",
+ "../../../release/scripts/templates_py/gizmo_simple.py",
"../../../release/scripts/templates_py/operator_simple.py",
"../../../release/scripts/templates_py/ui_panel_simple.py",
"../../../release/scripts/templates_py/ui_previews_custom_icon.py",
diff --git a/extern/audaspace/blender_config.cmake b/extern/audaspace/blender_config.cmake
index fb1ef95fee4..7deb78d27da 100644
--- a/extern/audaspace/blender_config.cmake
+++ b/extern/audaspace/blender_config.cmake
@@ -1,21 +1,20 @@
set(AUDASPACE_STANDALONE FALSE)
-set(BUILD_DEMOS FALSE)
-set(SHARED_LIBRARY FALSE)
-set(WITH_C TRUE)
-set(WITH_DOCS FALSE)
-set(WITH_FFMPEG ${WITH_CODEC_FFMPEG})
-set(WITH_FFTW FALSE)
-set(WITH_LIBSNDFILE ${WITH_CODEC_SNDFILE})
-set(SEPARATE_C FALSE)
-set(PLUGIN_FFMPEG FALSE)
-set(PLUGIN_JACK FALSE)
-set(PLUGIN_LIBSNDFILE FALSE)
-set(PLUGIN_OPENAL FALSE)
-set(PLUGIN_SDL FALSE)
-set(WITH_PYTHON_MODULE FALSE)
-set(DYNLOAD_JACK ${WITH_JACK_DYNLOAD})
-set(WITH_BINDING_DOCS FALSE)
-set(BLENDER_AUDASPACE TRUE)
+set(BUILD_DEMOS FALSE CACHE BOOL "Build and install demos")
+set(SHARED_LIBRARY FALSE CACHE BOOL "Build Shared Library")
+set(WITH_C TRUE CACHE BOOL "Build C Module")
+set(WITH_DOCS FALSE CACHE BOOL "Build C++ HTML Documentation with Doxygen")
+set(WITH_FFMPEG ${WITH_CODEC_FFMPEG} CACHE BOOL "Build With FFMPEG")
+set(WITH_FFTW FALSE CACHE BOOL "Build With FFTW")
+set(WITH_LIBSNDFILE ${WITH_CODEC_SNDFILE} CACHE BOOL "Build With LibSndFile")
+set(SEPARATE_C FALSE CACHE BOOL "Build C Binding as separate library")
+set(PLUGIN_FFMPEG FALSE CACHE BOOL "Build FFMPEG Plugin")
+set(PLUGIN_JACK FALSE CACHE BOOL "Build JACK Plugin")
+set(PLUGIN_LIBSNDFILE FALSE CACHE BOOL "Build LibSndFile Plugin")
+set(PLUGIN_OPENAL FALSE CACHE BOOL "Build OpenAL Plugin")
+set(PLUGIN_SDL FALSE CACHE BOOL "Build SDL Plugin")
+set(WITH_PYTHON_MODULE FALSE CACHE BOOL "Build Python Module")
+set(DYNLOAD_JACK ${WITH_JACK_DYNLOAD} CACHE BOOL "Dynamically load JACK")
+set(WITH_BINDING_DOCS FALSE CACHE BOOL "Build C/Python HTML Documentation with Sphinx")
set(FFMPEG_FOUND ${WITH_CODEC_FFMPEG})
set(JACK_FOUND ${WITH_JACK})
set(LIBSNDFILE_FOUND ${WITH_CODEC_SNDFILE})
@@ -26,5 +25,7 @@ set(NUMPY_INCLUDE_DIRS ${PYTHON_NUMPY_INCLUDE_DIRS})
set(SDL_FOUND ${WITH_SDL})
if(WIN32)
- set(DEFAULT_PLUGIN_PATH "plugins")
+ set(DEFAULT_PLUGIN_PATH "plugins" CACHE STRING "Default plugin installation and loading path.")
endif()
+
+mark_as_advanced(BUILD_DEMOS SHARED_LIBRARY WITH_C WITH_DOCS WITH_FFMPEG WITH_FFTW WITH_LIBSNDFILE SEPARATE_C PLUGIN_FFMPEG PLUGIN_JACK PLUGIN_LIBSNDFILE PLUGIN_OPENAL PLUGIN_SDL WITH_PYTHON_MODULE DYNLOAD_JACK WITH_BINDING_DOCS DEFAULT_PLUGIN_PATH)
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 1a050892836..1459100d415 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -34,7 +34,6 @@ add_subdirectory(opencolorio)
add_subdirectory(mikktspace)
add_subdirectory(glew-mx)
add_subdirectory(eigen)
-add_subdirectory(gawain)
if(WITH_AUDASPACE)
add_subdirectory(audaspace)
diff --git a/intern/clog/clog.c b/intern/clog/clog.c
index d26f0545117..7ebd3fba425 100644
--- a/intern/clog/clog.c
+++ b/intern/clog/clog.c
@@ -472,7 +472,7 @@ void CLG_logf(
static void CLG_ctx_output_set(CLogContext *ctx, void *file_handle)
{
ctx->output_file = file_handle;
- ctx->output = fileno(file_handle);
+ ctx->output = fileno(ctx->output_file);
#if defined(__unix__) || defined(__APPLE__)
ctx->use_color = isatty(ctx->output);
#endif
@@ -561,7 +561,7 @@ static void CLG_ctx_free(CLogContext *ctx)
* \{ */
/* We could support multiple at once, for now this seems not needed. */
-struct CLogContext *g_ctx = NULL;
+static struct CLogContext *g_ctx = NULL;
void CLG_init(void)
{
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 0740aa51039..00ac8e7e182 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -224,31 +224,6 @@ endif()
# TODO(sergey): Consider removing it, only causes confusion in interface.
set(WITH_CYCLES_DEVICE_MULTI TRUE)
-if(CYCLES_STANDALONE_REPOSITORY)
- TEST_UNORDERED_MAP_SUPPORT()
-endif()
-if(WITH_CXX11)
- add_definitions(-DCYCLES_STD_UNORDERED_MAP)
-elseif(HAVE_STD_UNORDERED_MAP_HEADER)
- if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
- add_definitions(-DCYCLES_STD_UNORDERED_MAP)
- else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- add_definitions(-DCYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
- else()
- add_definitions(-DCYCLES_NO_UNORDERED_MAP)
- message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
- endif()
-else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- add_definitions(-DCYCLES_TR1_UNORDERED_MAP)
- else()
- add_definitions(-DCYCLES_NO_UNORDERED_MAP)
- message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
-endif()
-
# Logging capabilities using GLog library.
if(WITH_CYCLES_LOGGING)
add_definitions(-DWITH_CYCLES_LOGGING)
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 5c52a8bcce9..476cf975737 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -52,7 +52,9 @@ def _workaround_buggy_drivers():
def _configure_argument_parser():
import argparse
- parser = argparse.ArgumentParser(description="Cycles Addon argument parser")
+ # No help because it conflicts with general Python scripts argument parsing
+ parser = argparse.ArgumentParser(description="Cycles Addon argument parser",
+ add_help=False)
parser.add_argument("--cycles-resumable-num-chunks",
help="Number of chunks to split sample range into",
default=None)
@@ -65,6 +67,9 @@ def _configure_argument_parser():
parser.add_argument("--cycles-resumable-end-chunk",
help="End chunk to render",
default=None)
+ parser.add_argument("--cycles-print-stats",
+ help="Print rendering statistics to stderr",
+ action='store_true')
return parser
@@ -93,6 +98,9 @@ def _parse_command_line():
int(args.cycles_resumable_start_chunk),
int(args.cycles_resumable_end_chunk),
)
+ if args.cycles_print_stats:
+ import _cycles
+ _cycles.enable_print_stats()
def init():
@@ -168,7 +176,7 @@ def reset(engine, data, depsgraph):
import bpy
if bpy.app.debug_value == 256:
- _cycles.debug_flags_update(depsgraph.scene)
+ _cycles.debug_flags_update(depsgraph.scene.as_pointer())
else:
_cycles.debug_flags_reset()
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 6e56e42f9b2..737f7416486 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -883,14 +883,9 @@ class CYCLES_CAMERA_PT_dof_viewport(CyclesButtonsPanel, Panel):
cam = context.camera
dof_options = cam.gpu_dof
- hq_support = dof_options.is_hq_supported
sub = flow.column(align=True)
- subhq = sub.column()
- subhq.active = hq_support
- subhq.prop(dof_options, "use_high_quality")
sub.prop(dof_options, "fstop")
- if dof_options.use_high_quality and hq_support:
- sub.prop(dof_options, "blades")
+ sub.prop(dof_options, "blades")
class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
@@ -900,7 +895,10 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return (context.material or context.object) and CyclesButtonsPanel.poll(context)
+ if context.active_object and context.active_object.type == 'GPENCIL':
+ return False
+ else:
+ return (context.material or context.object) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1227,7 +1225,7 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
world = context.world
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
- layout.prop(world, "horizon_color", text="Color")
+ layout.prop(world, "color")
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index c7e8fb6f72f..1d0e8fc6ace 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -1077,38 +1077,21 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
bool object_updated,
bool hide_tris)
{
- /* When viewport display is not needed during render we can force some
- * caches to be releases from blender side in order to reduce peak memory
- * footprint during synchronization process.
- */
- const bool is_interface_locked = b_engine.render() &&
- b_engine.render().use_lock_interface();
- const bool can_free_caches = BlenderSession::headless || is_interface_locked;
-
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data;
- BL::Material material_override = view_layer.material_override;
/* find shader indices */
vector<Shader*> used_shaders;
BL::Object::material_slots_iterator slot;
for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
- if(material_override) {
- find_shader(material_override, used_shaders, scene->default_surface);
- }
- else {
- BL::ID b_material(slot->material());
- find_shader(b_material, used_shaders, scene->default_surface);
- }
+ BL::ID b_material(slot->material());
+ find_shader(b_material, used_shaders, scene->default_surface);
}
if(used_shaders.size() == 0) {
- if(material_override)
- find_shader(material_override, used_shaders, scene->default_surface);
- else
- used_shaders.push_back(scene->default_surface);
+ used_shaders.push_back(scene->default_surface);
}
/* test if we need to sync */
@@ -1210,10 +1193,6 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
if(view_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
sync_curves(mesh, b_mesh, b_ob, false);
- if(can_free_caches) {
- b_ob.cache_release();
- }
-
if(b_mesh) {
/* free derived mesh */
b_data.meshes.remove(b_mesh, false, true, false);
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index ed01d728931..a1f39d0848f 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -291,8 +291,8 @@ void BlenderSync::sync_background_light(bool use_portal)
/* Object */
Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
+ BL::ViewLayer& b_view_layer,
BL::DepsgraphObjectInstance& b_instance,
- uint layer_flag,
float motion_time,
bool hide_tris,
BlenderObjectCulling& culling,
@@ -314,10 +314,13 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
}
/* light is handled separately */
- if(object_is_light(b_ob)) {
- /* don't use lights for excluded layers used as mask layer */
- if(!motion && !((layer_flag & view_layer.holdout_layer) &&
- (layer_flag & view_layer.exclude_layer)))
+ if(!motion && object_is_light(b_ob)) {
+ /* TODO: don't use lights for excluded layers used as mask layer,
+ * when dynamic overrides are back. */
+#if 0
+ if(!((layer_flag & view_layer.holdout_layer) &&
+ (layer_flag & view_layer.exclude_layer)))
+#endif
{
sync_light(b_parent,
persistent_id,
@@ -343,21 +346,24 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
/* Visibility flags for both parent and child. */
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_holdout = (layer_flag & view_layer.holdout_layer) != 0 ||
- get_boolean(cobject, "is_holdout");
+ bool use_holdout = get_boolean(cobject, "is_holdout") ||
+ b_parent.holdout_get(b_view_layer);
uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
if(b_parent.ptr.data != b_ob.ptr.data) {
visibility &= object_ray_visibility(b_parent);
}
- /* Make holdout objects on excluded layer invisible for non-camera rays. */
+ /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
+#if 0
if(use_holdout && (layer_flag & view_layer.exclude_layer)) {
visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
}
+#endif
- /* Hide objects not on render layer from camera rays. */
- if(!(layer_flag & view_layer.layer)) {
+ /* Clear camera visibility for indirect only objects. */
+ bool use_indirect_only = b_parent.indirect_only_get(b_view_layer);
+ if(use_indirect_only) {
visibility &= ~PATH_RAY_CAMERA;
}
@@ -583,6 +589,7 @@ void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time)
bool cancel = false;
bool use_portal = false;
+ BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
BL::Depsgraph::mode_enum depsgraph_mode = b_depsgraph.mode();
BL::Depsgraph::object_instances_iterator b_instance_iter;
@@ -604,8 +611,8 @@ void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time)
if(!object_render_hide(b_ob, true, true, hide_tris, depsgraph_mode)) {
/* object itself */
sync_object(b_depsgraph,
+ b_view_layer,
b_instance,
- ~(0), /* until we get rid of layers */
motion_time,
hide_tris,
culling,
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 4c199f4838f..a79c28e43aa 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -738,6 +738,12 @@ static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *a
Py_RETURN_NONE;
}
+static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/)
+{
+ BlenderSession::print_render_stats = true;
+ Py_RETURN_NONE;
+}
+
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
{
vector<DeviceInfo>& devices = Device::available_devices();
@@ -776,6 +782,9 @@ static PyMethodDef methods[] = {
{"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},
{"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
+ /* Statistics. */
+ {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
+
/* Resumable render */
{"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
{"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index cd55155e33b..05adb6f5fe0 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -28,6 +28,7 @@
#include "render/scene.h"
#include "render/session.h"
#include "render/shader.h"
+#include "render/stats.h"
#include "util/util_color.h"
#include "util/util_foreach.h"
@@ -48,6 +49,7 @@ int BlenderSession::num_resumable_chunks = 0;
int BlenderSession::current_resumable_chunk = 0;
int BlenderSession::start_resumable_chunk = 0;
int BlenderSession::end_resumable_chunk = 0;
+bool BlenderSession::print_render_stats = false;
BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
BL::UserPreferences& b_userpref,
@@ -461,15 +463,13 @@ void BlenderSession::render(BL::Depsgraph& b_depsgraph_)
scene->integrator->tag_update(scene);
}
- /* Update number of samples per layer. */
- int samples = sync->get_layer_samples();
- bool bound_samples = sync->get_layer_bound_samples();
- int effective_layer_samples;
+ int effective_layer_samples = session_params.samples;
+ /* TODO: Update number of samples per layer. */
+#if 0
if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
effective_layer_samples = samples;
- else
- effective_layer_samples = session_params.samples;
+#endif
/* Update tile manager if we're doing resumable render. */
update_resumable_tile_manager(effective_layer_samples);
@@ -481,6 +481,12 @@ void BlenderSession::render(BL::Depsgraph& b_depsgraph_)
session->start();
session->wait();
+ if(!b_engine.is_preview() && background && print_render_stats) {
+ RenderStats stats;
+ session->scene->collect_statistics(&stats);
+ printf("Render statistics:\n%s\n", stats.full_report().c_str());
+ }
+
if(session->progress.get_cancel())
break;
}
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 1d727e416a0..2be57f293b4 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -145,6 +145,8 @@ public:
static int start_resumable_chunk;
static int end_resumable_chunk;
+ static bool print_render_stats;
+
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 6129565fec5..62c160ca503 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -517,6 +517,12 @@ static ShaderNode *add_node(Scene *scene,
}
node = hair;
}
+ else if(b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
+ BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
+ PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
+ principled_hair->parametrization = (NodePrincipledHairParametrization) get_enum(b_principled_hair_node.ptr, "parametrization", NODE_PRINCIPLED_HAIR_NUM, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ node = principled_hair;
+ }
else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
PrincipledBsdfNode *principled = new PrincipledBsdfNode();
@@ -1330,7 +1336,7 @@ void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
}
else if(b_world) {
BackgroundNode *background = new BackgroundNode();
- background->color = get_float3(b_world.horizon_color());
+ background->color = get_float3(b_world.color());
graph->add(background);
ShaderNode *out = graph->output();
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index cbca623ece7..93232fbf98f 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -207,6 +207,8 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render,
python_thread_state);
mesh_synced.clear();
+
+ free_data_after_sync(b_depsgraph);
}
/* Integrator */
@@ -363,28 +365,11 @@ void BlenderSync::sync_film()
void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer)
{
/* render layer */
- uint layer_override = get_layer(b_engine.layer_override());
- uint view_layers = layer_override ? layer_override : get_layer(b_scene.layers());
-
view_layer.name = b_view_layer.name();
-
- view_layer.holdout_layer = 0;
- view_layer.exclude_layer = 0;
-
- view_layer.view_layer = view_layers & ~view_layer.exclude_layer;
- view_layer.view_layer |= view_layer.exclude_layer & view_layer.holdout_layer;
-
- view_layer.layer = (1 << 20) - 1;
- view_layer.layer |= view_layer.holdout_layer;
-
- view_layer.material_override = PointerRNA_NULL;
view_layer.use_background_shader = b_view_layer.use_sky();
view_layer.use_background_ao = b_view_layer.use_ao();
view_layer.use_surfaces = b_view_layer.use_solid();
view_layer.use_hair = b_view_layer.use_strand();
-
- view_layer.bound_samples = false;
- view_layer.samples = 0;
}
/* Images */
@@ -566,6 +551,30 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
return passes;
}
+void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
+{
+ /* When viewport display is not needed during render we can force some
+ * caches to be releases from blender side in order to reduce peak memory
+ * footprint during synchronization process.
+ */
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ const bool can_free_caches = BlenderSession::headless || is_interface_locked;
+ if (!can_free_caches) {
+ return;
+ }
+ /* TODO(sergey): We can actually remove the whole dependency graph,
+ * but that will need some API support first.
+ */
+ BL::Depsgraph::objects_iterator b_ob;
+ for(b_depsgraph.objects.begin(b_ob);
+ b_ob != b_depsgraph.objects.end();
+ ++b_ob)
+ {
+ b_ob->cache_release();
+ }
+}
+
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index cd1a37d3f13..e63ef9e5e47 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -78,8 +78,6 @@ public:
void sync_view(BL::SpaceView3D& b_v3d,
BL::RegionView3D& b_rv3d,
int width, int height);
- inline int get_layer_samples() { return view_layer.samples; }
- inline int get_layer_bound_samples() { return view_layer.bound_samples; }
/* get parameters */
static SceneParams get_scene_params(BL::Scene& b_scene,
@@ -126,8 +124,8 @@ private:
bool motion,
int motion_step = 0);
Object *sync_object(BL::Depsgraph& b_depsgraph,
+ BL::ViewLayer& b_view_layer,
BL::DepsgraphObjectInstance& b_instance,
- uint layer_flag,
float motion_time,
bool hide_tris,
BlenderObjectCulling& culling,
@@ -157,6 +155,9 @@ private:
/* Images. */
void sync_images();
+ /* Early data free. */
+ void free_data_after_sync(BL::Depsgraph& b_depsgraph);
+
/* util */
void find_shader(BL::ID& id, vector<Shader*>& used_shaders, Shader *default_shader);
bool BKE_object_is_modified(BL::Object& b_ob);
@@ -188,28 +189,18 @@ private:
struct RenderLayerInfo {
RenderLayerInfo()
- : view_layer(0), layer(0),
- holdout_layer(0), exclude_layer(0),
- material_override(PointerRNA_NULL),
- use_background_shader(true),
+ : use_background_shader(true),
use_background_ao(true),
use_surfaces(true),
- use_hair(true),
- samples(0), bound_samples(false)
+ use_hair(true)
{}
string name;
uint view_layer;
- uint layer; /* This can be safely removed from Cycles. */
- uint holdout_layer; /* This can be safely removed from Cycles. */
- uint exclude_layer; /* This can be safely removed from Cycles. */
- BL::Material material_override; /* This can be safely removed from Cycles. */
bool use_background_shader;
bool use_background_ao;
bool use_surfaces;
bool use_hair;
- int samples; /* This can be safely removed from Cycles. */
- bool bound_samples; /* This can be safely removed from Cycles. */
} view_layer;
Progress &progress;
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 95eef8263d4..be0f8f45399 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -23,6 +23,7 @@
#include "util/util_foreach.h"
#include "util/util_logging.h"
#include "util/util_set.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
@@ -166,11 +167,14 @@ string device_opencl_capabilities(void)
platform_ids.resize(num_platforms);
opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
-#define APPEND_STRING_INFO(func, id, name, what) \
+ typedef char cl_string[1024];
+
+#define APPEND_INFO(func, id, name, what, type) \
do { \
- char data[1024] = "\0"; \
+ type data; \
+ memset(&data, 0, sizeof(data)); \
opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
- result += string_printf("%s: %s\n", name, data); \
+ result += string_printf("%s: %s\n", name, to_string(data).c_str()); \
} while(false)
#define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
do { \
@@ -182,10 +186,10 @@ string device_opencl_capabilities(void)
} \
} \
} while(false)
-#define APPEND_PLATFORM_STRING_INFO(id, name, what) \
- APPEND_STRING_INFO(clGetPlatformInfo, id, "\tPlatform " name, what)
-#define APPEND_DEVICE_STRING_INFO(id, name, what) \
- APPEND_STRING_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
+#define APPEND_PLATFORM_INFO(id, name, what, type) \
+ APPEND_INFO(clGetPlatformInfo, id, "\tPlatform " name, what, type)
+#define APPEND_DEVICE_INFO(id, name, what, type) \
+ APPEND_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what, type)
#define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
@@ -195,11 +199,11 @@ string device_opencl_capabilities(void)
result += string_printf("Platform #%u\n", platform);
- APPEND_PLATFORM_STRING_INFO(platform_id, "Name", CL_PLATFORM_NAME);
- APPEND_PLATFORM_STRING_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR);
- APPEND_PLATFORM_STRING_INFO(platform_id, "Version", CL_PLATFORM_VERSION);
- APPEND_PLATFORM_STRING_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE);
- APPEND_PLATFORM_STRING_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS);
+ APPEND_PLATFORM_INFO(platform_id, "Name", CL_PLATFORM_NAME, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Version", CL_PLATFORM_VERSION, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS, cl_string);
cl_uint num_devices = 0;
opencl_assert(clGetDeviceIDs(platform_ids[platform],
@@ -220,13 +224,16 @@ string device_opencl_capabilities(void)
result += string_printf("\t\tDevice: #%u\n", device);
- APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
+ APPEND_DEVICE_INFO(device_id, "Name", CL_DEVICE_NAME, cl_string);
APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
- APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
- APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
- APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
- APPEND_DEVICE_STRING_INFO(device_id, "Version", CL_DEVICE_VERSION);
- APPEND_DEVICE_STRING_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS);
+ APPEND_DEVICE_INFO(device_id, "Vendor", CL_DEVICE_VENDOR, cl_string);
+ APPEND_DEVICE_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Profile", CL_DEVICE_PROFILE, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Version", CL_DEVICE_VERSION, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Max clock frequency (MHz)", CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
+ APPEND_DEVICE_INFO(device_id, "Max compute units", CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
+ APPEND_DEVICE_INFO(device_id, "Max work group size", CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t);
}
}
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index 9104f64bedd..d6304ba688a 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -1136,6 +1136,21 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
name = get_device_name(device_id);
}
+ /* Special exception for AMD Vega, need to be able to tell
+ * Vega 56 from 64 apart.
+ */
+ if (name == "Radeon RX Vega") {
+ cl_int max_compute_units = 0;
+ if (clGetDeviceInfo(device_id,
+ CL_DEVICE_MAX_COMPUTE_UNITS,
+ sizeof(max_compute_units),
+ &max_compute_units,
+ NULL) == CL_SUCCESS)
+ {
+ name += " " + to_string(max_compute_units);
+ }
+ }
+
/* Distinguish from our native CPU device. */
if(get_device_type(device_id) & CL_DEVICE_TYPE_CPU) {
name += " (OpenCL)";
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index 45ffc8d7d6b..5960d9aa7d5 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -425,20 +425,22 @@ bool Node::equals(const Node& other) const
/* Hash */
+namespace {
+
template<typename T>
-static void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
{
md5.append(((uint8_t*)node) + socket.struct_offset, socket.size());
}
-static void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
{
/* Don't compare 4th element used for padding. */
md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3);
}
template<typename T>
-static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
{
const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset);
for (size_t i = 0; i < a.size(); i++) {
@@ -446,7 +448,7 @@ static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
}
}
-static void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
{
/* Don't compare 4th element used for padding. */
const array<float3>& a = *(const array<float3>*)(((char*)node) + socket.struct_offset);
@@ -455,6 +457,8 @@ static void float3_array_hash(const Node *node, const SocketType& socket, MD5Has
}
}
+} // namespace
+
void Node::hash(MD5Hash& md5)
{
md5.append(type->name.string());
@@ -495,4 +499,77 @@ void Node::hash(MD5Hash& md5)
}
}
+namespace {
+
+template<typename T>
+size_t array_size_in_bytes(const Node *node, const SocketType& socket)
+{
+ const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset);
+ return a.size() * sizeof(T);
+}
+
+} // namespace
+
+size_t Node::get_total_size_in_bytes() const
+{
+ size_t total_size = 0;
+ foreach(const SocketType& socket, type->inputs) {
+ switch(socket.type) {
+ case SocketType::BOOLEAN:
+ case SocketType::FLOAT:
+ case SocketType::INT:
+ case SocketType::UINT:
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL:
+ case SocketType::POINT2:
+ case SocketType::CLOSURE:
+ case SocketType::STRING:
+ case SocketType::ENUM:
+ case SocketType::TRANSFORM:
+ case SocketType::NODE:
+ total_size += socket.size();
+ break;
+
+ case SocketType::BOOLEAN_ARRAY:
+ total_size += array_size_in_bytes<bool>(this, socket);
+ break;
+ case SocketType::FLOAT_ARRAY:
+ total_size += array_size_in_bytes<float>(this, socket);
+ break;
+ case SocketType::INT_ARRAY:
+ total_size += array_size_in_bytes<int>(this, socket);
+ break;
+ case SocketType::COLOR_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::VECTOR_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::POINT_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::NORMAL_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::POINT2_ARRAY:
+ total_size += array_size_in_bytes<float2>(this, socket);
+ break;
+ case SocketType::STRING_ARRAY:
+ total_size += array_size_in_bytes<ustring>(this, socket);
+ break;
+ case SocketType::TRANSFORM_ARRAY:
+ total_size += array_size_in_bytes<Transform>(this, socket);
+ break;
+ case SocketType::NODE_ARRAY:
+ total_size += array_size_in_bytes<void*>(this, socket);
+ break;
+
+ case SocketType::UNDEFINED: break;
+ }
+ }
+ return total_size;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index a738bfe197e..11695a8631d 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -92,6 +92,9 @@ struct Node
/* compute hash of node and its socket values */
void hash(MD5Hash& md5);
+ /* Get total size of this node. */
+ size_t get_total_size_in_bytes() const;
+
ustring name;
const NodeType *type;
};
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index 671ae2d815a..e045777e969 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -134,7 +134,7 @@ NodeType::~NodeType()
void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset,
const void *default_value, const NodeEnum *enum_values,
- const NodeType **node_type, int flags, int extra_flags)
+ const NodeType **node_type, int flags, int extra_flags)
{
SocketType socket;
socket.name = name;
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index d4e2dbceff6..1d565794b27 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -114,9 +114,9 @@ struct NodeType
void register_input(ustring name, ustring ui_name, SocketType::Type type,
int struct_offset, const void *default_value,
- const NodeEnum *enum_values = NULL,
- const NodeType **node_type = NULL,
- int flags = 0, int extra_flags = 0);
+ const NodeEnum *enum_values = NULL,
+ const NodeType **node_type = NULL,
+ int flags = 0, int extra_flags = 0);
void register_output(ustring name, ustring ui_name, SocketType::Type type);
const SocketType *find_input(ustring name) const;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 092bec08a51..c4cad17429d 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -156,6 +156,7 @@ set(SRC_CLOSURE_HEADERS
closure/volume.h
closure/bsdf_principled_diffuse.h
closure/bsdf_principled_sheen.h
+ closure/bsdf_hair_principled.h
)
set(SRC_SVM_HEADERS
diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h
index f2379efc656..2ee29ac9c27 100644
--- a/intern/cycles/kernel/bvh/bvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/bvh_volume_all.h
@@ -212,14 +212,16 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect_array->t = isect_t;
if(num_hits == max_hits) {
#if BVH_FEATURE(BVH_INSTANCING)
+ if(object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
}
#endif /* BVH_FEATURE(BVH_INSTANCING) */
return num_hits;
@@ -257,14 +259,16 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect_array->t = isect_t;
if(num_hits == max_hits) {
# if BVH_FEATURE(BVH_INSTANCING)
+ if(object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
}
# endif /* BVH_FEATURE(BVH_INSTANCING) */
return num_hits;
diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h
index ac5f58a9a51..1e454e4d36b 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h
@@ -279,14 +279,16 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect_array->t = isect_t;
if(num_hits == max_hits) {
#if BVH_FEATURE(BVH_INSTANCING)
+ if(object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
}
#endif /* BVH_FEATURE(BVH_INSTANCING) */
return num_hits;
@@ -317,14 +319,16 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect_array->t = isect_t;
if(num_hits == max_hits) {
# if BVH_FEATURE(BVH_INSTANCING)
+ if(object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
+ for(int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array-i-1)->t *= t_fac;
+ }
}
# endif /* BVH_FEATURE(BVH_INSTANCING) */
return num_hits;
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index f191b812f11..3a9629ea9d7 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -27,6 +27,7 @@
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
#include "kernel/closure/bsdf_toon.h"
#include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_hair_principled.h"
#include "kernel/closure/bsdf_principled_diffuse.h"
#include "kernel/closure/bsdf_principled_sheen.h"
#include "kernel/closure/bssrdf.h"
@@ -171,6 +172,10 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
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;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
#ifdef __PRINCIPLED__
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
@@ -284,6 +289,9 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
@@ -366,6 +374,9 @@ float3 bsdf_eval(KernelGlobals *kg,
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
@@ -424,6 +435,9 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ bsdf_principled_hair_blur(sc, roughness);
+ break;
default:
break;
}
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
new file mode 100644
index 00000000000..4ee58089384
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifdef __KERNEL_CPU__
+#include <fenv.h>
+#endif
+
+#include "kernel/kernel_color.h"
+
+#ifndef __BSDF_HAIR_PRINCIPLED_H__
+#define __BSDF_HAIR_PRINCIPLED_H__
+
+CCL_NAMESPACE_BEGIN
+
+typedef ccl_addr_space struct PrincipledHairExtra {
+ /* Geometry data. */
+ float4 geom;
+} PrincipledHairExtra;
+
+typedef ccl_addr_space struct PrincipledHairBSDF {
+ SHADER_CLOSURE_BASE;
+
+ /* Absorption coefficient. */
+ float3 sigma;
+ /* Variance of the underlying logistic distribution. */
+ float v;
+ /* Scale factor of the underlying logistic distribution. */
+ float s;
+ /* Cuticle tilt angle. */
+ float alpha;
+ /* IOR. */
+ float eta;
+ /* Effective variance for the diffuse bounce only. */
+ float m0_roughness;
+
+ /* Extra closure. */
+ PrincipledHairExtra *extra;
+} PrincipledHairBSDF;
+
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF), "PrincipledHairBSDF is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra), "PrincipledHairExtra is too large!");
+
+ccl_device_inline float cos_from_sin(const float s)
+{
+ return safe_sqrtf(1.0f - s*s);
+}
+
+/* Gives the change in direction in the normal plane for the given angles and p-th-order scattering. */
+ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
+{
+ return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
+}
+
+/* Remaps the given angle to [-pi, pi]. */
+ccl_device_inline float wrap_angle(float a)
+{
+ while(a > M_PI_F) {
+ a -= M_2PI_F;
+ }
+ while(a < -M_PI_F) {
+ a += M_2PI_F;
+ }
+ return a;
+}
+
+/* Logistic distribution function. */
+ccl_device_inline float logistic(float x, float s)
+{
+ float v = expf(-fabsf(x)/s);
+ return v / (s * sqr(1.0f + v));
+}
+
+/* Logistic cumulative density function. */
+ccl_device_inline float logistic_cdf(float x, float s)
+{
+ float arg = -x/s;
+ /* expf() overflows if arg >= 89.0. */
+ if(arg > 88.0f) {
+ return 0.0f;
+ }
+ else {
+ return 1.0f / (1.0f + expf(arg));
+ }
+}
+
+/* Numerical approximation to the Bessel function of the first kind. */
+ccl_device_inline float bessel_I0(float x)
+{
+ x = sqr(x);
+ float val = 1.0f + 0.25f*x;
+ float pow_x_2i = sqr(x);
+ uint64_t i_fac_2 = 1;
+ int pow_4_i = 16;
+ for(int i = 2; i < 10; i++) {
+ i_fac_2 *= i*i;
+ float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
+ if(val == newval) {
+ return val;
+ }
+ val = newval;
+ pow_x_2i *= x;
+ pow_4_i *= 4;
+ }
+ return val;
+}
+
+/* Logarithm of the Bessel function of the first kind. */
+ccl_device_inline float log_bessel_I0(float x)
+{
+ if (x > 12.0f) {
+ /* log(1/x) == -log(x) iff x > 0.
+ * This is only used with positive cosines */
+ return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
+ }
+ else {
+ return logf(bessel_I0(x));
+ }
+}
+
+/* Logistic distribution limited to the interval [-pi, pi]. */
+ccl_device_inline float trimmed_logistic(float x, float s)
+{
+ /* The logistic distribution is symmetric and centered around zero,
+ * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
+ * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
+ float scaling_fac = 1.0f - 2.0f*logistic_cdf(-M_PI_F, s);
+ float val = logistic(x, s);
+ return safe_divide(val, scaling_fac);
+}
+
+/* Sampling function for the trimmed logistic function. */
+ccl_device_inline float sample_trimmed_logistic(float u, float s)
+{
+ float cdf_minuspi = logistic_cdf(-M_PI_F, s);
+ float x = -s*logf(1.0f / (u*(1.0f - 2.0f*cdf_minuspi) + cdf_minuspi) - 1.0f);
+ return clamp(x, -M_PI_F, M_PI_F);
+}
+
+/* Azimuthal scattering function Np. */
+ccl_device_inline float azimuthal_scattering(float phi,
+ int p,
+ float s,
+ float gamma_o,
+ float gamma_t)
+{
+ float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
+ float val = trimmed_logistic(phi_o, s);
+ return val;
+}
+
+/* Longitudinal scattering function Mp. */
+ccl_device_inline float longitudinal_scattering(float sin_theta_i,
+ float cos_theta_i,
+ float sin_theta_o,
+ float cos_theta_o,
+ float v)
+{
+ float inv_v = 1.0f/v;
+ float cos_arg = cos_theta_i * cos_theta_o * inv_v;
+ float sin_arg = sin_theta_i * sin_theta_o * inv_v;
+ if(v <= 0.1f) {
+ float i0 = log_bessel_I0(cos_arg);
+ float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f*inv_v));
+ return val;
+ }
+ else {
+ float i0 = bessel_I0(cos_arg);
+ float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
+ return val;
+ }
+}
+
+/* Combine the three values using their luminances. */
+ccl_device_inline float4 combine_with_energy(KernelGlobals *kg, float3 c)
+{
+ return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
+}
+
+#ifdef __HAIR__
+/* Set up the hair closure. */
+ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bsdf)
+{
+ bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+ bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
+ bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
+ /* Apply Primary Reflection Roughness modifier. */
+ bsdf->m0_roughness = clamp(bsdf->m0_roughness*bsdf->v, 0.001f, 1.0f);
+
+ /* Map from roughness_u and roughness_v to variance and scale factor. */
+ bsdf->v = sqr(0.726f*bsdf->v + 0.812f*sqr(bsdf->v) + 3.700f*pow20(bsdf->v));
+ bsdf->s = (0.265f*bsdf->s + 1.194f*sqr(bsdf->s) + 5.372f*pow22(bsdf->s))*M_SQRT_PI_8_F;
+ bsdf->m0_roughness = sqr(0.726f*bsdf->m0_roughness + 0.812f*sqr(bsdf->m0_roughness) + 3.700f*pow20(bsdf->m0_roughness));
+
+ /* Compute local frame, aligned to curve tangent and ray direction. */
+ float3 X = safe_normalize(sd->dPdu);
+ float3 Y = safe_normalize(cross(X, sd->I));
+ float3 Z = safe_normalize(cross(X, Y));
+ /* TODO: the solution below works where sd->Ng is the normal
+ * pointing from the center of the curve to the shading point.
+ * It doesn't work for triangles, see https://developer.blender.org/T43625 */
+
+ /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
+ * the center, to grazing the other edge. This is the sine of the angle
+ * between sd->Ng and Z, as seen from the tangent X. */
+
+ /* TODO: we convert this value to a cosine later and discard the sign, so
+ * we could probably save some operations. */
+ float h = dot(cross(sd->Ng, X), Z);
+
+ kernel_assert(fabsf(h) < 1.0f + 1e-4f);
+ kernel_assert(isfinite3_safe(Y));
+ kernel_assert(isfinite_safe(h));
+
+ bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+}
+
+#endif /* __HAIR__ */
+
+/* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
+ccl_device_inline void hair_attenuation(KernelGlobals *kg,
+ float f,
+ float3 T,
+ float4 *Ap)
+{
+ /* Primary specular (R). */
+ Ap[0] = make_float4(f, f, f, f);
+
+ /* Transmission (TT). */
+ float3 col = sqr(1.0f - f) * T;
+ Ap[1] = combine_with_energy(kg, col);
+
+ /* Secondary specular (TRT). */
+ col *= T*f;
+ Ap[2] = combine_with_energy(kg, col);
+
+ /* Residual component (TRRT+). */
+ col *= safe_divide_color(T*f, make_float3(1.0f, 1.0f, 1.0f) - T*f);
+ Ap[3] = combine_with_energy(kg, col);
+
+ /* Normalize sampling weights. */
+ float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
+ float fac = safe_divide(1.0f, totweight);
+
+ Ap[0].w *= fac;
+ Ap[1].w *= fac;
+ Ap[2].w *= fac;
+ Ap[3].w *= fac;
+}
+
+/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
+ccl_device_inline void hair_alpha_angles(float sin_theta_i,
+ float cos_theta_i,
+ float alpha,
+ float *angles)
+{
+ float sin_1alpha = sinf(alpha);
+ float cos_1alpha = cos_from_sin(sin_1alpha);
+ float sin_2alpha = 2.0f*sin_1alpha*cos_1alpha;
+ float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
+ float sin_4alpha = 2.0f*sin_2alpha*cos_2alpha;
+ float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
+
+ angles[0] = sin_theta_i*cos_2alpha + cos_theta_i*sin_2alpha;
+ angles[1] = fabsf(cos_theta_i*cos_2alpha - sin_theta_i*sin_2alpha);
+ angles[2] = sin_theta_i*cos_1alpha - cos_theta_i*sin_1alpha;
+ angles[3] = fabsf(cos_theta_i*cos_1alpha + sin_theta_i*sin_1alpha);
+ angles[4] = sin_theta_i*cos_4alpha - cos_theta_i*sin_4alpha;
+ angles[5] = fabsf(cos_theta_i*cos_4alpha + sin_theta_i*sin_4alpha);
+}
+
+/* Evaluation function for our shader. */
+ccl_device float3 bsdf_principled_hair_eval(KernelGlobals *kg,
+ const ShaderData *sd,
+ const ShaderClosure *sc,
+ const float3 omega_in,
+ float *pdf)
+{
+ kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
+
+ const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
+ float3 Y = float4_to_float3(bsdf->extra->geom);
+
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-4f);
+ float3 Z = safe_normalize(cross(X, Y));
+
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+ float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
+
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
+
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
+
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
+
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+
+ float sin_theta_i = wi.x;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+ float phi_i = atan2f(wi.z, wi.y);
+
+ float phi = phi_i - phi_o;
+
+ float angles[6];
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+
+ float4 F;
+ float Mp, Np;
+
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ *pdf = F.w;
+ return float4_to_float3(F);
+}
+
+/* Sampling function for the hair shader. */
+ccl_device int bsdf_principled_hair_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ ShaderData *sd,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
+{
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*) sc;
+
+ float3 Y = float4_to_float3(bsdf->extra->geom);
+
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-4f);
+ float3 Z = safe_normalize(cross(X, Y));
+
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+
+ float2 u[2];
+ u[0] = make_float2(randu, randv);
+ u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
+ u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
+
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
+
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
+
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
+
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
+
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+
+ int p = 0;
+ for(; p < 3; p++) {
+ if(u[0].x < Ap[p].w) {
+ break;
+ }
+ u[0].x -= Ap[p].w;
+ }
+
+ float v = bsdf->v;
+ if(p == 1) {
+ v *= 0.25f;
+ }
+ if(p >= 2) {
+ v *= 4.0f;
+ }
+
+ u[1].x = max(u[1].x, 1e-5f);
+ float fac = 1.0f + v*logf(u[1].x + (1.0f - u[1].x)*expf(-2.0f/v));
+ float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+
+ float angles[6];
+ if(p < 3) {
+ hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
+ sin_theta_i = angles[2*p];
+ cos_theta_i = angles[2*p+1];
+ }
+
+ float phi;
+ if(p < 3) {
+ phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
+ }
+ else {
+ phi = M_2PI_F*u[0].y;
+ }
+ float phi_i = phi_o + phi;
+
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+
+ float4 F;
+ float Mp, Np;
+
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ *eval = float4_to_float3(F);
+ *pdf = F.w;
+
+ *omega_in = X*sin_theta_i + Y*cos_theta_i*cosf(phi_i) + Z*cos_theta_i*sinf(phi_i);
+
+#ifdef __RAY_DIFFERENTIALS__
+ float3 N = safe_normalize(sd->I + *omega_in);
+ *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
+ *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
+#endif
+
+ return LABEL_GLOSSY|((p == 0)? LABEL_REFLECT : LABEL_TRANSMIT);
+}
+
+/* Implements Filter Glossy by capping the effective roughness. */
+ccl_device void bsdf_principled_hair_blur(ShaderClosure *sc, float roughness)
+{
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)sc;
+
+ bsdf->v = fmaxf(roughness, bsdf->v);
+ bsdf->s = fmaxf(roughness, bsdf->s);
+ bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index e35267f02bf..dea0c742ed7 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -23,6 +23,33 @@ CCL_NAMESPACE_BEGIN
#ifdef __HAIR__
+/* Interpolation of curve geometry */
+
+ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float fc = 0.71f;
+ float data[4];
+ float t2 = t * t;
+ data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
+ data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
+ data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
+ data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
+ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float data[4];
+ float fc = 0.71f;
+ float t2 = t * t;
+ float t3 = t2 * t;
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
/* Reading attributes on various curve elements */
ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h
index 46c3f408f0b..4cfbe21685c 100644
--- a/intern/cycles/kernel/geom/geom_curve_intersect.h
+++ b/intern/cycles/kernel/geom/geom_curve_intersect.h
@@ -752,31 +752,6 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
#endif
}
-ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
-{
- float fc = 0.71f;
- float data[4];
- float t2 = t * t;
- data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
- data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
- data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
- data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
-}
-
-ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
-{
- float data[4];
- float fc = 0.71f;
- float t2 = t * t;
- float t3 = t2 * t;
- data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
- data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
- data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
- data[3] = fc * t3 - fc * t2;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
-}
-
ccl_device_inline float3 curve_refine(KernelGlobals *kg,
ShaderData *sd,
const Intersection *isect,
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index d1ae10a0384..3f7e264fbee 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -123,6 +123,7 @@
#define fmaxf(x, y) fmax(((float)(x)), ((float)(y)))
#define fminf(x, y) fmin(((float)(x)), ((float)(y)))
#define fmodf(x, y) fmod((float)(x), (float)(y))
+#define sinhf(x) sinh(((float)(x)))
#ifndef __CL_USE_NATIVE__
# define sinf(x) native_sin(((float)(x)))
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 32cb924d25f..262d7df1364 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -72,24 +72,17 @@ ccl_device_inline float rect_light_sample(float3 P,
float y0 = dot(dir, y);
float x1 = x0 + axisu_len;
float y1 = y0 + axisv_len;
- /* Create vectors to four vertices. */
- float3 v00 = make_float3(x0, y0, z0);
- float3 v01 = make_float3(x0, y1, z0);
- float3 v10 = make_float3(x1, y0, z0);
- float3 v11 = make_float3(x1, y1, z0);
- /* Compute normals to edges. */
- float3 n0 = normalize(cross(v00, v10));
- float3 n1 = normalize(cross(v10, v11));
- float3 n2 = normalize(cross(v11, v01));
- float3 n3 = normalize(cross(v01, v00));
/* Compute internal angles (gamma_i). */
- float g0 = safe_acosf(-dot(n0, n1));
- float g1 = safe_acosf(-dot(n1, n2));
- float g2 = safe_acosf(-dot(n2, n3));
- float g3 = safe_acosf(-dot(n3, n0));
+ float4 diff = make_float4(x0, y1, x1, y0) - make_float4(x1, y0, x0, y1);
+ float4 nz = make_float4(y0, x1, y1, x0) * diff;
+ nz = nz / sqrt(z0 * z0 * diff * diff + nz * nz);
+ float g0 = safe_acosf(-nz.x * nz.y);
+ float g1 = safe_acosf(-nz.y * nz.z);
+ float g2 = safe_acosf(-nz.z * nz.w);
+ float g3 = safe_acosf(-nz.w * nz.x);
/* Compute predefined constants. */
- float b0 = n0.z;
- float b1 = n2.z;
+ float b0 = nz.x;
+ float b1 = nz.z;
float b0sq = b0 * b0;
float k = M_2PI_F - g2 - g3;
/* Compute solid angle from internal angles. */
diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h
index 49dc1f08cc1..09a3fe8f23d 100644
--- a/intern/cycles/kernel/kernel_montecarlo.h
+++ b/intern/cycles/kernel/kernel_montecarlo.h
@@ -184,6 +184,35 @@ ccl_device float2 regular_polygon_sample(float corners, float rotation, float u,
return make_float2(cr*p.x - sr*p.y, sr*p.x + cr*p.y);
}
+ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N)
+{
+ float3 R = 2*dot(N, I)*N - I;
+ if(dot(Ng, R) >= 0.05f) {
+ return N;
+ }
+
+ /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane.
+ * The X axis is found by normalizing the component of N that's orthogonal to Ng.
+ * The Y axis isn't actually needed.
+ */
+ float3 X = normalize(N - dot(N, Ng)*Ng);
+
+ /* Calculate N.z and N.x in the local coordinate system. */
+ float Iz = dot(I, Ng);
+ float Ix2 = sqr(dot(I, X)), Iz2 = sqr(Iz);
+ float Ix2Iz2 = Ix2 + Iz2;
+
+ float a = sqrtf(Ix2*(Ix2Iz2 - sqr(0.05f)));
+ float b = Iz*0.05f + Ix2Iz2;
+ float c = (a + b > 0.0f)? (a + b) : (-a + b);
+
+ float Nz = sqrtf(0.5f * c * (1.0f / Ix2Iz2));
+ float Nx = sqrtf(1.0f - sqr(Nz));
+
+ /* Transform back into global coordinates. */
+ return Nx*X + Nz*Ng;
+}
+
CCL_NAMESPACE_END
#endif /* __KERNEL_MONTECARLO_CL__ */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 69ee66b3dd5..85548484873 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -54,7 +54,7 @@ CCL_NAMESPACE_BEGIN
#define PRIM_NONE (~0)
#define LAMP_NONE (~0)
-#define VOLUME_STACK_SIZE 16
+#define VOLUME_STACK_SIZE 32
/* Split kernel constants */
#define WORK_POOL_SIZE_GPU 64
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index a7072c3ad03..d71761a97bc 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -91,7 +91,7 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals *kg,
ccl_device float3 volume_color_transmittance(float3 sigma, float t)
{
- return make_float3(expf(-sigma.x * t), expf(-sigma.y * t), expf(-sigma.z * t));
+ return exp3(-sigma * t);
}
ccl_device float kernel_volume_channel_get(float3 value, int channel)
@@ -234,7 +234,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
sum += (-sigma_t * (new_t - t));
if((i & 0x07) == 0) { /* ToDo: Other interval? */
- tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
+ tp = *throughput * exp3(sum);
/* stop if nearly all light is blocked */
if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
@@ -246,7 +246,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
t = new_t;
if(t == ray->t) {
/* Update throughput in case we haven't done it above */
- tp = *throughput * make_float3(expf(sum.x), expf(sum.y), expf(sum.z));
+ tp = *throughput * exp3(sum);
break;
}
}
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 581b38e65c0..8c7ae30725c 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -4,7 +4,7 @@
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
- * Modifications Copyright 2011, Blender Foundation.
+ * Modifications Copyright 2011-2018, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -59,6 +59,7 @@
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
#include "kernel/closure/bsdf_toon.h"
#include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_hair_principled.h"
#include "kernel/closure/bsdf_principled_diffuse.h"
#include "kernel/closure/bsdf_principled_sheen.h"
#include "kernel/closure/volume.h"
@@ -176,6 +177,61 @@ BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, principled_sheen, PrincipledSheenBsdf,
CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
+/* PRINCIPLED HAIR BSDF */
+class PrincipledHairClosure : public CBSDFClosure {
+public:
+ PrincipledHairBSDF params;
+
+ PrincipledHairBSDF *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)bsdf_alloc_osl(sd, sizeof(PrincipledHairBSDF), weight, &params);
+ if(!bsdf) {
+ return NULL;
+ }
+
+ PrincipledHairExtra *extra = (PrincipledHairExtra*)closure_alloc_extra(sd, sizeof(PrincipledHairExtra));
+ if(!extra) {
+ return NULL;
+ }
+
+ bsdf->extra = extra;
+ return bsdf;
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ if(!skip(sd, path_flag, LABEL_GLOSSY))
+ {
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)alloc(sd, path_flag, weight);
+ if (!bsdf)
+ {
+ return;
+ }
+
+ sd->flag |= (bsdf) ? bsdf_principled_hair_setup(sd, bsdf) : 0;
+ }
+ }
+};
+
+static ClosureParam *closure_bsdf_principled_hair_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.sigma),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.v),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.s),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.m0_roughness),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.alpha),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.eta),
+ CLOSURE_STRING_KEYPARAM(PrincipledHairClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(PrincipledHairClosure)
+ };
+
+ return params;
+}
+
+CCLOSURE_PREPARE(closure_bsdf_principled_hair_prepare, PrincipledHairClosure)
+
/* DISNEY PRINCIPLED CLEARCOAT */
class PrincipledClearcoatClosure : public CBSDFClosure {
public:
@@ -322,6 +378,9 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
register_closure(ss, "hair_transmission", id++,
bsdf_hair_transmission_params(), bsdf_hair_transmission_prepare);
+ register_closure(ss, "principled_hair", id++,
+ closure_bsdf_principled_hair_params(), closure_bsdf_principled_hair_prepare);
+
register_closure(ss, "henyey_greenstein", id++,
closure_henyey_greenstein_params(), closure_henyey_greenstein_prepare);
register_closure(ss, "absorption", id++,
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 857cc84afd2..d9aeb9ab9fb 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -79,6 +79,7 @@ void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *,
void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_principled_clearcoat_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_principled_hair_prepare(OSL::RendererServices *, int id, void *data);
#define CCLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 9ee78d160a4..4740db27d4e 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -85,6 +85,7 @@ set(SRC_OSL
node_wave_texture.osl
node_wireframe.osl
node_hair_bsdf.osl
+ node_principled_hair_bsdf.osl
node_uv_map.osl
node_principled_bsdf.osl
node_rgb_to_bw.osl
diff --git a/intern/cycles/kernel/shaders/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl
index 7f01cf2ca91..a2a4468d5f3 100644
--- a/intern/cycles/kernel/shaders/node_bump.osl
+++ b/intern/cycles/kernel/shaders/node_bump.osl
@@ -64,5 +64,7 @@ surface node_bump(
if (use_object_space) {
NormalOut = normalize(transform("object", "world", NormalOut));
}
+
+ NormalOut = ensure_valid_reflection(Ng, I, NormalOut);
}
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index 41bcac4fb10..fda6f12a5da 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -88,5 +88,7 @@ shader node_normal_map(
if (Strength != 1.0)
Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
+
+ Normal = ensure_valid_reflection(Ng, I, Normal);
}
diff --git a/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
new file mode 100644
index 00000000000..757a88f8ece
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018 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 "stdosl.h"
+
+color log3(color a)
+{
+ return color(log(a[0]), log(a[1]), log(a[2]));
+}
+
+color sigma_from_concentration(float eumelanin, float pheomelanin)
+{
+ return eumelanin*color(0.506, 0.841, 1.653) + pheomelanin*color(0.343, 0.733, 1.924);
+}
+
+color sigma_from_reflectance(color c, float azimuthal_roughness)
+{
+ float x = azimuthal_roughness;
+ float roughness_fac = (((((0.245*x) + 5.574)*x - 10.73)*x + 2.532)*x - 0.215)*x + 5.969;
+ color sigma = log3(c) / roughness_fac;
+ return sigma * sigma;
+}
+
+shader node_principled_hair_bsdf(
+ color Color = color(0.017513, 0.005763, 0.002059),
+ float Melanin = 0.8,
+ float MelaninRedness = 1.0,
+ float RandomColor = 0.0,
+ color Tint = 1.0,
+ color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
+ normal Normal = Ng,
+ string parametrization = "Absorption coefficient",
+ float Offset = radians(2),
+ float Roughness = 0.3,
+ float RadialRoughness = 0.3,
+ float RandomRoughness = 0.0,
+ float Coat = 0.0,
+ float IOR = 1.55,
+ string AttrRandom = "geom:curve_random",
+ float Random = 0.0,
+
+ output closure color BSDF = 0)
+{
+ /* Get random value from curve in none is specified. */
+ float random_value = 0.0;
+
+ if (isconnected(Random)) {
+ random_value = Random;
+ }
+ else {
+ getattribute(AttrRandom, random_value);
+ }
+
+ /* Compute roughness. */
+ float factor_random_roughness = 1.0 + 2.0*(random_value - 0.5)*RandomRoughness;
+ float m0_roughness = 1.0 - clamp(Coat, 0.0, 1.0);
+ float roughness = Roughness*factor_random_roughness;
+ float radial_roughness = RadialRoughness*factor_random_roughness;
+
+ /* Compute absorption. */
+ color sigma;
+
+ if (parametrization == "Absorption coefficient") {
+ sigma = AbsorptionCoefficient;
+ }
+ else if (parametrization == "Melanin concentration") {
+ /* Randomize melanin. */
+ float factor_random_color = 1.0 + 2.0*(random_value - 0.5) * RandomColor;
+ float melanin = Melanin * factor_random_color;
+
+ /* Map melanin 0..inf from more perceptually linear 0..1. */
+ melanin = -log(max(1.0 - melanin, 0.0001));
+
+ /* Benedikt Bitterli's melanin ratio remapping. */
+ float eumelanin = melanin * (1.0 - MelaninRedness);
+ float pheomelanin = melanin * MelaninRedness;
+ color melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
+
+ /* Optional tint. */
+ color tint_sigma = sigma_from_reflectance(Tint, radial_roughness);
+ sigma = melanin_sigma + tint_sigma;
+ }
+ else if (parametrization == "Direct coloring"){
+ sigma = sigma_from_reflectance(Color, radial_roughness);
+ }
+ else {
+ /* Fallback to brownish hair, same as defaults for melanin. */
+ sigma = sigma_from_concentration(0.0, 0.8054375);
+ }
+
+ BSDF = principled_hair(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
+}
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 82223ca0219..4a8378796ba 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -282,6 +282,36 @@ point rotate (point p, float angle, point a, point b)
return transform (M, p-a) + a;
}
+normal ensure_valid_reflection(normal Ng, vector I, normal N)
+{
+ float sqr(float x) { return x*x; }
+
+ vector R = 2*dot(N, I)*N - I;
+ if (dot(Ng, R) >= 0.05) {
+ return N;
+ }
+
+ /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane.
+ * The X axis is found by normalizing the component of N that's orthogonal to Ng.
+ * The Y axis isn't actually needed.
+ */
+ vector X = normalize(N - dot(N, Ng)*Ng);
+
+ /* Calculate N.z and N.x in the local coordinate system. */
+ float Ix = dot(I, X), Iz = dot(I, Ng);
+ float Ix2 = sqr(dot(I, X)), Iz2 = sqr(dot(I, Ng));
+ float Ix2Iz2 = Ix2 + Iz2;
+
+ float a = sqrt(Ix2*(Ix2Iz2 - sqr(0.05)));
+ float b = Iz*0.05 + Ix2Iz2;
+ float c = (a + b > 0.0)? (a + b) : (-a + b);
+
+ float Nz = sqrt(0.5 * c * (1.0 / Ix2Iz2));
+ float Nx = sqrt(1.0 - sqr(Nz));
+
+ /* Transform back into global coordinates. */
+ return Nx*X + Nz*Ng;
+}
// Color functions
@@ -554,6 +584,7 @@ closure color bssrdf(string method, normal N, vector radius, color albedo) BUILT
// Hair
closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
closure color hair_transmission(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
+closure color principled_hair(normal N, color sigma, float roughnessu, float roughnessv, float coat, float alpha, float eta) BUILTIN;
// Volume
closure color henyey_greenstein(float g) BUILTIN;
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 4de9cfb88db..aa253223c93 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -16,6 +16,21 @@
CCL_NAMESPACE_BEGIN
+/* Hair Melanin */
+
+ccl_device_inline float3 sigma_from_concentration(float eumelanin, float pheomelanin)
+{
+ return eumelanin*make_float3(0.506f, 0.841f, 1.653f) + pheomelanin*make_float3(0.343f, 0.733f, 1.924f);
+}
+
+ccl_device_inline float3 sigma_from_reflectance(float3 color, float azimuthal_roughness)
+{
+ float x = azimuthal_roughness;
+ float roughness_fac = (((((0.245f*x) + 5.574f)*x - 10.73f)*x + 2.532f)*x - 0.215f)*x + 5.969f;
+ float3 sigma = log3(color) / roughness_fac;
+ return sigma * sigma;
+}
+
/* Closure Nodes */
ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int type, float eta, float roughness, bool refract)
@@ -243,7 +258,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 spec_weight = weight * specular_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
- if(!bsdf){
+ if(!bsdf) {
break;
}
@@ -722,6 +737,107 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
#ifdef __HAIR__
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: {
+ uint4 data_node2 = read_node(kg, offset);
+ uint4 data_node3 = read_node(kg, offset);
+ uint4 data_node4 = read_node(kg, offset);
+
+ float3 weight = sd->svm_closure_weight * mix_weight;
+
+ uint offset_ofs, ior_ofs, color_ofs, parametrization;
+ decode_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, &parametrization);
+ float alpha = stack_load_float_default(stack, offset_ofs, data_node.z);
+ float ior = stack_load_float_default(stack, ior_ofs, data_node.w);
+
+ uint coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs;
+ decode_node_uchar4(data_node2.x, &coat_ofs, &melanin_ofs, &melanin_redness_ofs, &absorption_coefficient_ofs);
+
+ uint tint_ofs, random_ofs, random_color_ofs, random_roughness_ofs;
+ decode_node_uchar4(data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &random_roughness_ofs);
+
+ const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node4.y);
+ float random = 0.0f;
+ if (attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
+ random = primitive_attribute_float(kg, sd, attr_descr_random, NULL, NULL);
+ }
+ else {
+ random = stack_load_float_default(stack, random_ofs, data_node3.y);
+ }
+
+
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)bsdf_alloc(sd, sizeof(PrincipledHairBSDF), weight);
+ if(bsdf) {
+ PrincipledHairExtra *extra = (PrincipledHairExtra*)closure_alloc_extra(sd, sizeof(PrincipledHairExtra));
+
+ if (!extra)
+ break;
+
+ /* Random factors range: [-randomization/2, +randomization/2]. */
+ float random_roughness = stack_load_float_default(stack, random_roughness_ofs, data_node3.w);
+ float factor_random_roughness = 1.0f + 2.0f*(random - 0.5f)*random_roughness;
+ float roughness = param1 * factor_random_roughness;
+ float radial_roughness = param2 * factor_random_roughness;
+
+ /* Remap Coat value to [0, 100]% of Roughness. */
+ float coat = stack_load_float_default(stack, coat_ofs, data_node2.y);
+ float m0_roughness = 1.0f - clamp(coat, 0.0f, 1.0f);
+
+ bsdf->N = N;
+ bsdf->v = roughness;
+ bsdf->s = radial_roughness;
+ bsdf->m0_roughness = m0_roughness;
+ bsdf->alpha = alpha;
+ bsdf->eta = ior;
+ bsdf->extra = extra;
+
+ switch(parametrization) {
+ case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: {
+ float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
+ bsdf->sigma = absorption_coefficient;
+ break;
+ }
+ case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
+ float melanin = stack_load_float_default(stack, melanin_ofs, data_node2.z);
+ float melanin_redness = stack_load_float_default(stack, melanin_redness_ofs, data_node2.w);
+
+ /* Randomize melanin. */
+ float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
+ random_color = clamp(random_color, 0.0f, 1.0f);
+ float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
+ melanin *= factor_random_color;
+
+ /* Map melanin 0..inf from more perceptually linear 0..1. */
+ melanin = -logf(fmaxf(1.0f - melanin, 0.0001f));
+
+ /* Benedikt Bitterli's melanin ratio remapping. */
+ float eumelanin = melanin * (1.0f - melanin_redness);
+ float pheomelanin = melanin * melanin_redness;
+ float3 melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
+
+ /* Optional tint. */
+ float3 tint = stack_load_float3(stack, tint_ofs);
+ float3 tint_sigma = sigma_from_reflectance(tint, radial_roughness);
+
+ bsdf->sigma = melanin_sigma + tint_sigma;
+ break;
+ }
+ case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
+ float3 color = stack_load_float3(stack, color_ofs);
+ bsdf->sigma = sigma_from_reflectance(color, radial_roughness);
+ break;
+ }
+ default: {
+ /* Fallback to brownish hair, same as defaults for melanin. */
+ kernel_assert(!"Invalid Principled Hair parametrization!");
+ bsdf->sigma = sigma_from_concentration(0.0f, 0.8054375f);
+ break;
+ }
+ }
+
+ sd->flag |= bsdf_principled_hair_setup(sd, bsdf);
+ }
+ break;
+ }
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
float3 weight = sd->svm_closure_weight * mix_weight;
@@ -764,7 +880,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
-#endif
+#endif /* __HAIR__ */
#ifdef __SUBSURFACE__
case CLOSURE_BSSRDF_CUBIC_ID:
diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h
index b85eb9c0458..0f5b3abef87 100644
--- a/intern/cycles/kernel/svm/svm_displace.h
+++ b/intern/cycles/kernel/svm/svm_displace.h
@@ -75,6 +75,8 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
object_normal_transform(kg, sd, &normal_out);
}
+ normal_out = ensure_valid_reflection(sd->Ng, sd->I, normal_out);
+
stack_store_float3(stack, node.w, normal_out);
#endif
}
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 7c207083929..45c38d64763 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -345,6 +345,8 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
N = safe_normalize(sd->N + (N - sd->N)*strength);
}
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+
if(is_zero(N)) {
N = sd->N;
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index e03ad3a0cfe..910537a2539 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -418,6 +418,13 @@ typedef enum ShaderType {
SHADER_TYPE_BUMP,
} ShaderType;
+typedef enum NodePrincipledHairParametrization {
+ NODE_PRINCIPLED_HAIR_REFLECTANCE = 0,
+ NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
+ NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
+ NODE_PRINCIPLED_HAIR_NUM,
+} NodePrincipledHairParametrization;
+
/* Closure */
typedef enum ClosureType {
@@ -464,6 +471,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
+ CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
/* Special cases */
@@ -495,7 +503,7 @@ typedef enum ClosureType {
/* watch this, being lazy with memory usage */
#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID)
-#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID)
+#define CLOSURE_IS_BSDF_GLOSSY(type) ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID )|| (type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID))
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID)
#define CLOSURE_IS_BSDF_SINGULAR(type) (type == CLOSURE_BSDF_REFLECTION_ID || \
diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h
index e5e350bf76a..75af910d940 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -52,7 +52,7 @@ ccl_device void voronoi_neighbors(float3 p, NodeVoronoiDistanceMetric distance,
case NODE_VORONOI_CHEBYCHEV:
d = max3(fabs(vp - p));
break;
- case NODE_VORONOI_MINKOWSKI:
+ case NODE_VORONOI_MINKOWSKI: {
float3 n = fabs(vp - p);
if(e == 0.5f) {
d = sqr(reduce_add(sqrt(n)));
@@ -61,6 +61,7 @@ ccl_device void voronoi_neighbors(float3 p, NodeVoronoiDistanceMetric distance,
d = powf(reduce_add(pow3(n, e)), 1.0f/e);
}
break;
+ }
}
/* To keep the shortest four distances and associated points we have to keep them in sorted order. */
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index b7248354abd..7d2220f37f9 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -33,6 +33,7 @@ set(SRC
session.cpp
shader.cpp
sobol.cpp
+ stats.cpp
svm.cpp
tables.cpp
tile.cpp
@@ -60,6 +61,7 @@ set(SRC_HEADERS
session.h
shader.h
sobol.h
+ stats.h
svm.h
tables.h
tile.h
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 78a2039c423..3a9e2981418 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -1091,6 +1091,9 @@ int ShaderGraph::get_num_closures()
else if(CLOSURE_IS_VOLUME(closure_type)) {
num_closures += VOLUME_STACK_SIZE;
}
+ else if(closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
+ num_closures += 4;
+ }
else {
++num_closures;
}
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index fa280fec01f..2865b0e5e97 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -17,6 +17,7 @@
#include "device/device.h"
#include "render/image.h"
#include "render/scene.h"
+#include "render/stats.h"
#include "util/util_foreach.h"
#include "util/util_logging.h"
@@ -30,20 +31,58 @@
CCL_NAMESPACE_BEGIN
+namespace {
+
/* Some helpers to silence warning in templated function. */
-static bool isfinite(uchar /*value*/)
+bool isfinite(uchar /*value*/)
{
- return false;
+ return true;
}
-static bool isfinite(half /*value*/)
+bool isfinite(half /*value*/)
{
- return false;
+ return true;
}
-static bool isfinite(uint16_t /*value*/)
+bool isfinite(uint16_t /*value*/)
{
- return false;
+ return true;
+}
+
+/* The lower three bits of a device texture slot number indicate its type.
+ * These functions convert the slot ids from ImageManager "images" ones
+ * to device ones and vice verse.
+ */
+int type_index_to_flattened_slot(int slot, ImageDataType type)
+{
+ return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
}
+int flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
+{
+ *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
+ return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
+}
+
+const char* name_from_type(ImageDataType type)
+{
+ switch(type) {
+ case IMAGE_DATA_TYPE_FLOAT4: return "float4";
+ case IMAGE_DATA_TYPE_BYTE4: return "byte4";
+ case IMAGE_DATA_TYPE_HALF4: return "half4";
+ case IMAGE_DATA_TYPE_FLOAT: return "float";
+ case IMAGE_DATA_TYPE_BYTE: return "byte";
+ case IMAGE_DATA_TYPE_HALF: return "half";
+ case IMAGE_DATA_TYPE_USHORT4: return "ushort4";
+ case IMAGE_DATA_TYPE_USHORT: return "ushort";
+ case IMAGE_DATA_NUM_TYPES:
+ assert(!"System enumerator type, should never be used");
+ return "";
+ }
+ assert(!"Unhandled image data type");
+ return "";
+}
+
+} // namespace
+
ImageManager::ImageManager(const DeviceInfo& info)
{
need_update = true;
@@ -90,12 +129,12 @@ bool ImageManager::set_animation_frame_update(int frame)
device_memory *ImageManager::image_memory(int flat_slot)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *img = images[type][slot];
+ Image *img = images[type][slot];
- return img->mem;
+ return img->mem;
}
bool ImageManager::get_image_metadata(int flat_slot,
@@ -133,10 +172,12 @@ bool ImageManager::get_image_metadata(const string& filename,
if(metadata.is_float) {
metadata.is_linear = true;
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
+ : IMAGE_DATA_TYPE_FLOAT;
}
else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
+ : IMAGE_DATA_TYPE_BYTE;
}
return true;
@@ -148,7 +189,8 @@ bool ImageManager::get_image_metadata(const string& filename,
return false;
}
if(path_is_directory(filename)) {
- VLOG(1) << "File '" << filename << "' is a directory, can't use as image.";
+ VLOG(1) << "File '" << filename
+ << "' is a directory, can't use as image.";
return false;
}
@@ -211,16 +253,20 @@ bool ImageManager::get_image_metadata(const string& filename,
metadata.channels = spec.nchannels;
if(metadata.is_half) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4
+ : IMAGE_DATA_TYPE_HALF;
}
else if(metadata.is_float) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
+ : IMAGE_DATA_TYPE_FLOAT;
}
else if(spec.format == TypeDesc::USHORT) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4
+ : IMAGE_DATA_TYPE_USHORT;
}
else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
+ : IMAGE_DATA_TYPE_BYTE;
}
in->close();
@@ -229,50 +275,6 @@ bool ImageManager::get_image_metadata(const string& filename,
return true;
}
-int ImageManager::max_flattened_slot(ImageDataType type)
-{
- if(tex_num_images[type] == 0) {
- /* No textures for the type, no slots needs allocation. */
- return 0;
- }
- return type_index_to_flattened_slot(tex_num_images[type], type);
-}
-
-/* The lower three bits of a device texture slot number indicate its type.
- * These functions convert the slot ids from ImageManager "images" ones
- * to device ones and vice verse.
- */
-int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
-{
- return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
-}
-
-int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
-{
- *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
- return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
-}
-
-string ImageManager::name_from_type(int type)
-{
- if(type == IMAGE_DATA_TYPE_FLOAT4)
- return "float4";
- else if(type == IMAGE_DATA_TYPE_FLOAT)
- return "float";
- else if(type == IMAGE_DATA_TYPE_BYTE)
- return "byte";
- else if(type == IMAGE_DATA_TYPE_HALF4)
- return "half4";
- else if(type == IMAGE_DATA_TYPE_HALF)
- return "half";
- else if(type == IMAGE_DATA_TYPE_USHORT)
- return "ushort";
- else if(type == IMAGE_DATA_TYPE_USHORT4)
- return "ushort4";
- else
- return "byte4";
-}
-
static bool image_equals(ImageManager::Image *image,
const string& filename,
void *builtin_data,
@@ -344,14 +346,16 @@ int ImageManager::add_image(const string& filename,
}
/* Count if we're over the limit.
- * Very unlikely, since max_num_images is insanely big. But better safe than sorry. */
+ * Very unlikely, since max_num_images is insanely big. But better safe
+ * than sorry.
+ */
int tex_count = 0;
for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
tex_count += tex_num_images[type];
}
if(tex_count > max_num_images) {
- printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n",
- max_num_images, filename.c_str());
+ printf("ImageManager::add_image: Reached image limit (%d), "
+ "skipping '%s'\n", max_num_images, filename.c_str());
return -1;
}
@@ -508,7 +512,6 @@ bool ImageManager::file_load_image(Image *img,
int texture_limit,
device_vector<DeviceType>& tex_img)
{
- const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1;
ImageInput *in = NULL;
if(!file_load_image_generic(img, &in)) {
return false;
@@ -601,13 +604,19 @@ bool ImageManager::file_load_image(Image *img,
type == IMAGE_DATA_TYPE_BYTE4 ||
type == IMAGE_DATA_TYPE_USHORT4);
if(is_rgba) {
+ const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
+
if(cmyk) {
/* CMYK */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
- pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
- pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
- pixels[i*4+3] = alpha_one;
+ float c = util_image_cast_to_float(pixels[i*4+0]);
+ float m = util_image_cast_to_float(pixels[i*4+1]);
+ float y = util_image_cast_to_float(pixels[i*4+2]);
+ float k = util_image_cast_to_float(pixels[i*4+3]);
+ pixels[i*4+0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
+ pixels[i*4+1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
+ pixels[i*4+2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
+ pixels[i*4+3] = one;
}
}
else if(components == 2) {
@@ -622,7 +631,7 @@ bool ImageManager::file_load_image(Image *img,
else if(components == 3) {
/* RGB */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = alpha_one;
+ pixels[i*4+3] = one;
pixels[i*4+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1];
pixels[i*4+0] = pixels[i*3+0];
@@ -631,7 +640,7 @@ bool ImageManager::file_load_image(Image *img,
else if(components == 1) {
/* grayscale */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = alpha_one;
+ pixels[i*4+3] = one;
pixels[i*4+2] = pixels[i];
pixels[i*4+1] = pixels[i];
pixels[i*4+0] = pixels[i];
@@ -639,7 +648,7 @@ bool ImageManager::file_load_image(Image *img,
}
if(img->use_alpha == false) {
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = alpha_one;
+ pixels[i*4+3] = one;
}
}
}
@@ -727,7 +736,8 @@ void ImageManager::device_load_image(Device *device,
/* Slot assignment */
int flat_slot = type_index_to_flattened_slot(slot, type);
- img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot);
+ img->mem_name = string_printf("__tex_image_%s_%03d",
+ name_from_type(type), flat_slot);
/* Free previous texture in slot. */
if(img->mem) {
@@ -871,7 +881,7 @@ void ImageManager::device_load_image(Device *device,
thread_scoped_lock device_lock(device_mutex);
uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
- pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
}
img->mem = tex_img;
@@ -893,10 +903,10 @@ void ImageManager::device_load_image(Device *device,
thread_scoped_lock device_lock(device_mutex);
uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
}
img->mem = tex_img;
@@ -1066,4 +1076,15 @@ void ImageManager::device_free(Device *device)
}
}
+void ImageManager::collect_statistics(RenderStats *stats)
+{
+ for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ foreach(const Image *image, images[type]) {
+ stats->image.textures.add_entry(
+ NamedSizeEntry(path_filename(image->filename),
+ image->mem->memory_size()));
+ }
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index c9667fb77a9..0bf06c322d0 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN
class Device;
class Progress;
+class RenderStats;
class Scene;
class ImageMetaData {
@@ -93,6 +94,8 @@ public:
device_memory *image_memory(int flat_slot);
+ void collect_statistics(RenderStats *stats);
+
bool need_update;
/* NOTE: Here pixels_size is a size of storage, which equals to
@@ -153,16 +156,11 @@ private:
int texture_limit,
device_vector<DeviceType>& tex_img);
- int max_flattened_slot(ImageDataType type);
- int type_index_to_flattened_slot(int slot, ImageDataType type);
- int flattened_slot_to_type_index(int flat_slot, ImageDataType *type);
- string name_from_type(int type);
-
void device_load_image(Device *device,
Scene *scene,
ImageDataType type,
int slot,
- Progress *progess);
+ Progress *progress);
void device_free_image(Device *device,
ImageDataType type,
int slot);
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 7a9d604244d..ade575a52d6 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -27,6 +27,7 @@
#include "render/nodes.h"
#include "render/object.h"
#include "render/scene.h"
+#include "render/stats.h"
#include "kernel/osl/osl_globals.h"
@@ -2015,8 +2016,8 @@ void MeshManager::device_update_displacement_images(Device *device,
}
void MeshManager::device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress)
+ Scene *scene,
+ Progress& progress)
{
progress.set_status("Updating Volume Images");
TaskPool pool;
@@ -2043,11 +2044,11 @@ void MeshManager::device_update_volume_images(Device *device,
foreach(int slot, volume_images) {
pool.push(function_bind(&ImageManager::device_update_slot,
- image_manager,
- device,
- scene,
- slot,
- &progress));
+ image_manager,
+ device,
+ scene,
+ slot,
+ &progress));
}
pool.wait_work();
}
@@ -2276,6 +2277,15 @@ void MeshManager::tag_update(Scene *scene)
scene->object_manager->need_update = true;
}
+void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats)
+{
+ foreach(Mesh *mesh, scene->meshes) {
+ stats->mesh.geometry.add_entry(
+ NamedSizeEntry(string(mesh->name.c_str()),
+ mesh->get_total_size_in_bytes()));
+ }
+}
+
bool Mesh::need_attribute(Scene *scene, AttributeStandard std)
{
if(std == ATTR_STD_NONE)
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index e7dc1c8e5cf..444f03a3664 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -38,6 +38,7 @@ class Device;
class DeviceScene;
class Mesh;
class Progress;
+class RenderStats;
class Scene;
class SceneParams;
class AttributeRequest;
@@ -351,6 +352,8 @@ public:
void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
+ void collect_statistics(const Scene *scene, RenderStats *stats);
+
protected:
/* Calculate verts/triangles/curves offsets in global arrays. */
void mesh_calc_offset(Scene *scene);
@@ -381,8 +384,8 @@ protected:
Progress& progress);
void device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress);
+ Scene *scene,
+ Progress& progress);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index d1c49b456ff..3ee4124ba0f 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -87,23 +87,31 @@ const float3 quads_normals[6] = {
make_float3(0.0f, 0.0f, 1.0f),
};
-static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int face_index)
+static int add_vertex(int3 v, vector<int3> &vertices, int3 res, unordered_map<size_t, int> &used_verts)
{
- size_t vertex_offset = vertices.size();
+ size_t vert_key = v.x + v.y * (res.x+1) + v.z * (res.x+1)*(res.y+1);
+ unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
+ if(it != used_verts.end()) {
+ return it->second;
+ }
+
+ int vertex_offset = vertices.size();
+ used_verts[vert_key] = vertex_offset;
+ vertices.push_back(v);
+ return vertex_offset;
+}
+
+static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int3 res, unordered_map<size_t, int> &used_verts, int face_index)
+{
QuadData quad;
- quad.v0 = vertex_offset + 0;
- quad.v1 = vertex_offset + 1;
- quad.v2 = vertex_offset + 2;
- quad.v3 = vertex_offset + 3;
+ quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
+ quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
+ quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
+ quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
quad.normal = quads_normals[face_index];
quads.push_back(quad);
-
- vertices.push_back(corners[quads_indices[face_index][0]]);
- vertices.push_back(corners[quads_indices[face_index][1]]);
- vertices.push_back(corners[quads_indices[face_index][2]]);
- vertices.push_back(corners[quads_indices[face_index][3]]);
}
struct VolumeParams {
@@ -159,9 +167,6 @@ private:
void generate_vertices_and_quads(vector<int3> &vertices_is,
vector<QuadData> &quads);
- void deduplicate_vertices(vector<int3> &vertices,
- vector<QuadData> &quads);
-
void convert_object_space(const vector<int3> &vertices,
vector<float3> &out_vertices);
@@ -234,8 +239,6 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
generate_vertices_and_quads(vertices_is, quads);
- deduplicate_vertices(vertices_is, quads);
-
convert_object_space(vertices_is, vertices);
convert_quads_to_tris(quads, indices, face_normals);
@@ -245,10 +248,7 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
vector<ccl::int3> &vertices_is,
vector<QuadData> &quads)
{
- /* Overallocation, we could count the number of quads and vertices to create
- * in a pre-pass if memory becomes an issue. */
- vertices_is.reserve(number_of_nodes*8);
- quads.reserve(number_of_nodes*6);
+ unordered_map<size_t, int> used_verts;
for(int z = 0; z < res.z; ++z) {
for(int y = 0; y < res.y; ++y) {
@@ -283,77 +283,38 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
voxel_index = compute_voxel_index(res, x - 1, y, z);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_X_MIN);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
}
voxel_index = compute_voxel_index(res, x + 1, y, z);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_X_MAX);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
}
voxel_index = compute_voxel_index(res, x, y - 1, z);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_Y_MIN);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
}
voxel_index = compute_voxel_index(res, x, y + 1, z);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_Y_MAX);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
}
voxel_index = compute_voxel_index(res, x, y, z - 1);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_Z_MIN);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
}
voxel_index = compute_voxel_index(res, x, y, z + 1);
if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, QUAD_Z_MAX);
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
}
}
}
}
}
-void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices,
- vector<QuadData> &quads)
-{
- vector<int3> sorted_vertices = vertices;
- std::sort(sorted_vertices.begin(), sorted_vertices.end());
- vector<int3>::iterator it = std::unique(sorted_vertices.begin(), sorted_vertices.end());
- sorted_vertices.resize(std::distance(sorted_vertices.begin(), it));
-
- vector<QuadData> new_quads = quads;
-
- for(size_t i = 0; i < vertices.size(); ++i) {
- for(size_t j = 0; j < sorted_vertices.size(); ++j) {
- if(vertices[i] != sorted_vertices[j]) {
- continue;
- }
-
- for(int k = 0; k < quads.size(); ++k) {
- if(quads[k].v0 == i) {
- new_quads[k].v0 = j;
- }
- else if(quads[k].v1 == i) {
- new_quads[k].v1 = j;
- }
- else if(quads[k].v2 == i) {
- new_quads[k].v2 = j;
- }
- else if(quads[k].v3 == i) {
- new_quads[k].v3 = j;
- }
- }
-
- break;
- }
- }
-
- vertices = sorted_vertices;
- quads = new_quads;
-}
-
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
vector<float3> &out_vertices)
{
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index e6bb341d1b8..cce851612db 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3089,6 +3089,139 @@ void PrincipledVolumeNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_principled_volume");
}
+/* Principled Hair BSDF Closure */
+
+NODE_DEFINE(PrincipledHairBsdfNode)
+{
+ NodeType* type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
+
+ /* Color parametrization specified as enum. */
+ static NodeEnum parametrization_enum;
+ parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
+ parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
+ SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+
+ /* Initialize sockets to their default values. */
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
+ SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
+ SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
+ SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
+ SOCKET_IN_VECTOR(absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f), SocketType::VECTOR);
+
+ SOCKET_IN_FLOAT(offset, "Offset", 2.f*M_PI_F/180.f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
+ SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
+ SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
+ SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
+
+ SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
+ SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
+ SOCKET_IN_FLOAT(random, "Random", 0.0f);
+
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
+PrincipledHairBsdfNode::PrincipledHairBsdfNode()
+: BsdfBaseNode(node_type)
+{
+ closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+}
+
+/* Enable retrieving Hair Info -> Random if Random isn't linked. */
+void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
+{
+ if(!input("Random")->link) {
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
+ ShaderNode::attributes(shader, attributes);
+}
+
+/* Prepares the input data for the SVM shader. */
+void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
+{
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
+
+ ShaderInput *roughness_in = input("Roughness");
+ ShaderInput *radial_roughness_in = input("Radial Roughness");
+ ShaderInput *random_roughness_in = input("Random Roughness");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *coat_in = input("Coat");
+ ShaderInput *ior_in = input("IOR");
+ ShaderInput *melanin_in = input("Melanin");
+ ShaderInput *melanin_redness_in = input("Melanin Redness");
+ ShaderInput *random_color_in = input("Random Color");
+
+ int color_ofs = compiler.stack_assign(input("Color"));
+ int tint_ofs = compiler.stack_assign(input("Tint"));
+ int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
+
+ ShaderInput *random_in = input("Random");
+ int attr_random = random_in->link ? SVM_STACK_INVALID : compiler.attribute(ATTR_STD_CURVE_RANDOM);
+
+ /* Encode all parameters into data nodes. */
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ /* Socket IDs can be packed 4 at a time into a single data packet */
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign_if_linked(roughness_in),
+ compiler.stack_assign_if_linked(radial_roughness_in),
+ compiler.closure_mix_weight_offset()),
+ /* The rest are stored as unsigned integers */
+ __float_as_uint(roughness),
+ __float_as_uint(radial_roughness));
+
+ compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(offset_in),
+ compiler.stack_assign_if_linked(ior_in),
+ color_ofs,
+ parametrization),
+ __float_as_uint(offset),
+ __float_as_uint(ior));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(coat_in),
+ compiler.stack_assign_if_linked(melanin_in),
+ compiler.stack_assign_if_linked(melanin_redness_in),
+ absorption_coefficient_ofs),
+ __float_as_uint(coat),
+ __float_as_uint(melanin),
+ __float_as_uint(melanin_redness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ tint_ofs,
+ compiler.stack_assign_if_linked(random_in),
+ compiler.stack_assign_if_linked(random_color_in),
+ compiler.stack_assign_if_linked(random_roughness_in)),
+ __float_as_uint(random),
+ __float_as_uint(random_color),
+ __float_as_uint(random_roughness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID),
+ attr_random,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID);
+}
+
+/* Prepares the input data for the OSL shader. */
+void PrincipledHairBsdfNode::compile(OSLCompiler& compiler)
+{
+ compiler.parameter(this, "parametrization");
+ compiler.add(this, "node_principled_hair_bsdf");
+}
+
/* Hair BSDF Closure */
NODE_DEFINE(HairBsdfNode)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index fd043ce5161..c2cf13ad020 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -610,6 +610,45 @@ public:
float temperature;
};
+/* Interface between the I/O sockets and the SVM/OSL backend. */
+class PrincipledHairBsdfNode : public BsdfBaseNode {
+public:
+ SHADER_NODE_CLASS(PrincipledHairBsdfNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ /* Longitudinal roughness. */
+ float roughness;
+ /* Azimuthal roughness. */
+ float radial_roughness;
+ /* Randomization factor for roughnesses. */
+ float random_roughness;
+ /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
+ float coat;
+ /* Index of reflection. */
+ float ior;
+ /* Cuticle tilt angle. */
+ float offset;
+ /* Direct coloring's color. */
+ float3 color;
+ /* Melanin concentration. */
+ float melanin;
+ /* Melanin redness ratio. */
+ float melanin_redness;
+ /* Dye color. */
+ float3 tint;
+ /* Randomization factor for melanin quantities. */
+ float random_color;
+ /* Absorption coefficient (unfiltered). */
+ float3 absorption_coefficient;
+
+ float3 normal;
+ float surface_mix_weight;
+ /* If linked, here will be the given random number. */
+ float random;
+ /* Selected coloring parametrization. */
+ NodePrincipledHairParametrization parametrization;
+};
+
class HairBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(HairBsdfNode)
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 1d65ef65980..9f93fed139c 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -379,4 +379,10 @@ void Scene::device_free()
free_memory(false);
}
+void Scene::collect_statistics(RenderStats *stats)
+{
+ mesh_manager->collect_statistics(this, stats);
+ image_manager->collect_statistics(stats);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 713eba623b1..dd8069537eb 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -56,6 +56,7 @@ class ShaderManager;
class Progress;
class BakeManager;
class BakeData;
+class RenderStats;
/* Scene Device Data */
@@ -255,6 +256,8 @@ public:
void reset();
void device_free();
+ void collect_statistics(RenderStats *stats);
+
protected:
/* Check if some heavy data worth logging was updated.
* Mainly used to suppress extra annoying logging.
diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp
new file mode 100644
index 00000000000..101d33fcf65
--- /dev/null
+++ b/intern/cycles/render/stats.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011-2018 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 "render/stats.h"
+#include "util/util_algorithm.h"
+#include "util/util_foreach.h"
+#include "util/util_string.h"
+
+CCL_NAMESPACE_BEGIN
+
+static int kIndentNumSpaces = 2;
+
+/* Named size entry. */
+
+namespace {
+
+bool namedSizeEntryComparator(const NamedSizeEntry& a, const NamedSizeEntry& b)
+{
+ /* We sort in descending order. */
+ return a.size > b.size;
+}
+
+} // namespace
+
+NamedSizeEntry::NamedSizeEntry()
+ : name(""),
+ size(0) {
+}
+
+NamedSizeEntry::NamedSizeEntry(const string& name, size_t size)
+ : name(name),
+ size(size) {
+}
+
+/* Named size statistics. */
+
+NamedSizeStats::NamedSizeStats()
+ : total_size(0) {
+}
+
+void NamedSizeStats::add_entry(const NamedSizeEntry& entry) {
+ total_size += entry.size;
+ entries.push_back(entry);
+}
+
+string NamedSizeStats::full_report(int indent_level)
+{
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ const string double_indent = indent + indent;
+ string result = "";
+ result += string_printf("%sTotal memory: %s (%s)\n",
+ indent.c_str(),
+ string_human_readable_size(total_size).c_str(),
+ string_human_readable_number(total_size).c_str());
+ sort(entries.begin(), entries.end(), namedSizeEntryComparator);
+ foreach(const NamedSizeEntry& entry, entries) {
+ result += string_printf(
+ "%s%-32s %s (%s)\n",
+ double_indent.c_str(),
+ entry.name.c_str(),
+ string_human_readable_size(entry.size).c_str(),
+ string_human_readable_number(entry.size).c_str());
+ }
+ return result;
+}
+
+/* Mesh statistics. */
+
+MeshStats::MeshStats() {
+}
+
+string MeshStats::full_report(int indent_level)
+{
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
+ return result;
+}
+
+/* Image statistics. */
+
+ImageStats::ImageStats() {
+}
+
+string ImageStats::full_report(int indent_level)
+{
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
+ return result;
+}
+
+/* Overall statistics. */
+
+RenderStats::RenderStats() {
+}
+
+string RenderStats::full_report()
+{
+ string result = "";
+ result += "Mesh statistics:\n" + mesh.full_report(1);
+ result += "Image statistics:\n" + image.full_report(1);
+ return result;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h
new file mode 100644
index 00000000000..72d5f1dd93d
--- /dev/null
+++ b/intern/cycles/render/stats.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011-2018 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 __RENDER_STATS_H__
+#define __RENDER_STATS_H__
+
+#include "util/util_string.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Named statistics entry, which corresponds to a size. There is no real
+ * semantic around the units of size, it just should be the same for all
+ * entries.
+ *
+ * This is a generic entry foi all size-related statistics, which helps
+ * avoiding duplicating code for things like sorting.
+ */
+class NamedSizeEntry {
+public:
+ NamedSizeEntry();
+ NamedSizeEntry(const string& name, size_t size);
+
+ string name;
+ size_t size;
+};
+
+/* Container of named size entries. Used, for example, to store per-mesh memory
+ * usage statistics. But also keeps track of overall memory usage of the
+ * container.
+ */
+class NamedSizeStats {
+public:
+ NamedSizeStats();
+
+ /* Add entry to the statistics. */
+ void add_entry(const NamedSizeEntry& entry);
+
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
+
+ /* Total size of all entries. */
+ size_t total_size;
+
+ /* NOTE: Is fine to read directly, but for adding use add_entry(), which
+ * makes sure all accumulating values are properly updated.
+ */
+ vector<NamedSizeEntry> entries;
+};
+
+/* Statistics about mesh in the render database. */
+class MeshStats {
+public:
+ MeshStats();
+
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
+
+ /* Input geometry statistics, this is what is coming as an input to render
+ * from. say, Blender. This does not include runtime or engine specific
+ * memory like BVH.
+ */
+ NamedSizeStats geometry;
+};
+
+/* Statistics about images held in memory. */
+class ImageStats {
+public:
+ ImageStats();
+
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
+
+ NamedSizeStats textures;
+};
+
+/* Render process statistics. */
+class RenderStats {
+public:
+ RenderStats();
+
+ /* Return full report as string. */
+ string full_report();
+
+ MeshStats mesh;
+ ImageStats image;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __RENDER_STATS_H__ */
diff --git a/intern/cycles/util/util_defines.h b/intern/cycles/util/util_defines.h
index d994d4e08f4..8bce4aca699 100644
--- a/intern/cycles/util/util_defines.h
+++ b/intern/cycles/util/util_defines.h
@@ -87,12 +87,8 @@
# define UNLIKELY(x) (x)
#endif
-#if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
-# define HAS_CPP11_FEATURES
-#endif
-
#if defined(__GNUC__) || defined(__clang__)
-# if defined(HAS_CPP11_FEATURES)
+# if defined(__cplusplus)
/* Some magic to be sure we don't have reference in the type. */
template<typename T> static inline T decltype_helper(T x) { return x; }
# define TYPEOF(x) decltype(decltype_helper(x))
diff --git a/intern/cycles/util/util_foreach.h b/intern/cycles/util/util_foreach.h
index 03fcefc67b9..2a74ff0a55d 100644
--- a/intern/cycles/util/util_foreach.h
+++ b/intern/cycles/util/util_foreach.h
@@ -17,13 +17,8 @@
#ifndef __UTIL_FOREACH_H__
#define __UTIL_FOREACH_H__
-/* Use Boost to get nice foreach() loops for STL data structures. */
+/* Nice foreach() loops for STL data structures. */
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# define foreach(x, y) for(x : y)
-#else
-# include <boost/foreach.hpp>
-# define foreach BOOST_FOREACH
-#endif
+#define foreach(x, y) for(x : y)
#endif /* __UTIL_FOREACH_H__ */
diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h
index 958f8b4008c..f3cc00329ad 100644
--- a/intern/cycles/util/util_function.h
+++ b/intern/cycles/util/util_function.h
@@ -17,18 +17,12 @@
#ifndef __UTIL_FUNCTION_H__
#define __UTIL_FUNCTION_H__
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# include <functional>
-#else
-# include <boost/bind.hpp>
-# include <boost/function.hpp>
-#endif
+#include <functional>
CCL_NAMESPACE_BEGIN
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# define function_bind std::bind
-# define function_null nullptr
+#define function_bind std::bind
+#define function_null nullptr
using std::function;
using std::placeholders::_1;
using std::placeholders::_2;
@@ -39,11 +33,7 @@ using std::placeholders::_6;
using std::placeholders::_7;
using std::placeholders::_8;
using std::placeholders::_9;
-#else
-using boost::function;
-# define function_bind boost::bind
-# define function_null NULL
-#endif
+
CCL_NAMESPACE_END
#endif /* __UTIL_FUNCTION_H__ */
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index 58f3f903619..53b7f2472bd 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -42,7 +42,7 @@ public:
half() : v(0) {}
half(const unsigned short& i) : v(i) {}
operator unsigned short() { return v; }
- half & operator =(const unsigned short& i) { v = i; return *this; }
+ half& operator =(const unsigned short& i) { v = i; return *this; }
private:
unsigned short v;
};
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index 18876841b5b..85bdb0d8050 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -38,6 +38,68 @@ void util_image_resize_pixels(const vector<T>& input_pixels,
size_t *output_height,
size_t *output_depth);
+/* Cast input pixel from unknown storage to float. */
+template<typename T>
+inline float util_image_cast_to_float(T value);
+
+template<>
+inline float util_image_cast_to_float(float value)
+{
+ return value;
+}
+template<>
+inline float util_image_cast_to_float(uchar value)
+{
+ return (float)value / 255.0f;
+}
+template<>
+inline float util_image_cast_to_float(uint16_t value)
+{
+ return (float)value / 65535.0f;
+}
+template<>
+inline float util_image_cast_to_float(half value)
+{
+ return half_to_float(value);
+}
+
+/* Cast float value to output pixel type. */
+template<typename T>
+inline T util_image_cast_from_float(float value);
+
+template<>
+inline float util_image_cast_from_float(float value)
+{
+ return value;
+}
+template<>
+inline uchar util_image_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 uint16_t util_image_cast_from_float(float value)
+{
+ if(value < 0.0f) {
+ return 0;
+ }
+ else if(value > (1.0f - 0.5f / 65535.0f)) {
+ return 65535;
+ }
+ return (uint16_t)((65535.0f * value) + 0.5f);
+}
+template<>
+inline half util_image_cast_from_float(float value)
+{
+ return float_to_half(value);
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_IMAGE_H__ */
diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h
index fb953a43ab2..5bc1c727595 100644
--- a/intern/cycles/util/util_image_impl.h
+++ b/intern/cycles/util/util_image_impl.h
@@ -38,68 +38,6 @@ 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(uint16_t value)
-{
- return (float)value / 65535.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 uint16_t cast_from_float(float value)
-{
- if(value < 0.0f) {
- return 0;
- }
- else if(value >(1.0f - 0.5f / 65535.0f)) {
- return 65535;
- }
- return (uchar)((65535.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,
@@ -133,7 +71,7 @@ void util_image_downscale_sample(const vector<T>& pixels,
components,
nx, ny, nz);
for(size_t k = 0; k < components; ++k) {
- accum[k] += cast_to_float(pixel[k]);
+ accum[k] += util_image_cast_to_float(pixel[k]);
}
++count;
}
@@ -142,7 +80,7 @@ void util_image_downscale_sample(const vector<T>& pixels,
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);
+ result[k] = util_image_cast_from_float<T>(accum[k] * inv_count);
}
}
else {
diff --git a/intern/cycles/util/util_map.h b/intern/cycles/util/util_map.h
index b3d887f093c..3c9288417cf 100644
--- a/intern/cycles/util/util_map.h
+++ b/intern/cycles/util/util_map.h
@@ -18,38 +18,13 @@
#define __UTIL_MAP_H__
#include <map>
-
-#if defined(CYCLES_TR1_UNORDERED_MAP)
-# include <tr1/unordered_map>
-#endif
-
-#if defined(CYCLES_STD_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# include <unordered_map>
-#endif
-
-#if !defined(CYCLES_NO_UNORDERED_MAP) && !defined(CYCLES_TR1_UNORDERED_MAP) && \
- !defined(CYCLES_STD_UNORDERED_MAP) && !defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
-# error One of: CYCLES_NO_UNORDERED_MAP, CYCLES_TR1_UNORDERED_MAP,\
- CYCLES_STD_UNORDERED_MAP, CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
-#endif
-
+#include <unordered_map>
CCL_NAMESPACE_BEGIN
using std::map;
using std::pair;
-
-#if defined(CYCLES_NO_UNORDERED_MAP)
-typedef std::map unordered_map;
-#endif
-
-#if defined(CYCLES_TR1_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-using std::tr1::unordered_map;
-#endif
-
-#if defined(CYCLES_STD_UNORDERED_MAP)
using std::unordered_map;
-#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 85cbd18b7ba..52aeb8d8599 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -55,6 +55,15 @@ CCL_NAMESPACE_BEGIN
#ifndef M_2_PI_F
# define M_2_PI_F (0.6366197723675813f) /* 2/pi */
#endif
+#ifndef M_1_2PI_F
+# define M_1_2PI_F (0.1591549430918953f) /* 1/(2*pi) */
+#endif
+#ifndef M_SQRT_PI_8_F
+# define M_SQRT_PI_8_F (0.6266570686577501f) /* sqrt(pi/8) */
+#endif
+#ifndef M_LN_2PI_F
+# define M_LN_2PI_F (1.8378770664093454f) /* ln(2*pi) */
+#endif
/* Multiplication */
#ifndef M_2PI_F
@@ -541,6 +550,16 @@ ccl_device_inline float sqr(float a)
return a * a;
}
+ccl_device_inline float pow20(float a)
+{
+ return sqr(sqr(sqr(sqr(a))*a));
+}
+
+ccl_device_inline float pow22(float a)
+{
+ return sqr(a*sqr(sqr(sqr(a))*a));
+}
+
ccl_device_inline float beta(float x, float y)
{
#ifndef __KERNEL_OPENCL__
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index 3a5a2ab2244..75265c1c9a2 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -280,11 +280,6 @@ ccl_device_inline float3 sqrt(const float3& a)
#endif
}
-ccl_device_inline float3 pow3(const float3& a, float e)
-{
- return make_float3(powf(a.x, e), powf(a.y, e), powf(a.z, e));
-}
-
ccl_device_inline float3 mix(const float3& a, const float3& b, float t)
{
return a + t*(b - a);
@@ -382,6 +377,21 @@ ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
#endif
}
+ccl_device_inline float3 pow3(float3 v, float e)
+{
+ return make_float3(powf(v.x, e), powf(v.y, e), powf(v.z, e));
+}
+
+ccl_device_inline float3 exp3(float3 v)
+{
+ return make_float3(expf(v.x), expf(v.y), expf(v.z));
+}
+
+ccl_device_inline float3 log3(float3 v)
+{
+ return make_float3(logf(v.x), logf(v.y), logf(v.z));
+}
+
ccl_device_inline int3 quick_floor_to_int3(const float3 a)
{
#ifdef __KERNEL_SSE__
diff --git a/intern/cycles/util/util_set.h b/intern/cycles/util/util_set.h
index 1d010e19996..298e1f7729a 100644
--- a/intern/cycles/util/util_set.h
+++ b/intern/cycles/util/util_set.h
@@ -18,24 +18,7 @@
#define __UTIL_SET_H__
#include <set>
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# include <unordered_set>
-#else
-# if defined(CYCLES_TR1_UNORDERED_MAP)
-# include <tr1/unordered_set>
-# endif
-# if defined(CYCLES_STD_UNORDERED_MAP) || \
- defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# include <unordered_set>
-# endif
-# if !defined(CYCLES_NO_UNORDERED_MAP) && \
- !defined(CYCLES_TR1_UNORDERED_MAP) && \
- !defined(CYCLES_STD_UNORDERED_MAP) && \
- !defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# error One of: CYCLES_NO_UNORDERED_MAP, CYCLES_TR1_UNORDERED_MAP,\
- CYCLES_STD_UNORDERED_MAP, CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
-# endif
-#endif
+#include <unordered_set>
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
# include <iterator>
@@ -44,19 +27,8 @@
CCL_NAMESPACE_BEGIN
using std::set;
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-using std::unordered_set;
-#else
-# if defined(CYCLES_NO_UNORDERED_MAP)
-typedef std::set unordered_set;
-# endif
-# if defined(CYCLES_TR1_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-using std::tr1::unordered_set;
-# endif
-# if defined(CYCLES_STD_UNORDERED_MAP)
using std::unordered_set;
-# endif
-#endif
+
CCL_NAMESPACE_END
#endif /* __UTIL_SET_H__ */
diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h
index e90049254de..dc3cb3f6ecc 100644
--- a/intern/cycles/util/util_static_assert.h
+++ b/intern/cycles/util/util_static_assert.h
@@ -22,27 +22,7 @@ CCL_NAMESPACE_BEGIN
/* TODO(sergey): In theory CUDA might work with own static assert
* implementation since it's just pure C++.
*/
-#ifndef __KERNEL_GPU__
-# if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-/* C++11 has built-in static_assert() */
-# elif defined(static_assert)
-/* Some platforms might have static_assert() defined even tho their
- * C++ support wouldn't be declared to be C++11.
- */
-# else /* C++11 or MSVC2015 */
-template <bool Test> class StaticAssertFailure;
-template <> class StaticAssertFailure<true> {};
-# define _static_assert_private_glue_impl(A, B) A ## B
-# define _static_assert_glue(A, B) _static_assert_private_glue_impl(A, B)
-# ifdef __COUNTER__
-# define static_assert(condition, message) \
- enum {_static_assert_glue(q_static_assert_result, __COUNTER__) = sizeof(StaticAssertFailure<!!(condition)>)} // NOLINT
-# else /* __COUNTER__ */
-# define static_assert(condition, message) \
- enum {_static_assert_glue(q_static_assert_result, __LINE__) = sizeof(StaticAssertFailure<!!(condition)>)} // NOLINT
-# endif /* __COUNTER__ */
-# endif /* C++11 or MSVC2015 */
-#else /* __KERNEL_GPU__ */
+#ifdef __KERNEL_GPU__
# ifndef static_assert
# define static_assert(statement, message)
# endif
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index 995f5d3df27..47119e90a45 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -168,6 +168,11 @@ string string_from_bool(bool var)
return "False";
}
+string to_string(const char *str)
+{
+ return string(str);
+}
+
/* Wide char strings helpers for Windows. */
#ifdef _WIN32
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index 7dfa97335a9..3a4f4398158 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -29,6 +29,7 @@ using std::string;
using std::stringstream;
using std::ostringstream;
using std::istringstream;
+using std::to_string;
#ifdef __GNUC__
#define PRINTF_ATTRIBUTE __attribute__((format(printf, 1, 2)))
@@ -49,6 +50,7 @@ bool string_endswith(const string& s, const char *end);
string string_strip(const string& s);
string string_remove_trademark(const string& s);
string string_from_bool(const bool var);
+string to_string(const char *str);
/* Wide char strings are only used on Windows to deal with non-ascii
* characters in file names and such. No reason to use such strings
diff --git a/intern/cycles/util/util_thread.cpp b/intern/cycles/util/util_thread.cpp
index c66aa484264..16a8591a8a9 100644
--- a/intern/cycles/util/util_thread.cpp
+++ b/intern/cycles/util/util_thread.cpp
@@ -26,11 +26,7 @@ thread::thread(function<void(void)> run_cb, int group)
joined_(false),
group_(group)
{
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
thread_ = std::thread(&thread::run, this);
-#else
- pthread_create(&pthread_id_, NULL, run, (void*)this);
-#endif
}
thread::~thread()
@@ -64,7 +60,6 @@ void *thread::run(void *arg)
bool thread::join()
{
joined_ = true;
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
try {
thread_.join();
return true;
@@ -72,9 +67,6 @@ bool thread::join()
catch (const std::system_error&) {
return false;
}
-#else
- return pthread_join(pthread_id_, NULL) == 0;
-#endif
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index 77b51d37ea0..f39fcfb4279 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -17,15 +17,10 @@
#ifndef __UTIL_THREAD_H__
#define __UTIL_THREAD_H__
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# include <thread>
-# include <mutex>
-# include <condition_variable>
-# include <functional>
-#else
-# include <boost/thread.hpp>
-# include <pthread.h>
-#endif
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <functional>
#include <queue>
#ifdef _WIN32
@@ -42,16 +37,9 @@
CCL_NAMESPACE_BEGIN
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
typedef std::mutex thread_mutex;
typedef std::unique_lock<std::mutex> thread_scoped_lock;
typedef std::condition_variable thread_condition_variable;
-#else
-/* use boost for mutexes */
-typedef boost::mutex thread_mutex;
-typedef boost::mutex::scoped_lock thread_scoped_lock;
-typedef boost::condition_variable thread_condition_variable;
-#endif
/* own pthread based implementation, to avoid boost version conflicts with
* dynamically loaded blender plugins */
@@ -66,11 +54,7 @@ public:
protected:
function<void(void)> run_cb_;
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
std::thread thread_;
-#else
- pthread_t pthread_id_;
-#endif
bool joined_;
int group_;
};
diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h
index 569f503b66e..0b33221ad4d 100644
--- a/intern/cycles/util/util_vector.h
+++ b/intern/cycles/util/util_vector.h
@@ -59,11 +59,7 @@ public:
void shrink_to_fit(void)
{
-#if __cplusplus < 201103L
- vector<value_type>().swap(*this);
-#else
std::vector<value_type, allocator_type>::shrink_to_fit();
-#endif
}
void free_memory(void)
diff --git a/intern/gawain/CMakeLists.txt b/intern/gawain/CMakeLists.txt
deleted file mode 100644
index 7ebd3ee7622..00000000000
--- a/intern/gawain/CMakeLists.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-# WITH_OPENGL limits the visibility of the opengl headers to just gawain and bg_gpu,
-# to more easily highlight codepadths in other libraries that need to be refactored,
-# bf_intern_gawain is allowed to have opengl regardless of this option.
-
-if(NOT WITH_OPENGL)
- add_definitions(-DWITH_OPENGL)
-endif()
-
-set(INC
- gawain
-)
-
-set(INC_SYS
- ${GLEW_INCLUDE_PATH}
-)
-
-set(SRC
- src/gwn_attr_binding.c
- src/gwn_batch.c
- src/gwn_element.c
- src/gwn_buffer_id.cpp
- src/gwn_immediate.c
- src/gwn_imm_util.c
- src/gwn_primitive.c
- src/gwn_shader_interface.c
- src/gwn_vertex_array_id.cpp
- src/gwn_vertex_buffer.c
- src/gwn_vertex_format.c
-
- gawain/gwn_attr_binding.h
- gawain/gwn_attr_binding_private.h
- gawain/gwn_batch.h
- gawain/gwn_batch_private.h
- gawain/gwn_buffer_id.h
- gawain/gwn_common.h
- gawain/gwn_element.h
- gawain/gwn_imm_util.h
- gawain/gwn_immediate.h
- gawain/gwn_primitive.h
- gawain/gwn_primitive_private.h
- gawain/gwn_shader_interface.h
- gawain/gwn_vertex_array_id.h
- gawain/gwn_vertex_buffer.h
- gawain/gwn_vertex_format.h
- gawain/gwn_vertex_format_private.h
-)
-
-add_definitions(${GL_DEFINITIONS})
-
-blender_add_lib(bf_intern_gawain "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/gawain/gawain/gwn_attr_binding.h b/intern/gawain/gawain/gwn_attr_binding.h
deleted file mode 100644
index a209e1c4f0f..00000000000
--- a/intern/gawain/gawain/gwn_attr_binding.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-// Gawain vertex attribute binding
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_common.h"
-
-typedef struct Gwn_AttrBinding {
- uint64_t loc_bits; // store 4 bits for each of the 16 attribs
- uint16_t enabled_bits; // 1 bit for each attrib
-} Gwn_AttrBinding;
diff --git a/intern/gawain/gawain/gwn_attr_binding_private.h b/intern/gawain/gawain/gwn_attr_binding_private.h
deleted file mode 100644
index 300945d464b..00000000000
--- a/intern/gawain/gawain/gwn_attr_binding_private.h
+++ /dev/null
@@ -1,20 +0,0 @@
-
-// Gawain vertex attribute binding
-//
-// 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 "gwn_vertex_format.h"
-#include "gwn_shader_interface.h"
-
-void AttribBinding_clear(Gwn_AttrBinding*);
-
-void get_attrib_locations(const Gwn_VertFormat*, Gwn_AttrBinding*, const Gwn_ShaderInterface*);
-unsigned read_attrib_location(const Gwn_AttrBinding*, unsigned a_idx);
diff --git a/intern/gawain/gawain/gwn_batch.h b/intern/gawain/gawain/gwn_batch.h
deleted file mode 100644
index cf7b0c9f1b5..00000000000
--- a/intern/gawain/gawain/gwn_batch.h
+++ /dev/null
@@ -1,169 +0,0 @@
-
-// Gawain geometry batch
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_vertex_buffer.h"
-#include "gwn_element.h"
-#include "gwn_shader_interface.h"
-
-typedef enum {
- GWN_BATCH_READY_TO_FORMAT,
- GWN_BATCH_READY_TO_BUILD,
- GWN_BATCH_BUILDING,
- GWN_BATCH_READY_TO_DRAW
-} Gwn_BatchPhase;
-
-#define GWN_BATCH_VBO_MAX_LEN 3
-#define GWN_BATCH_VAO_STATIC_LEN 3
-#define GWN_BATCH_VAO_DYN_ALLOC_COUNT 16
-
-typedef struct Gwn_Batch {
- // geometry
- Gwn_VertBuf* verts[GWN_BATCH_VBO_MAX_LEN]; // verts[0] is required, others can be NULL
- Gwn_VertBuf* inst; // instance attribs
- Gwn_IndexBuf* elem; // NULL if element list not needed
- uint32_t gl_prim_type;
-
- // cached values (avoid dereferencing later)
- uint32_t vao_id;
- uint32_t program;
- const struct Gwn_ShaderInterface* interface;
-
- // book-keeping
- unsigned owns_flag;
- struct Gwn_Context *context; // used to free all vaos. this implies all vaos were created under the same context.
- Gwn_BatchPhase phase;
- bool program_in_use;
-
- // Vao management: remembers all geometry state (vertex attrib bindings & element buffer)
- // for each shader interface. Start with a static number of vaos and fallback to dynamic count
- // if necessary. Once a batch goes dynamic it does not go back.
- bool is_dynamic_vao_count;
- union {
- // Static handle count
- struct {
- const struct Gwn_ShaderInterface* interfaces[GWN_BATCH_VAO_STATIC_LEN];
- uint32_t vao_ids[GWN_BATCH_VAO_STATIC_LEN];
- } static_vaos;
- // Dynamic handle count
- struct {
- unsigned count;
- const struct Gwn_ShaderInterface** interfaces;
- uint32_t* vao_ids;
- } dynamic_vaos;
- };
-
- // XXX This is the only solution if we want to have some data structure using
- // batches as key to identify nodes. We must destroy these nodes with this callback.
- void (*free_callback)(struct Gwn_Batch*, void*);
- void* callback_data;
-} Gwn_Batch;
-
-enum {
- GWN_BATCH_OWNS_VBO = (1 << 0),
- /* each vbo index gets bit-shifted */
- GWN_BATCH_OWNS_INSTANCES = (1 << 30),
- GWN_BATCH_OWNS_INDEX = (1 << 31),
-};
-
-Gwn_Batch* GWN_batch_create_ex(Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, unsigned owns_flag);
-void GWN_batch_init_ex(Gwn_Batch*, Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, unsigned owns_flag);
-Gwn_Batch* GWN_batch_duplicate(Gwn_Batch* batch_src);
-
-#define GWN_batch_create(prim, verts, elem) \
- GWN_batch_create_ex(prim, verts, elem, 0)
-#define GWN_batch_init(batch, prim, verts, elem) \
- GWN_batch_init_ex(batch, prim, verts, elem, 0)
-
-void GWN_batch_discard(Gwn_Batch*); // verts & elem are not discarded
-
-void GWN_batch_callback_free_set(Gwn_Batch*, void (*callback)(Gwn_Batch*, void*), void*);
-
-void GWN_batch_instbuf_set(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); // Instancing
-
-int GWN_batch_vertbuf_add_ex(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo);
-
-#define GWN_batch_vertbuf_add(batch, verts) \
- GWN_batch_vertbuf_add_ex(batch, verts, false)
-
-void GWN_batch_program_set_no_use(Gwn_Batch*, uint32_t program, const Gwn_ShaderInterface*);
-void GWN_batch_program_set(Gwn_Batch*, uint32_t program, const Gwn_ShaderInterface*);
-// 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.
-
-void GWN_batch_program_use_begin(Gwn_Batch*); // call before Batch_Uniform (temp hack?)
-void GWN_batch_program_use_end(Gwn_Batch*);
-
-void GWN_batch_uniform_1ui(Gwn_Batch*, const char* name, int value);
-void GWN_batch_uniform_1i(Gwn_Batch*, const char* name, int value);
-void GWN_batch_uniform_1b(Gwn_Batch*, const char* name, bool value);
-void GWN_batch_uniform_1f(Gwn_Batch*, const char* name, float value);
-void GWN_batch_uniform_2f(Gwn_Batch*, const char* name, float x, float y);
-void GWN_batch_uniform_3f(Gwn_Batch*, const char* name, float x, float y, float z);
-void GWN_batch_uniform_4f(Gwn_Batch*, const char* name, float x, float y, float z, float w);
-void GWN_batch_uniform_2fv(Gwn_Batch*, const char* name, const float data[2]);
-void GWN_batch_uniform_3fv(Gwn_Batch*, const char* name, const float data[3]);
-void GWN_batch_uniform_4fv(Gwn_Batch*, const char* name, const float data[4]);
-void GWN_batch_uniform_2fv_array(Gwn_Batch*, const char* name, int len, const float *data);
-void GWN_batch_uniform_4fv_array(Gwn_Batch*, const char* name, int len, const float *data);
-void GWN_batch_uniform_mat4(Gwn_Batch*, const char* name, const float data[4][4]);
-
-void GWN_batch_draw(Gwn_Batch*);
-
-// This does not bind/unbind shader and does not call gpuBindMatrices()
-void GWN_batch_draw_range_ex(Gwn_Batch*, int v_first, int v_count, bool force_instance);
-
-// Does not even need batch
-void GWN_draw_primitive(Gwn_PrimType, int v_count);
-
-#if 0 // future plans
-
-// Can multiple batches share a Gwn_VertBuf? Use ref count?
-
-
-// We often need a batch with its own data, to be created and discarded together.
-// WithOwn variants reduce number of system allocations.
-
-typedef struct BatchWithOwnVertexBuffer {
- Gwn_Batch batch;
- Gwn_VertBuf verts; // link batch.verts to this
-} BatchWithOwnVertexBuffer;
-
-typedef struct BatchWithOwnElementList {
- Gwn_Batch batch;
- Gwn_IndexBuf elem; // link batch.elem to this
-} BatchWithOwnElementList;
-
-typedef struct BatchWithOwnVertexBufferAndElementList {
- Gwn_Batch batch;
- Gwn_IndexBuf elem; // link batch.elem to this
- Gwn_VertBuf verts; // link batch.verts to this
-} BatchWithOwnVertexBufferAndElementList;
-
-Gwn_Batch* create_BatchWithOwnVertexBuffer(Gwn_PrimType, Gwn_VertFormat*, unsigned v_len, Gwn_IndexBuf*);
-Gwn_Batch* create_BatchWithOwnElementList(Gwn_PrimType, Gwn_VertBuf*, unsigned prim_len);
-Gwn_Batch* create_BatchWithOwnVertexBufferAndElementList(Gwn_PrimType, Gwn_VertFormat*, unsigned v_len, unsigned prim_len);
-// verts: shared, own
-// elem: none, shared, own
-Gwn_Batch* create_BatchInGeneral(Gwn_PrimType, VertexBufferStuff, ElementListStuff);
-
-#endif // future plans
-
-
-/* Macros */
-
-#define GWN_BATCH_DISCARD_SAFE(batch) do { \
- if (batch != NULL) { \
- GWN_batch_discard(batch); \
- batch = NULL; \
- } \
-} while (0)
diff --git a/intern/gawain/gawain/gwn_batch_private.h b/intern/gawain/gawain/gwn_batch_private.h
deleted file mode 100644
index 6503429c237..00000000000
--- a/intern/gawain/gawain/gwn_batch_private.h
+++ /dev/null
@@ -1,30 +0,0 @@
-
-// Gawain context
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2018 Mike Erwin, Clément Foucault
-//
-// 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
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "gwn_batch.h"
-#include "gwn_context.h"
-#include "gwn_shader_interface.h"
-
-void gwn_batch_remove_interface_ref(Gwn_Batch*, const Gwn_ShaderInterface*);
-void gwn_batch_vao_cache_clear(Gwn_Batch*);
-
-void gwn_context_add_batch(Gwn_Context*, Gwn_Batch*);
-void gwn_context_remove_batch(Gwn_Context*, Gwn_Batch*);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/intern/gawain/gawain/gwn_buffer_id.h b/intern/gawain/gawain/gwn_buffer_id.h
deleted file mode 100644
index 6f51ca6905d..00000000000
--- a/intern/gawain/gawain/gwn_buffer_id.h
+++ /dev/null
@@ -1,30 +0,0 @@
-
-// Gawain buffer IDs
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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
-
-// Manage GL buffer IDs in a thread-safe way
-// Use these instead of glGenBuffers & its friends
-// - alloc must be called from main thread
-// - free can be called from any thread
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "gwn_common.h"
-
-GLuint GWN_buf_id_alloc(void);
-void GWN_buf_id_free(GLuint buffer_id);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/intern/gawain/gawain/gwn_common.h b/intern/gawain/gawain/gwn_common.h
deleted file mode 100644
index 6a56543da40..00000000000
--- a/intern/gawain/gawain/gwn_common.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-// Gawain common #defines and #includes
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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
-
-#define PROGRAM_NO_OPTI 0
-
-#if defined(NDEBUG)
- #define TRUST_NO_ONE 0
-#else
- // strict error checking, enabled for debug builds during early development
- #define TRUST_NO_ONE 1
-#endif
-
-#if defined(WITH_OPENGL)
- #include <GL/glew.h>
-#endif
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#if TRUST_NO_ONE
- #include <assert.h>
-#endif
-
-/* GWN_INLINE */
-#if defined(_MSC_VER)
-# define GWN_INLINE static __forceinline
-#else
-# define GWN_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
-#endif
diff --git a/intern/gawain/gawain/gwn_context.h b/intern/gawain/gawain/gwn_context.h
deleted file mode 100644
index 3addce762b3..00000000000
--- a/intern/gawain/gawain/gwn_context.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-// Gawain context
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2018 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
-
-// This interface allow Gawain to manage VAOs for mutiple context and threads.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "gwn_common.h"
-#include "gwn_batch.h"
-#include "gwn_shader_interface.h"
-
-typedef struct Gwn_Context Gwn_Context;
-
-Gwn_Context* GWN_context_create(void);
-void GWN_context_discard(Gwn_Context*);
-
-void GWN_context_active_set(Gwn_Context*);
-Gwn_Context* GWN_context_active_get(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/intern/gawain/gawain/gwn_element.h b/intern/gawain/gawain/gwn_element.h
deleted file mode 100644
index 53a54cdfd76..00000000000
--- a/intern/gawain/gawain/gwn_element.h
+++ /dev/null
@@ -1,79 +0,0 @@
-
-// Gawain element list (AKA index buffer)
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_primitive.h"
-
-#define GWN_TRACK_INDEX_RANGE 1
-
-#define GWN_PRIM_RESTART 0xFFFFFFFF
-
-typedef enum {
- GWN_INDEX_U8, // GL has this, Vulkan does not
- GWN_INDEX_U16,
- GWN_INDEX_U32
-} Gwn_IndexBufType;
-
-typedef struct Gwn_IndexBuf {
- unsigned index_len;
-#if GWN_TRACK_INDEX_RANGE
- Gwn_IndexBufType index_type;
- uint32_t gl_index_type;
- unsigned min_index;
- unsigned max_index;
- unsigned base_index;
-#endif
- uint32_t vbo_id; // 0 indicates not yet sent to VRAM
- bool use_prim_restart;
-} Gwn_IndexBuf;
-
-void GWN_indexbuf_use(Gwn_IndexBuf*);
-unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf*);
-
-typedef struct Gwn_IndexBufBuilder {
- unsigned max_allowed_index;
- unsigned max_index_len;
- unsigned index_len;
- Gwn_PrimType prim_type;
- unsigned* data;
- bool use_prim_restart;
-} Gwn_IndexBufBuilder;
-
-
-// supports all primitive types.
-void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned index_len, unsigned vertex_len, bool use_prim_restart);
-
-// supports only GWN_PRIM_POINTS, GWN_PRIM_LINES and GWN_PRIM_TRIS.
-void GWN_indexbuf_init(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned prim_len, unsigned vertex_len);
-
-void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder*, unsigned v);
-void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder*);
-
-void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder*, unsigned v);
-void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2);
-void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2, unsigned v3);
-void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2, unsigned v3, unsigned v4);
-
-Gwn_IndexBuf* GWN_indexbuf_build(Gwn_IndexBufBuilder*);
-void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder*, Gwn_IndexBuf*);
-
-void GWN_indexbuf_discard(Gwn_IndexBuf*);
-
-
-/* Macros */
-
-#define GWN_INDEXBUF_DISCARD_SAFE(elem) do { \
- if (elem != NULL) { \
- GWN_indexbuf_discard(elem); \
- elem = NULL; \
- } \
-} while (0)
diff --git a/intern/gawain/gawain/gwn_imm_util.h b/intern/gawain/gawain/gwn_imm_util.h
deleted file mode 100644
index 5d17ec50669..00000000000
--- a/intern/gawain/gawain/gwn_imm_util.h
+++ /dev/null
@@ -1,22 +0,0 @@
-
-// Gawain immediate mode drawing utilities
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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
-
-
-// Draw 2D rectangles (replaces glRect functions)
-// caller is reponsible for vertex format & shader
-void immRectf(unsigned pos, float x1, float y1, float x2, float y2);
-void immRecti(unsigned pos, int x1, int y1, int x2, int y2);
-
-// Same as immRectf/immRecti but does not call immBegin/immEnd. To use with GWN_PRIM_TRIS.
-void immRectf_fast_with_color(unsigned pos, unsigned col, float x1, float y1, float x2, float y2, const float color[4]);
-void immRecti_fast_with_color(unsigned pos, unsigned col, int x1, int y1, int x2, int y2, const float color[4]);
diff --git a/intern/gawain/gawain/gwn_immediate.h b/intern/gawain/gawain/gwn_immediate.h
deleted file mode 100644
index c3ea2b911a0..00000000000
--- a/intern/gawain/gawain/gwn_immediate.h
+++ /dev/null
@@ -1,120 +0,0 @@
-
-// Gawain immediate mode work-alike
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_vertex_format.h"
-#include "gwn_primitive.h"
-#include "gwn_shader_interface.h"
-
-#define IMM_BATCH_COMBO 1
-
-
-Gwn_VertFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib
-
-void immBindProgram(uint32_t program, const Gwn_ShaderInterface*); // every immBegin must have a program bound first
-void immUnbindProgram(void); // call after your last immEnd, or before binding another program
-
-void immBegin(Gwn_PrimType, unsigned vertex_len); // must supply exactly vertex_len vertices
-void immBeginAtMost(Gwn_PrimType, unsigned max_vertex_len); // can supply fewer vertices
-void immEnd(void); // finishes and draws
-
-#if IMM_BATCH_COMBO
-#include "gwn_batch.h"
-// immBegin a batch, then use standard immFunctions as usual.
-// immEnd will finalize the batch instead of drawing.
-// Then you can draw it as many times as you like! Partially replaces the need for display lists.
-Gwn_Batch* immBeginBatch(Gwn_PrimType, unsigned vertex_len);
-Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType, unsigned vertex_len);
-#endif
-
-
-// provide attribute values that can change per vertex
-// first vertex after immBegin must have all its attributes specified
-// skipped attributes will continue using the previous value for that attrib_id
-void immAttrib1f(unsigned attrib_id, float x);
-void immAttrib2f(unsigned attrib_id, float x, float y);
-void immAttrib3f(unsigned attrib_id, float x, float y, float z);
-void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w);
-
-void immAttrib2i(unsigned attrib_id, int x, int y);
-
-void immAttrib1u(unsigned attrib_id, unsigned x);
-
-void immAttrib2s(unsigned attrib_id, short x, short y);
-
-void immAttrib2fv(unsigned attrib_id, const float data[2]);
-void immAttrib3fv(unsigned attrib_id, const float data[3]);
-void immAttrib4fv(unsigned attrib_id, const float data[4]);
-
-void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b);
-void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-
-void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]);
-void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]);
-
-// explicitly skip an attribute
-// this advanced option kills automatic value copying for this attrib_id
-void immSkipAttrib(unsigned attrib_id);
-
-
-// provide one last attribute value & end the current vertex
-// this is most often used for 2D or 3D position (similar to glVertex)
-void immVertex2f(unsigned attrib_id, float x, float y);
-void immVertex3f(unsigned attrib_id, float x, float y, float z);
-void immVertex4f(unsigned attrib_id, float x, float y, float z, float w);
-
-void immVertex2i(unsigned attrib_id, int x, int y);
-
-void immVertex2s(unsigned attrib_id, short x, short y);
-
-void immVertex2fv(unsigned attrib_id, const float data[2]);
-void immVertex3fv(unsigned attrib_id, const float data[3]);
-
-void immVertex2iv(unsigned attrib_id, const int data[2]);
-
-
-// provide uniform values that don't change for the entire draw call
-void immUniform1i(const char* name, int x);
-void immUniform4iv(const char* name, const int data[4]);
-void immUniform1f(const char* name, float x);
-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 immUniformArray4fv(const char* bare_name, const float *data, int count);
-void immUniformMatrix4fv(const char* name, const float data[4][4]);
-
-
-// convenience functions for setting "uniform vec4 color"
-// the rgb functions have implicit alpha = 1.0
-void immUniformColor4f(float r, float g, float b, float a);
-void immUniformColor4fv(const float rgba[4]);
-void immUniformColor3f(float r, float g, float b);
-void immUniformColor3fv(const float rgb[3]);
-void immUniformColor3fvAlpha(const float rgb[3], float a);
-
-void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b);
-void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-void immUniformColor3ubv(const unsigned char rgb[3]);
-void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char a);
-void immUniformColor4ubv(const unsigned char rgba[4]);
-
-
-// these are called by the system -- not part of drawing API
-
-void immInit(void);
-void immActivate(void);
-void immDeactivate(void);
-void immDestroy(void);
diff --git a/intern/gawain/gawain/gwn_primitive.h b/intern/gawain/gawain/gwn_primitive.h
deleted file mode 100644
index 3359b3582bb..00000000000
--- a/intern/gawain/gawain/gwn_primitive.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-// 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 "gwn_common.h"
-
-typedef enum {
- GWN_PRIM_POINTS,
- GWN_PRIM_LINES,
- GWN_PRIM_TRIS,
- GWN_PRIM_LINE_STRIP,
- GWN_PRIM_LINE_LOOP, // GL has this, Vulkan does not
- GWN_PRIM_TRI_STRIP,
- GWN_PRIM_TRI_FAN,
-
- GWN_PRIM_LINES_ADJ,
- GWN_PRIM_TRIS_ADJ,
- GWN_PRIM_LINE_STRIP_ADJ,
-
- GWN_PRIM_NONE
-} Gwn_PrimType;
-
-// what types of primitives does each shader expect?
-typedef enum {
- GWN_PRIM_CLASS_NONE = 0,
- GWN_PRIM_CLASS_POINT = (1 << 0),
- GWN_PRIM_CLASS_LINE = (1 << 1),
- GWN_PRIM_CLASS_SURFACE = (1 << 2),
- GWN_PRIM_CLASS_ANY = GWN_PRIM_CLASS_POINT | GWN_PRIM_CLASS_LINE | GWN_PRIM_CLASS_SURFACE
-} Gwn_PrimClass;
-
-Gwn_PrimClass GWN_primtype_class(Gwn_PrimType);
-bool GWN_primtype_belongs_to_class(Gwn_PrimType, Gwn_PrimClass);
diff --git a/intern/gawain/gawain/gwn_primitive_private.h b/intern/gawain/gawain/gwn_primitive_private.h
deleted file mode 100644
index d959cd89852..00000000000
--- a/intern/gawain/gawain/gwn_primitive_private.h
+++ /dev/null
@@ -1,14 +0,0 @@
-
-// Gawain geometric primitives (private interface for use inside Gawain)
-//
-// 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
-
-GLenum convert_prim_type_to_gl(Gwn_PrimType);
diff --git a/intern/gawain/gawain/gwn_shader_interface.h b/intern/gawain/gawain/gwn_shader_interface.h
deleted file mode 100644
index b27b12c18d8..00000000000
--- a/intern/gawain/gawain/gwn_shader_interface.h
+++ /dev/null
@@ -1,81 +0,0 @@
-
-// 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 "gwn_common.h"
-
-typedef enum {
- GWN_UNIFORM_NONE = 0, // uninitialized/unknown
-
- GWN_UNIFORM_MODEL, // mat4 ModelMatrix
- GWN_UNIFORM_VIEW, // mat4 ViewMatrix
- GWN_UNIFORM_MODELVIEW, // mat4 ModelViewMatrix
- GWN_UNIFORM_PROJECTION, // mat4 ProjectionMatrix
- GWN_UNIFORM_VIEWPROJECTION, // mat4 ViewProjectionMatrix
- GWN_UNIFORM_MVP, // mat4 ModelViewProjectionMatrix
-
- GWN_UNIFORM_MODEL_INV, // mat4 ModelMatrixInverse
- GWN_UNIFORM_VIEW_INV, // mat4 ViewMatrixInverse
- GWN_UNIFORM_MODELVIEW_INV, // mat4 ModelViewMatrixInverse
- GWN_UNIFORM_PROJECTION_INV, // mat4 ProjectionMatrixInverse
- GWN_UNIFORM_VIEWPROJECTION_INV, // mat4 ViewProjectionMatrixInverse
-
- GWN_UNIFORM_NORMAL, // mat3 NormalMatrix
- GWN_UNIFORM_WORLDNORMAL, // mat3 WorldNormalMatrix
- GWN_UNIFORM_CAMERATEXCO, // vec4 CameraTexCoFactors
- GWN_UNIFORM_ORCO, // vec3 OrcoTexCoFactors[]
-
- GWN_UNIFORM_COLOR, // vec4 color
- GWN_UNIFORM_EYE, // vec3 eye
- GWN_UNIFORM_CALLID, // int callId
-
- GWN_UNIFORM_CUSTOM, // custom uniform, not one of the above built-ins
-
- GWN_NUM_UNIFORMS, // Special value, denotes number of builtin uniforms.
-} Gwn_UniformBuiltin;
-
-typedef struct Gwn_ShaderInput {
- struct Gwn_ShaderInput* next;
- uint32_t name_offset;
- unsigned name_hash;
- Gwn_UniformBuiltin builtin_type; // only for uniform inputs
- uint32_t gl_type; // only for attrib inputs
- int32_t size; // only for attrib inputs
- int32_t location;
-} Gwn_ShaderInput;
-
-#define GWN_NUM_SHADERINTERFACE_BUCKETS 257
-#define GWN_SHADERINTERFACE_REF_ALLOC_COUNT 16
-
-typedef struct Gwn_ShaderInterface {
- int32_t program;
- uint32_t name_buffer_offset;
- Gwn_ShaderInput* attrib_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS];
- Gwn_ShaderInput* uniform_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS];
- Gwn_ShaderInput* ubo_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS];
- Gwn_ShaderInput* builtin_uniforms[GWN_NUM_UNIFORMS];
- char* name_buffer;
- struct Gwn_Batch** batches; // references to batches using this interface
- unsigned batches_len;
-} Gwn_ShaderInterface;
-
-Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program_id);
-void GWN_shaderinterface_discard(Gwn_ShaderInterface*);
-
-const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface*, const char* name);
-const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface*, Gwn_UniformBuiltin);
-const Gwn_ShaderInput* GWN_shaderinterface_ubo(const Gwn_ShaderInterface*, const char* name);
-const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface*, const char* name);
-
-// keep track of batches using this interface
-void GWN_shaderinterface_add_batch_ref(Gwn_ShaderInterface*, struct Gwn_Batch*);
-void GWN_shaderinterface_remove_batch_ref(Gwn_ShaderInterface*, struct Gwn_Batch*);
diff --git a/intern/gawain/gawain/gwn_vertex_array_id.h b/intern/gawain/gawain/gwn_vertex_array_id.h
deleted file mode 100644
index 1c093d428ce..00000000000
--- a/intern/gawain/gawain/gwn_vertex_array_id.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-// Gawain buffer IDs
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2018 Mike Erwin, Clément Foucault
-//
-// 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
-
-// Manage GL vertex array IDs in a thread-safe way
-// Use these instead of glGenBuffers & its friends
-// - alloc must be called from a thread that is bound
-// to the context that will be used for drawing with
-// this vao.
-// - free can be called from any thread
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "gwn_common.h"
-#include "gwn_context.h"
-
-GLuint GWN_vao_default(void);
-GLuint GWN_vao_alloc(void);
-void GWN_vao_free(GLuint vao_id, Gwn_Context*);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/intern/gawain/gawain/gwn_vertex_buffer.h b/intern/gawain/gawain/gwn_vertex_buffer.h
deleted file mode 100644
index 0eac4838e65..00000000000
--- a/intern/gawain/gawain/gwn_vertex_buffer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-
-// Gawain vertex buffer
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_vertex_format.h"
-
-#define VRAM_USAGE 1
-// How to create a Gwn_VertBuf:
-// 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts)
-// 2) GWN_vertformat_attr_add(verts->format, ...)
-// 3) GWN_vertbuf_data_alloc(verts, vertex_len) <-- finalizes/packs vertex format
-// 4) GWN_vertbuf_attr_fill(verts, pos, application_pos_buffer)
-
-// Is Gwn_VertBuf always used as part of a Gwn_Batch?
-
-typedef enum {
- // can be extended to support more types
- GWN_USAGE_STREAM,
- GWN_USAGE_STATIC, // do not keep data in memory
- GWN_USAGE_DYNAMIC
-} Gwn_UsageType;
-
-typedef struct Gwn_VertBuf {
- Gwn_VertFormat format;
- unsigned vertex_len; /* number of verts we want to draw */
- unsigned vertex_alloc; /* number of verts data */
- bool dirty;
- unsigned char* data; // NULL indicates data in VRAM (unmapped)
- uint32_t vbo_id; // 0 indicates not yet allocated
- Gwn_UsageType usage; // usage hint for GL optimisation
-} Gwn_VertBuf;
-
-Gwn_VertBuf* GWN_vertbuf_create(Gwn_UsageType);
-Gwn_VertBuf* GWN_vertbuf_create_with_format_ex(const Gwn_VertFormat*, Gwn_UsageType);
-
-#define GWN_vertbuf_create_with_format(format) \
- GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_STATIC)
-
-void GWN_vertbuf_discard(Gwn_VertBuf*);
-
-void GWN_vertbuf_init(Gwn_VertBuf*, Gwn_UsageType);
-void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf*, const Gwn_VertFormat*, Gwn_UsageType);
-
-#define GWN_vertbuf_init_with_format(verts, format) \
- GWN_vertbuf_init_with_format_ex(verts, format, GWN_USAGE_STATIC)
-
-unsigned GWN_vertbuf_size_get(const Gwn_VertBuf*);
-void GWN_vertbuf_data_alloc(Gwn_VertBuf*, unsigned v_len);
-void GWN_vertbuf_data_resize(Gwn_VertBuf*, unsigned v_len);
-void GWN_vertbuf_vertex_count_set(Gwn_VertBuf*, unsigned v_len);
-
-// The most important set_attrib variant is the untyped one. Get it right first.
-// It takes a void* so the app developer is responsible for matching their app data types
-// to the vertex attribute's type and component count. They're in control of both, so this
-// should not be a problem.
-
-void GWN_vertbuf_attr_set(Gwn_VertBuf*, unsigned a_idx, unsigned v_idx, const void* data);
-void GWN_vertbuf_attr_fill(Gwn_VertBuf*, unsigned a_idx, const void* data); // tightly packed, non interleaved input data
-void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf*, unsigned a_idx, unsigned stride, const void* data);
-
-// For low level access only
-typedef struct Gwn_VertBufRaw {
- unsigned size;
- unsigned stride;
- unsigned char* data;
- unsigned char* data_init;
-#if TRUST_NO_ONE
- // Only for overflow check
- unsigned char* _data_end;
-#endif
-} Gwn_VertBufRaw;
-
-GWN_INLINE void *GWN_vertbuf_raw_step(Gwn_VertBufRaw *a)
- {
- unsigned char* data = a->data;
- a->data += a->stride;
-#if TRUST_NO_ONE
- assert(data < a->_data_end);
-#endif
- return (void *)data;
- }
-
-GWN_INLINE unsigned GWN_vertbuf_raw_used(Gwn_VertBufRaw *a)
- {
- return ((a->data - a->data_init) / a->stride);
- }
-
-void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf*, unsigned a_idx, Gwn_VertBufRaw *access);
-
-// TODO: decide whether to keep the functions below
-// doesn't immediate mode satisfy these needs?
-
-// void setAttrib1f(unsigned a_idx, unsigned v_idx, float x);
-// void setAttrib2f(unsigned a_idx, unsigned v_idx, float x, float y);
-// void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z);
-// void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w);
-//
-// void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b);
-// void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-
-void GWN_vertbuf_use(Gwn_VertBuf*);
-
-
-// Metrics
-
-unsigned GWN_vertbuf_get_memory_usage(void);
-
-
-// Macros
-
-#define GWN_VERTBUF_DISCARD_SAFE(verts) do { \
- if (verts != NULL) { \
- GWN_vertbuf_discard(verts); \
- verts = NULL; \
- } \
-} while (0)
diff --git a/intern/gawain/gawain/gwn_vertex_format.h b/intern/gawain/gawain/gwn_vertex_format.h
deleted file mode 100644
index a4593e4615b..00000000000
--- a/intern/gawain/gawain/gwn_vertex_format.h
+++ /dev/null
@@ -1,78 +0,0 @@
-
-// Gawain vertex format
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_common.h"
-
-#define GWN_VERT_ATTR_MAX_LEN 16
-#define GWN_VERT_ATTR_MAX_NAMES 3
-#define GWN_VERT_ATTR_NAME_AVERAGE_LEN 11
-#define GWN_VERT_ATTR_NAMES_BUF_LEN ((GWN_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GWN_VERT_ATTR_MAX_LEN)
-
-typedef enum {
- GWN_COMP_I8,
- GWN_COMP_U8,
- GWN_COMP_I16,
- GWN_COMP_U16,
- GWN_COMP_I32,
- GWN_COMP_U32,
-
- GWN_COMP_F32,
-
- GWN_COMP_I10
-} Gwn_VertCompType;
-
-typedef enum {
- GWN_FETCH_FLOAT,
- GWN_FETCH_INT,
- GWN_FETCH_INT_TO_FLOAT_UNIT, // 127 (ubyte) -> 0.5 (and so on for other int types)
- GWN_FETCH_INT_TO_FLOAT // 127 (any int type) -> 127.0
-} Gwn_VertFetchMode;
-
-typedef struct Gwn_VertAttr {
- Gwn_VertFetchMode fetch_mode;
- Gwn_VertCompType comp_type;
- unsigned gl_comp_type;
- unsigned comp_len; // 1 to 4 or 8 or 12 or 16
- unsigned sz; // size in bytes, 1 to 64
- unsigned offset; // from beginning of vertex, in bytes
- unsigned name_len; // up to GWN_VERT_ATTR_MAX_NAMES
- const char* name[GWN_VERT_ATTR_MAX_NAMES];
-} Gwn_VertAttr;
-
-typedef struct Gwn_VertFormat {
- unsigned attr_len; // 0 to 16 (GWN_VERT_ATTR_MAX_LEN)
- unsigned name_len; // total count of active vertex attrib
- unsigned stride; // stride in bytes, 1 to 256
- unsigned name_offset;
- bool packed;
- char names[GWN_VERT_ATTR_NAMES_BUF_LEN];
- Gwn_VertAttr attribs[GWN_VERT_ATTR_MAX_LEN]; // TODO: variable-size attribs array
-} Gwn_VertFormat;
-
-void GWN_vertformat_clear(Gwn_VertFormat*);
-void GWN_vertformat_copy(Gwn_VertFormat* dest, const Gwn_VertFormat* src);
-
-unsigned GWN_vertformat_attr_add(Gwn_VertFormat*, const char* name, Gwn_VertCompType, unsigned comp_len, Gwn_VertFetchMode);
-void GWN_vertformat_alias_add(Gwn_VertFormat*, const char* alias);
-
-// format conversion
-
-typedef struct Gwn_PackedNormal {
- int x : 10;
- int y : 10;
- int z : 10;
- int w : 2; // 0 by default, can manually set to { -2, -1, 0, 1 }
-} Gwn_PackedNormal;
-
-Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3]);
-Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3]);
diff --git a/intern/gawain/gawain/gwn_vertex_format_private.h b/intern/gawain/gawain/gwn_vertex_format_private.h
deleted file mode 100644
index 90cd8412e53..00000000000
--- a/intern/gawain/gawain/gwn_vertex_format_private.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-// Gawain vertex format (private interface for use inside Gawain)
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016-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
-
-void VertexFormat_pack(Gwn_VertFormat*);
-unsigned padding(unsigned offset, unsigned alignment);
-unsigned vertex_buffer_size(const Gwn_VertFormat*, unsigned vertex_len);
diff --git a/intern/gawain/src/gwn_attr_binding.c b/intern/gawain/src/gwn_attr_binding.c
deleted file mode 100644
index c702a0ae99d..00000000000
--- a/intern/gawain/src/gwn_attr_binding.c
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Gawain vertex attribute binding
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_attr_binding.h"
-#include "gwn_attr_binding_private.h"
-#include <stddef.h>
-
-#if GWN_VERT_ATTR_MAX_LEN != 16
- #error "attrib binding code assumes GWN_VERT_ATTR_MAX_LEN = 16"
-#endif
-
-void AttribBinding_clear(Gwn_AttrBinding* binding)
- {
- binding->loc_bits = 0;
- binding->enabled_bits = 0;
- }
-
-unsigned read_attrib_location(const Gwn_AttrBinding* binding, unsigned a_idx)
- {
-#if TRUST_NO_ONE
- assert(a_idx < GWN_VERT_ATTR_MAX_LEN);
- assert(binding->enabled_bits & (1 << a_idx));
-#endif
-
- return (binding->loc_bits >> (4 * a_idx)) & 0xF;
- }
-
-static void write_attrib_location(Gwn_AttrBinding* binding, unsigned a_idx, unsigned location)
- {
-#if TRUST_NO_ONE
- assert(a_idx < GWN_VERT_ATTR_MAX_LEN);
- assert(location < GWN_VERT_ATTR_MAX_LEN);
-#endif
-
- const unsigned shift = 4 * a_idx;
- const uint64_t mask = ((uint64_t)0xF) << shift;
- // overwrite this attrib's previous location
- binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
- // mark this attrib as enabled
- binding->enabled_bits |= 1 << a_idx;
- }
-
-void get_attrib_locations(const Gwn_VertFormat* format, Gwn_AttrBinding* binding, const Gwn_ShaderInterface* shaderface)
- {
- AttribBinding_clear(binding);
-
- for (unsigned a_idx = 0; a_idx < format->attr_len; ++a_idx)
- {
- const Gwn_VertAttr* a = format->attribs + a_idx;
- for (unsigned n_idx = 0; n_idx < a->name_len; ++n_idx)
- {
- const Gwn_ShaderInput* input = GWN_shaderinterface_attr(shaderface, a->name[n_idx]);
-
-#if TRUST_NO_ONE
- assert(input != NULL);
- // TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program
-#endif
-
- write_attrib_location(binding, a_idx, input->location);
- }
- }
- }
diff --git a/intern/gawain/src/gwn_batch.c b/intern/gawain/src/gwn_batch.c
deleted file mode 100644
index 62342cfc42f..00000000000
--- a/intern/gawain/src/gwn_batch.c
+++ /dev/null
@@ -1,632 +0,0 @@
-
-// Gawain geometry batch
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_batch.h"
-#include "gwn_batch_private.h"
-#include "gwn_buffer_id.h"
-#include "gwn_vertex_array_id.h"
-#include "gwn_primitive_private.h"
-#include <stdlib.h>
-#include <string.h>
-
-// necessary functions from matrix API
-extern void gpuBindMatrices(const Gwn_ShaderInterface* shaderface);
-
-static void batch_update_program_bindings(Gwn_Batch* batch, unsigned int v_first);
-
-void gwn_batch_vao_cache_clear(Gwn_Batch* batch)
- {
- if (batch->context == NULL)
- return;
-
- if (batch->is_dynamic_vao_count)
- {
- for (int i = 0; i < batch->dynamic_vaos.count; ++i)
- {
- if (batch->dynamic_vaos.vao_ids[i])
- GWN_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context);
- if (batch->dynamic_vaos.interfaces[i])
- GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface *)batch->dynamic_vaos.interfaces[i], batch);
- }
- free(batch->dynamic_vaos.interfaces);
- free(batch->dynamic_vaos.vao_ids);
- }
- else
- {
- for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- {
- if (batch->static_vaos.vao_ids[i])
- GWN_vao_free(batch->static_vaos.vao_ids[i], batch->context);
- if (batch->static_vaos.interfaces[i])
- GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface *)batch->static_vaos.interfaces[i], batch);
- }
- }
-
- batch->is_dynamic_vao_count = false;
- for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- {
- batch->static_vaos.vao_ids[i] = 0;
- batch->static_vaos.interfaces[i] = NULL;
- }
-
- gwn_context_remove_batch(batch->context, batch);
- batch->context = NULL;
- }
-
-Gwn_Batch* GWN_batch_create_ex(
- Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem,
- unsigned owns_flag)
- {
- Gwn_Batch* batch = calloc(1, sizeof(Gwn_Batch));
-
- GWN_batch_init_ex(batch, prim_type, verts, elem, owns_flag);
-
- return batch;
- }
-
-void GWN_batch_init_ex(
- Gwn_Batch* batch, Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem,
- unsigned owns_flag)
- {
-#if TRUST_NO_ONE
- assert(verts != NULL);
-#endif
-
- batch->verts[0] = verts;
- for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v)
- batch->verts[v] = NULL;
- batch->inst = NULL;
- batch->elem = elem;
- batch->gl_prim_type = convert_prim_type_to_gl(prim_type);
- batch->phase = GWN_BATCH_READY_TO_DRAW;
- batch->is_dynamic_vao_count = false;
- batch->owns_flag = owns_flag;
- batch->free_callback = NULL;
- }
-
-// This will share the VBOs with the new batch
-Gwn_Batch* GWN_batch_duplicate(Gwn_Batch* batch_src)
- {
- Gwn_Batch* batch = GWN_batch_create_ex(GWN_PRIM_POINTS, batch_src->verts[0], batch_src->elem, 0);
-
- batch->gl_prim_type = batch_src->gl_prim_type;
- for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v)
- batch->verts[v] = batch_src->verts[v];
-
- return batch;
- }
-
-void GWN_batch_discard(Gwn_Batch* batch)
- {
- if (batch->owns_flag & GWN_BATCH_OWNS_INDEX)
- GWN_indexbuf_discard(batch->elem);
-
- if (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES)
- GWN_vertbuf_discard(batch->inst);
-
- if ((batch->owns_flag & ~GWN_BATCH_OWNS_INDEX) != 0)
- {
- for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v)
- {
- if (batch->verts[v] == NULL)
- break;
- if (batch->owns_flag & (1 << v))
- GWN_vertbuf_discard(batch->verts[v]);
- }
- }
-
- gwn_batch_vao_cache_clear(batch);
-
- if (batch->free_callback)
- batch->free_callback(batch, batch->callback_data);
-
- free(batch);
- }
-
-void GWN_batch_callback_free_set(Gwn_Batch* batch, void (*callback)(Gwn_Batch*, void*), void* user_data)
- {
- batch->free_callback = callback;
- batch->callback_data = user_data;
- }
-
-void GWN_batch_instbuf_set(Gwn_Batch* batch, Gwn_VertBuf* inst, bool own_vbo)
- {
-#if TRUST_NO_ONE
- assert(inst != NULL);
-#endif
- // redo the bindings
- gwn_batch_vao_cache_clear(batch);
-
- if (batch->inst != NULL && (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES))
- GWN_vertbuf_discard(batch->inst);
-
- batch->inst = inst;
-
- if (own_vbo)
- batch->owns_flag |= GWN_BATCH_OWNS_INSTANCES;
- else
- batch->owns_flag &= ~GWN_BATCH_OWNS_INSTANCES;
- }
-
-int GWN_batch_vertbuf_add_ex(
- Gwn_Batch* batch, Gwn_VertBuf* verts,
- bool own_vbo)
- {
- // redo the bindings
- gwn_batch_vao_cache_clear(batch);
-
- for (unsigned v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v)
- {
- if (batch->verts[v] == NULL)
- {
-#if TRUST_NO_ONE
- // for now all VertexBuffers must have same vertex_len
- assert(verts->vertex_len == batch->verts[0]->vertex_len);
- // in the near future we will enable instanced attribs which have their own vertex_len
-#endif
- batch->verts[v] = verts;
- // TODO: mark dirty so we can keep attrib bindings up-to-date
- if (own_vbo)
- batch->owns_flag |= (1 << v);
- return v;
- }
- }
-
- // we only make it this far if there is no room for another Gwn_VertBuf
-#if TRUST_NO_ONE
- assert(false);
-#endif
- return -1;
- }
-
-static GLuint batch_vao_get(Gwn_Batch *batch)
- {
- // Search through cache
- if (batch->is_dynamic_vao_count)
- {
- for (int i = 0; i < batch->dynamic_vaos.count; ++i)
- if (batch->dynamic_vaos.interfaces[i] == batch->interface)
- return batch->dynamic_vaos.vao_ids[i];
- }
- else
- {
- for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- if (batch->static_vaos.interfaces[i] == batch->interface)
- return batch->static_vaos.vao_ids[i];
- }
-
- // Set context of this batch.
- // It will be bound to it until gwn_batch_vao_cache_clear is called.
- // Until then it can only be drawn with this context.
- if (batch->context == NULL)
- {
- batch->context = GWN_context_active_get();
- gwn_context_add_batch(batch->context, batch);
- }
-#if TRUST_NO_ONE
- else // Make sure you are not trying to draw this batch in another context.
- assert(batch->context == GWN_context_active_get());
-#endif
-
- // Cache miss, time to add a new entry!
- GLuint new_vao = 0;
- if (!batch->is_dynamic_vao_count)
- {
- int i; // find first unused slot
- for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- if (batch->static_vaos.vao_ids[i] == 0)
- break;
-
- if (i < GWN_BATCH_VAO_STATIC_LEN)
- {
- batch->static_vaos.interfaces[i] = batch->interface;
- batch->static_vaos.vao_ids[i] = new_vao = GWN_vao_alloc();
- }
- else
- {
- // Not enough place switch to dynamic.
- batch->is_dynamic_vao_count = true;
- // Erase previous entries, they will be added back if drawn again.
- for (int j = 0; j < GWN_BATCH_VAO_STATIC_LEN; ++j)
- {
- GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface*)batch->static_vaos.interfaces[j], batch);
- GWN_vao_free(batch->static_vaos.vao_ids[j], batch->context);
- }
- // Init dynamic arrays and let the branch below set the values.
- batch->dynamic_vaos.count = GWN_BATCH_VAO_DYN_ALLOC_COUNT;
- batch->dynamic_vaos.interfaces = calloc(batch->dynamic_vaos.count, sizeof(Gwn_ShaderInterface*));
- batch->dynamic_vaos.vao_ids = calloc(batch->dynamic_vaos.count, sizeof(GLuint));
- }
- }
-
- if (batch->is_dynamic_vao_count)
- {
- int i; // find first unused slot
- for (i = 0; i < batch->dynamic_vaos.count; ++i)
- if (batch->dynamic_vaos.vao_ids[i] == 0)
- break;
-
- if (i == batch->dynamic_vaos.count)
- {
- // Not enough place, realloc the array.
- i = batch->dynamic_vaos.count;
- batch->dynamic_vaos.count += GWN_BATCH_VAO_DYN_ALLOC_COUNT;
- batch->dynamic_vaos.interfaces = realloc(batch->dynamic_vaos.interfaces, sizeof(Gwn_ShaderInterface*) * batch->dynamic_vaos.count);
- batch->dynamic_vaos.vao_ids = realloc(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count);
- memset(batch->dynamic_vaos.interfaces + i, 0, sizeof(Gwn_ShaderInterface*) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
- memset(batch->dynamic_vaos.vao_ids + i, 0, sizeof(GLuint) * GWN_BATCH_VAO_DYN_ALLOC_COUNT);
- }
-
- batch->dynamic_vaos.interfaces[i] = batch->interface;
- batch->dynamic_vaos.vao_ids[i] = new_vao = GWN_vao_alloc();
- }
-
- GWN_shaderinterface_add_batch_ref((Gwn_ShaderInterface*)batch->interface, batch);
-
-#if TRUST_NO_ONE
- assert(new_vao != 0);
-#endif
-
- // We just got a fresh VAO we need to initialize it.
- glBindVertexArray(new_vao);
- batch_update_program_bindings(batch, 0);
- glBindVertexArray(0);
-
- return new_vao;
- }
-
-void GWN_batch_program_set_no_use(Gwn_Batch* batch, uint32_t program, const Gwn_ShaderInterface* shaderface)
- {
-#if TRUST_NO_ONE
- assert(glIsProgram(shaderface->program));
- assert(batch->program_in_use == 0);
-#endif
-
- batch->interface = shaderface;
- batch->program = program;
- batch->vao_id = batch_vao_get(batch);
- }
-
-void GWN_batch_program_set(Gwn_Batch* batch, uint32_t program, const Gwn_ShaderInterface* shaderface)
- {
- GWN_batch_program_set_no_use(batch, program, shaderface);
- GWN_batch_program_use_begin(batch); // hack! to make Batch_Uniform* simpler
- }
-
-void gwn_batch_remove_interface_ref(Gwn_Batch* batch, const Gwn_ShaderInterface* interface)
- {
- if (batch->is_dynamic_vao_count)
- {
- for (int i = 0; i < batch->dynamic_vaos.count; ++i)
- {
- if (batch->dynamic_vaos.interfaces[i] == interface)
- {
- GWN_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context);
- batch->dynamic_vaos.vao_ids[i] = 0;
- batch->dynamic_vaos.interfaces[i] = NULL;
- break; // cannot have duplicates
- }
- }
- }
- else
- {
- int i;
- for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i)
- {
- if (batch->static_vaos.interfaces[i] == interface)
- {
- GWN_vao_free(batch->static_vaos.vao_ids[i], batch->context);
- batch->static_vaos.vao_ids[i] = 0;
- batch->static_vaos.interfaces[i] = NULL;
- break; // cannot have duplicates
- }
- }
- }
- }
-
-static void create_bindings(Gwn_VertBuf* verts, const Gwn_ShaderInterface* interface, unsigned int v_first, const bool use_instancing)
- {
- const Gwn_VertFormat* format = &verts->format;
-
- const unsigned attr_len = format->attr_len;
- const unsigned stride = format->stride;
-
- GWN_vertbuf_use(verts);
-
- for (unsigned a_idx = 0; a_idx < attr_len; ++a_idx)
- {
- const Gwn_VertAttr* a = format->attribs + a_idx;
-
- const GLvoid* pointer = (const GLubyte*)0 + a->offset + v_first * stride;
-
- for (unsigned n_idx = 0; n_idx < a->name_len; ++n_idx)
- {
- const Gwn_ShaderInput* input = GWN_shaderinterface_attr(interface, a->name[n_idx]);
-
- if (input == NULL) continue;
-
- if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8)
- {
-#if TRUST_NO_ONE
- assert(a->fetch_mode == GWN_FETCH_FLOAT);
- assert(a->gl_comp_type == GL_FLOAT);
-#endif
- for (int i = 0; i < a->comp_len / 4; ++i)
- {
- glEnableVertexAttribArray(input->location + i);
- glVertexAttribDivisor(input->location + i, (use_instancing) ? 1 : 0);
- glVertexAttribPointer(input->location + i, 4, a->gl_comp_type, GL_FALSE, stride,
- (const GLubyte*)pointer + i * 16);
- }
- }
- else
- {
- glEnableVertexAttribArray(input->location);
- glVertexAttribDivisor(input->location, (use_instancing) ? 1 : 0);
-
- switch (a->fetch_mode)
- {
- case GWN_FETCH_FLOAT:
- case GWN_FETCH_INT_TO_FLOAT:
- glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer);
- break;
- case GWN_FETCH_INT_TO_FLOAT_UNIT:
- glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer);
- break;
- case GWN_FETCH_INT:
- glVertexAttribIPointer(input->location, a->comp_len, a->gl_comp_type, stride, pointer);
- }
- }
- }
- }
- }
-
-static void batch_update_program_bindings(Gwn_Batch* batch, unsigned int v_first)
- {
- for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v)
- create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
-
- if (batch->inst)
- create_bindings(batch->inst, batch->interface, v_first, true);
-
- if (batch->elem)
- GWN_indexbuf_use(batch->elem);
- }
-
-void GWN_batch_program_use_begin(Gwn_Batch* batch)
- {
- // NOTE: use_program & done_using_program are fragile, depend on staying in sync with
- // the GL context's active program. use_program doesn't mark other programs as "not used".
- // TODO: make not fragile (somehow)
-
- if (!batch->program_in_use)
- {
- glUseProgram(batch->program);
- batch->program_in_use = true;
- }
- }
-
-void GWN_batch_program_use_end(Gwn_Batch* batch)
- {
- if (batch->program_in_use)
- {
-#if PROGRAM_NO_OPTI
- glUseProgram(0);
-#endif
- batch->program_in_use = false;
- }
- }
-
-#if TRUST_NO_ONE
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(batch->interface, name); assert(uniform);
-#else
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(batch->interface, name);
-#endif
-
-void GWN_batch_uniform_1ui(Gwn_Batch* batch, const char* name, int value)
- {
- GET_UNIFORM
- glUniform1ui(uniform->location, value);
- }
-
-void GWN_batch_uniform_1i(Gwn_Batch* batch, const char* name, int value)
- {
- GET_UNIFORM
- glUniform1i(uniform->location, value);
- }
-
-void GWN_batch_uniform_1b(Gwn_Batch* batch, const char* name, bool value)
- {
- GET_UNIFORM
- glUniform1i(uniform->location, value ? GL_TRUE : GL_FALSE);
- }
-
-void GWN_batch_uniform_2f(Gwn_Batch* batch, const char* name, float x, float y)
- {
- GET_UNIFORM
- glUniform2f(uniform->location, x, y);
- }
-
-void GWN_batch_uniform_3f(Gwn_Batch* batch, const char* name, float x, float y, float z)
- {
- GET_UNIFORM
- glUniform3f(uniform->location, x, y, z);
- }
-
-void GWN_batch_uniform_4f(Gwn_Batch* batch, const char* name, float x, float y, float z, float w)
- {
- GET_UNIFORM
- glUniform4f(uniform->location, x, y, z, w);
- }
-
-void GWN_batch_uniform_1f(Gwn_Batch* batch, const char* name, float x)
- {
- GET_UNIFORM
- glUniform1f(uniform->location, x);
- }
-
-void GWN_batch_uniform_2fv(Gwn_Batch* batch, const char* name, const float data[2])
- {
- GET_UNIFORM
- glUniform2fv(uniform->location, 1, data);
- }
-
-void GWN_batch_uniform_3fv(Gwn_Batch* batch, const char* name, const float data[3])
- {
- GET_UNIFORM
- glUniform3fv(uniform->location, 1, data);
- }
-
-void GWN_batch_uniform_4fv(Gwn_Batch* batch, const char* name, const float data[4])
- {
- GET_UNIFORM
- glUniform4fv(uniform->location, 1, data);
- }
-
-void GWN_batch_uniform_2fv_array(Gwn_Batch* batch, const char* name, const int len, const float *data)
- {
- GET_UNIFORM
- glUniform2fv(uniform->location, len, data);
- }
-
-void GWN_batch_uniform_4fv_array(Gwn_Batch* batch, const char* name, const int len, const float *data)
- {
- GET_UNIFORM
- glUniform4fv(uniform->location, len, data);
- }
-
-void GWN_batch_uniform_mat4(Gwn_Batch* batch, const char* name, const float data[4][4])
- {
- GET_UNIFORM
- glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data);
- }
-
-static void primitive_restart_enable(const Gwn_IndexBuf *el)
-{
- // TODO(fclem) Replace by GL_PRIMITIVE_RESTART_FIXED_INDEX when we have ogl 4.3
- glEnable(GL_PRIMITIVE_RESTART);
- GLuint restart_index = (GLuint)0xFFFFFFFF;
-
-#if GWN_TRACK_INDEX_RANGE
- if (el->index_type == GWN_INDEX_U8)
- restart_index = (GLuint)0xFF;
- else if (el->index_type == GWN_INDEX_U16)
- restart_index = (GLuint)0xFFFF;
-#endif
-
- glPrimitiveRestartIndex(restart_index);
-}
-
-static void primitive_restart_disable(void)
-{
- glDisable(GL_PRIMITIVE_RESTART);
-}
-
-void GWN_batch_draw(Gwn_Batch* batch)
- {
-#if TRUST_NO_ONE
- assert(batch->phase == GWN_BATCH_READY_TO_DRAW);
- assert(batch->verts[0]->vbo_id != 0);
-#endif
- GWN_batch_program_use_begin(batch);
- gpuBindMatrices(batch->interface); // external call.
-
- GWN_batch_draw_range_ex(batch, 0, 0, false);
-
- GWN_batch_program_use_end(batch);
- }
-
-void GWN_batch_draw_range_ex(Gwn_Batch* batch, int v_first, int v_count, bool force_instance)
- {
-#if TRUST_NO_ONE
- assert(!(force_instance && (batch->inst == NULL)) || v_count > 0); // we cannot infer length if force_instance
-#endif
- const bool do_instance = (force_instance || batch->inst);
-
- // If using offset drawing, use the default VAO and redo bindings.
- if (v_first != 0 && (do_instance || batch->elem))
- {
- glBindVertexArray(GWN_vao_default());
- batch_update_program_bindings(batch, v_first);
- }
- else
- glBindVertexArray(batch->vao_id);
-
- if (do_instance)
- {
- // Infer length if vertex count is not given
- if (v_count == 0)
- v_count = batch->inst->vertex_len;
-
- if (batch->elem)
- {
- const Gwn_IndexBuf* el = batch->elem;
-
- if (el->use_prim_restart)
- primitive_restart_enable(el);
-
-#if GWN_TRACK_INDEX_RANGE
- glDrawElementsInstancedBaseVertex(batch->gl_prim_type, el->index_len, el->gl_index_type, 0, v_count, el->base_index);
-#else
- glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count);
-#endif
- if (el->use_prim_restart)
- primitive_restart_disable();
- }
- else
- glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count);
- }
- else
- {
- // Infer length if vertex count is not given
- if (v_count == 0)
- v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len;
-
- if (batch->elem)
- {
- const Gwn_IndexBuf* el = batch->elem;
-
- if (el->use_prim_restart)
- primitive_restart_enable(el);
-
-#if GWN_TRACK_INDEX_RANGE
- if (el->base_index)
- glDrawRangeElementsBaseVertex(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0, el->base_index);
- else
- glDrawRangeElements(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0);
-#else
- glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, 0);
-#endif
- if (el->use_prim_restart)
- primitive_restart_disable();
- }
- else
- glDrawArrays(batch->gl_prim_type, v_first, v_count);
- }
-
- // Performance hog if you are drawing with the same vao multiple time.
- // Only activate for debugging.
- // glBindVertexArray(0);
- }
-
-// just draw some vertices and let shader place them where we want.
-void GWN_draw_primitive(Gwn_PrimType prim_type, int v_count)
- {
- // we cannot draw without vao ... annoying ...
- glBindVertexArray(GWN_vao_default());
-
- GLenum type = convert_prim_type_to_gl(prim_type);
- glDrawArrays(type, 0, v_count);
-
- // Performance hog if you are drawing with the same vao multiple time.
- // Only activate for debugging.
- // glBindVertexArray(0);
- }
diff --git a/intern/gawain/src/gwn_buffer_id.cpp b/intern/gawain/src/gwn_buffer_id.cpp
deleted file mode 100644
index 13473f1f28d..00000000000
--- a/intern/gawain/src/gwn_buffer_id.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Gawain buffer IDs
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "buffer_id.h"
-
-#include "gwn_buffer_id.h"
-#include <mutex>
-#include <vector>
-
-#define ORPHAN_DEBUG 0
-
-#if ORPHAN_DEBUG
- #include <cstdio>
-#endif
-
-static std::vector<GLuint> orphaned_buffer_ids;
-
-static std::mutex orphan_mutex;
-
-extern "C" {
-extern int BLI_thread_is_main(void); // Blender-specific function
-}
-
-static bool thread_is_main()
- {
- // "main" here means the GL context's thread
- return BLI_thread_is_main();
- }
-
-GLuint GWN_buf_id_alloc()
- {
- // delete orphaned IDs
- orphan_mutex.lock();
- if (!orphaned_buffer_ids.empty())
- {
- const auto orphaned_buffer_len = (unsigned)orphaned_buffer_ids.size();
-#if ORPHAN_DEBUG
- printf("deleting %u orphaned VBO%s\n", orphaned_buffer_len, orphaned_buffer_len == 1 ? "" : "s");
-#endif
- glDeleteBuffers(orphaned_buffer_len, orphaned_buffer_ids.data());
- orphaned_buffer_ids.clear();
- }
- orphan_mutex.unlock();
-
- GLuint new_buffer_id = 0;
- glGenBuffers(1, &new_buffer_id);
- return new_buffer_id;
- }
-
-void GWN_buf_id_free(GLuint buffer_id)
- {
- if (thread_is_main())
- glDeleteBuffers(1, &buffer_id);
- else
- {
- // add this ID to the orphaned list
- orphan_mutex.lock();
-#if ORPHAN_DEBUG
- printf("orphaning VBO %u\n", buffer_id);
-#endif
- orphaned_buffer_ids.emplace_back(buffer_id);
- orphan_mutex.unlock();
- }
- }
diff --git a/intern/gawain/src/gwn_element.c b/intern/gawain/src/gwn_element.c
deleted file mode 100644
index 257338fe089..00000000000
--- a/intern/gawain/src/gwn_element.c
+++ /dev/null
@@ -1,304 +0,0 @@
-
-// Gawain element list (AKA index buffer)
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_element.h"
-#include "gwn_buffer_id.h"
-#include <stdlib.h>
-
-#define KEEP_SINGLE_COPY 1
-
-static GLenum convert_index_type_to_gl(Gwn_IndexBufType type)
- {
- static const GLenum table[] = {
- [GWN_INDEX_U8] = GL_UNSIGNED_BYTE, // GL has this, Vulkan does not
- [GWN_INDEX_U16] = GL_UNSIGNED_SHORT,
- [GWN_INDEX_U32] = GL_UNSIGNED_INT
- };
- return table[type];
- }
-
-unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf* elem)
- {
-#if GWN_TRACK_INDEX_RANGE
- static const unsigned table[] = {
- [GWN_INDEX_U8] = sizeof(GLubyte), // GL has this, Vulkan does not
- [GWN_INDEX_U16] = sizeof(GLushort),
- [GWN_INDEX_U32] = sizeof(GLuint)
- };
- return elem->index_len * table[elem->index_type];
-#else
- return elem->index_len * sizeof(GLuint);
-#endif
- }
-
-void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned index_len, unsigned vertex_len, bool use_prim_restart)
- {
- builder->use_prim_restart = use_prim_restart;
- builder->max_allowed_index = vertex_len - 1;
- builder->max_index_len = index_len;
- builder->index_len = 0; // start empty
- builder->prim_type = prim_type;
- builder->data = calloc(builder->max_index_len, sizeof(unsigned));
- }
-
-void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned prim_len, unsigned vertex_len)
- {
- unsigned verts_per_prim = 0;
- switch (prim_type)
- {
- case GWN_PRIM_POINTS:
- verts_per_prim = 1;
- break;
- case GWN_PRIM_LINES:
- verts_per_prim = 2;
- break;
- case GWN_PRIM_TRIS:
- verts_per_prim = 3;
- break;
- case GWN_PRIM_LINES_ADJ:
- verts_per_prim = 4;
- break;
- default:
-#if TRUST_NO_ONE
- assert(false);
-#endif
- return;
- }
-
- GWN_indexbuf_init_ex(builder, prim_type, prim_len * verts_per_prim, vertex_len, false);
- }
-
-void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder* builder, unsigned v)
- {
-#if TRUST_NO_ONE
- assert(builder->data != NULL);
- assert(builder->index_len < builder->max_index_len);
- assert(v <= builder->max_allowed_index);
-#endif
-
- builder->data[builder->index_len++] = v;
- }
-
-void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder* builder)
- {
-#if TRUST_NO_ONE
- assert(builder->data != NULL);
- assert(builder->index_len < builder->max_index_len);
- assert(builder->use_prim_restart);
-#endif
-
- builder->data[builder->index_len++] = GWN_PRIM_RESTART;
- }
-
-void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder* builder, unsigned v)
- {
-#if TRUST_NO_ONE
- assert(builder->prim_type == GWN_PRIM_POINTS);
-#endif
-
- GWN_indexbuf_add_generic_vert(builder, v);
- }
-
-void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2)
- {
-#if TRUST_NO_ONE
- assert(builder->prim_type == GWN_PRIM_LINES);
- assert(v1 != v2);
-#endif
-
- GWN_indexbuf_add_generic_vert(builder, v1);
- GWN_indexbuf_add_generic_vert(builder, v2);
- }
-
-void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2, unsigned v3)
- {
-#if TRUST_NO_ONE
- assert(builder->prim_type == GWN_PRIM_TRIS);
- assert(v1 != v2 && v2 != v3 && v3 != v1);
-#endif
-
- GWN_indexbuf_add_generic_vert(builder, v1);
- GWN_indexbuf_add_generic_vert(builder, v2);
- GWN_indexbuf_add_generic_vert(builder, v3);
- }
-
-void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2, unsigned v3, unsigned v4)
- {
-#if TRUST_NO_ONE
- assert(builder->prim_type == GWN_PRIM_LINES_ADJ);
- assert(v2 != v3); /* only the line need diff indices */
-#endif
-
- GWN_indexbuf_add_generic_vert(builder, v1);
- GWN_indexbuf_add_generic_vert(builder, v2);
- GWN_indexbuf_add_generic_vert(builder, v3);
- GWN_indexbuf_add_generic_vert(builder, v4);
- }
-
-#if GWN_TRACK_INDEX_RANGE
-// Everything remains 32 bit while building to keep things simple.
-// Find min/max after, then convert to smallest index type possible.
-
-static unsigned index_range(const unsigned values[], unsigned value_len, unsigned* min_out, unsigned* max_out)
- {
- if (value_len == 0)
- {
- *min_out = 0;
- *max_out = 0;
- return 0;
- }
- unsigned min_value = values[0];
- unsigned max_value = values[0];
- for (unsigned i = 1; i < value_len; ++i)
- {
- const unsigned value = values[i];
- if (value == GWN_PRIM_RESTART)
- continue;
- else if (value < min_value)
- min_value = value;
- else if (value > max_value)
- max_value = value;
- }
- *min_out = min_value;
- *max_out = max_value;
- return max_value - min_value;
- }
-
-static void squeeze_indices_byte(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem)
- {
- const unsigned *values = builder->data;
- const unsigned index_len = elem->index_len;
-
- // data will never be *larger* than builder->data...
- // converting in place to avoid extra allocation
- GLubyte *data = (GLubyte *)builder->data;
-
- if (elem->max_index > 0xFF)
- {
- const unsigned base = elem->min_index;
-
- elem->base_index = base;
- elem->min_index = 0;
- elem->max_index -= base;
-
- for (unsigned i = 0; i < index_len; ++i)
- data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base);
- }
- else
- {
- elem->base_index = 0;
-
- for (unsigned i = 0; i < index_len; ++i)
- data[i] = (GLubyte)(values[i]);
- }
- }
-
-static void squeeze_indices_short(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem)
- {
- const unsigned *values = builder->data;
- const unsigned index_len = elem->index_len;
-
- // data will never be *larger* than builder->data...
- // converting in place to avoid extra allocation
- GLushort *data = (GLushort *)builder->data;
-
- if (elem->max_index > 0xFFFF)
- {
- const unsigned base = elem->min_index;
-
- elem->base_index = base;
- elem->min_index = 0;
- elem->max_index -= base;
-
- for (unsigned i = 0; i < index_len; ++i)
- data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base);
- }
- else
- {
- elem->base_index = 0;
-
- for (unsigned i = 0; i < index_len; ++i)
- data[i] = (GLushort)(values[i]);
- }
- }
-
-#endif // GWN_TRACK_INDEX_RANGE
-
-Gwn_IndexBuf* GWN_indexbuf_build(Gwn_IndexBufBuilder* builder)
- {
- Gwn_IndexBuf* elem = calloc(1, sizeof(Gwn_IndexBuf));
- GWN_indexbuf_build_in_place(builder, elem);
- return elem;
- }
-
-void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder* builder, Gwn_IndexBuf* elem)
- {
-#if TRUST_NO_ONE
- assert(builder->data != NULL);
-#endif
-
- elem->index_len = builder->index_len;
- elem->use_prim_restart = builder->use_prim_restart;
-
-#if GWN_TRACK_INDEX_RANGE
- unsigned range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index);
-
- // count the primitive restart index.
- if (elem->use_prim_restart)
- range += 1;
-
- if (range <= 0xFF)
- {
- elem->index_type = GWN_INDEX_U8;
- squeeze_indices_byte(builder, elem);
- }
- else if (range <= 0xFFFF)
- {
- elem->index_type = GWN_INDEX_U16;
- squeeze_indices_short(builder, elem);
- }
- else
- {
- elem->index_type = GWN_INDEX_U32;
- elem->base_index = 0;
- }
-
- elem->gl_index_type = convert_index_type_to_gl(elem->index_type);
-#endif
-
- if (elem->vbo_id == 0)
- elem->vbo_id = GWN_buf_id_alloc();
-
- // send data to GPU
- // GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound,
- // so we use the GL_ARRAY_BUFFER here to create a buffer without
- // interfering in the VAO state.
- glBindBuffer(GL_ARRAY_BUFFER, elem->vbo_id);
- glBufferData(GL_ARRAY_BUFFER, GWN_indexbuf_size_get(elem), builder->data, GL_STATIC_DRAW);
-
- // discard builder (one-time use)
- free(builder->data);
- builder->data = NULL;
- // other fields are safe to leave
- }
-
-void GWN_indexbuf_use(Gwn_IndexBuf* elem)
- {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id);
- }
-
-void GWN_indexbuf_discard(Gwn_IndexBuf* elem)
- {
- if (elem->vbo_id)
- GWN_buf_id_free(elem->vbo_id);
-
- free(elem);
- }
diff --git a/intern/gawain/src/gwn_imm_util.c b/intern/gawain/src/gwn_imm_util.c
deleted file mode 100644
index a8d2b05c8a3..00000000000
--- a/intern/gawain/src/gwn_imm_util.c
+++ /dev/null
@@ -1,80 +0,0 @@
-
-// Gawain immediate mode drawing utilities
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_imm_util.h"
-#include "gwn_immediate.h"
-
-
-void immRectf(unsigned pos, float x1, float y1, float x2, float y2)
- {
- immBegin(GWN_PRIM_TRI_FAN, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y1);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x1, y2);
- immEnd();
- }
-
-void immRecti(unsigned pos, int x1, int y1, int x2, int y2)
- {
- immBegin(GWN_PRIM_TRI_FAN, 4);
- immVertex2i(pos, x1, y1);
- immVertex2i(pos, x2, y1);
- immVertex2i(pos, x2, y2);
- immVertex2i(pos, x1, y2);
- immEnd();
- }
-
-void immRectf_fast_with_color(unsigned pos, unsigned col, float x1, float y1, float x2, float y2, const float color[4])
- {
- immAttrib4fv(col, color);
- immVertex2f(pos, x1, y1);
- immAttrib4fv(col, color);
- immVertex2f(pos, x2, y1);
- immAttrib4fv(col, color);
- immVertex2f(pos, x2, y2);
-
- immAttrib4fv(col, color);
- immVertex2f(pos, x1, y1);
- immAttrib4fv(col, color);
- immVertex2f(pos, x2, y2);
- immAttrib4fv(col, color);
- immVertex2f(pos, x1, y2);
- }
-
-void immRecti_fast_with_color(unsigned pos, unsigned col, int x1, int y1, int x2, int y2, const float color[4])
- {
- immAttrib4fv(col, color);
- immVertex2i(pos, x1, y1);
- immAttrib4fv(col, color);
- immVertex2i(pos, x2, y1);
- immAttrib4fv(col, color);
- immVertex2i(pos, x2, y2);
-
- immAttrib4fv(col, color);
- immVertex2i(pos, x1, y1);
- immAttrib4fv(col, color);
- immVertex2i(pos, x2, y2);
- immAttrib4fv(col, color);
- immVertex2i(pos, x1, y2);
- }
-
-#if 0 // more complete version in case we want that
-void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4])
- {
- Gwn_VertFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color);
- immRecti(pos, x1, y1, x2, y2);
- immUnbindProgram();
- }
-#endif
diff --git a/intern/gawain/src/gwn_immediate.c b/intern/gawain/src/gwn_immediate.c
deleted file mode 100644
index d43e52cc525..00000000000
--- a/intern/gawain/src/gwn_immediate.c
+++ /dev/null
@@ -1,923 +0,0 @@
-
-// Gawain immediate mode work-alike
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_immediate.h"
-#include "gwn_buffer_id.h"
-#include "gwn_attr_binding.h"
-#include "gwn_attr_binding_private.h"
-#include "gwn_vertex_format_private.h"
-#include "gwn_vertex_array_id.h"
-#include "gwn_primitive_private.h"
-#include <string.h>
-
-// necessary functions from matrix API
-extern void gpuBindMatrices(const Gwn_ShaderInterface*);
-extern bool gpuMatricesDirty(void);
-
-typedef struct {
- // TODO: organize this struct by frequency of change (run-time)
-
-#if IMM_BATCH_COMBO
- Gwn_Batch* batch;
-#endif
- Gwn_Context* context;
-
- // current draw call
- GLubyte* buffer_data;
- unsigned buffer_offset;
- unsigned buffer_bytes_mapped;
- unsigned vertex_len;
- bool strict_vertex_len;
- Gwn_PrimType prim_type;
-
- Gwn_VertFormat vertex_format;
-
- // current vertex
- unsigned vertex_idx;
- GLubyte* vertex_data;
- uint16_t unassigned_attrib_bits; // which attributes of current vertex have not been given values?
-
- GLuint vbo_id;
- GLuint vao_id;
-
- GLuint bound_program;
- const Gwn_ShaderInterface* shader_interface;
- Gwn_AttrBinding attrib_binding;
- uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok
-} Immediate;
-
-// size of internal buffer -- make this adjustable?
-#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
-
-static bool initialized = false;
-static Immediate imm;
-
-void immInit(void)
- {
-#if TRUST_NO_ONE
- assert(!initialized);
-#endif
-
- memset(&imm, 0, sizeof(Immediate));
-
- imm.vbo_id = GWN_buf_id_alloc();
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-
- imm.prim_type = GWN_PRIM_NONE;
- imm.strict_vertex_len = true;
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- initialized = true;
- }
-
-void immActivate(void)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair
- assert(imm.vao_id == 0);
-#endif
- imm.vao_id = GWN_vao_alloc();
- imm.context = GWN_context_active_get();
- }
-
-void immDeactivate(void)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair
- assert(imm.vao_id != 0);
-#endif
- GWN_vao_free(imm.vao_id, imm.context);
- imm.vao_id = 0;
- imm.prev_enabled_attrib_bits = 0;
- }
-
-void immDestroy(void)
- {
- GWN_buf_id_free(imm.vbo_id);
- initialized = false;
- }
-
-Gwn_VertFormat* immVertexFormat(void)
- {
- GWN_vertformat_clear(&imm.vertex_format);
- return &imm.vertex_format;
- }
-
-void immBindProgram(GLuint program, const Gwn_ShaderInterface* shaderface)
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program == 0);
- assert(glIsProgram(program));
-#endif
-
- imm.bound_program = program;
- imm.shader_interface = shaderface;
-
- if (!imm.vertex_format.packed)
- VertexFormat_pack(&imm.vertex_format);
-
- glUseProgram(program);
- get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, shaderface);
- gpuBindMatrices(shaderface);
- }
-
-void immUnbindProgram(void)
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program != 0);
-#endif
-#if PROGRAM_NO_OPTI
- glUseProgram(0);
-#endif
- imm.bound_program = 0;
- }
-
-#if TRUST_NO_ONE
-static bool vertex_count_makes_sense_for_primitive(unsigned vertex_len, Gwn_PrimType prim_type)
- {
- // does vertex_len make sense for this primitive type?
- if (vertex_len == 0)
- return false;
-
- switch (prim_type)
- {
- case GWN_PRIM_POINTS:
- return true;
- case GWN_PRIM_LINES:
- return vertex_len % 2 == 0;
- case GWN_PRIM_LINE_STRIP:
- case GWN_PRIM_LINE_LOOP:
- return vertex_len >= 2;
- case GWN_PRIM_LINE_STRIP_ADJ:
- return vertex_len >= 4;
- case GWN_PRIM_TRIS:
- return vertex_len % 3 == 0;
- case GWN_PRIM_TRI_STRIP:
- case GWN_PRIM_TRI_FAN:
- return vertex_len >= 3;
- default:
- return false;
- }
- }
-#endif
-
-void immBegin(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun
- assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
-#endif
-
- imm.prim_type = prim_type;
- imm.vertex_len = vertex_len;
- imm.vertex_idx = 0;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
-
- // how many bytes do we need for this draw call?
- const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len);
-
-#if TRUST_NO_ONE
- assert(bytes_needed <= IMM_BUFFER_SIZE);
-#endif
-
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
-
- // does the current buffer have enough room?
- const unsigned available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset;
- // ensure vertex data is aligned
- const unsigned pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); // might waste a little space, but it's safe
- if ((bytes_needed + pre_padding) <= available_bytes)
- imm.buffer_offset += pre_padding;
- else
- {
- // orphan this buffer & start with a fresh one
-#if 1
- // this method works on all platforms, old & new
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-#else
- // TODO: use other (more recent) methods after thorough testing
- if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata)
- glInvalidateBufferData(imm.vbo_id);
- else
- {
- // glitches!
-// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT);
-
- // works
-// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE,
-// GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
-// glUnmapBuffer(GL_ARRAY_BUFFER);
-
- // also works
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
- }
-#endif
-
- imm.buffer_offset = 0;
- }
-
-// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1);
-
- imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed,
- GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
-
-#if TRUST_NO_ONE
- assert(imm.buffer_data != NULL);
-#endif
-
- imm.buffer_bytes_mapped = bytes_needed;
- imm.vertex_data = imm.buffer_data;
- }
-
-void immBeginAtMost(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(vertex_len > 0);
-#endif
-
- imm.strict_vertex_len = false;
- immBegin(prim_type, vertex_len);
- }
-
-#if IMM_BATCH_COMBO
-
-Gwn_Batch* immBeginBatch(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun
- assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
-#endif
-
- imm.prim_type = prim_type;
- imm.vertex_len = vertex_len;
- imm.vertex_idx = 0;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
-
- Gwn_VertBuf* verts = GWN_vertbuf_create_with_format(&imm.vertex_format);
- GWN_vertbuf_data_alloc(verts, vertex_len);
-
- imm.buffer_bytes_mapped = GWN_vertbuf_size_get(verts);
- imm.vertex_data = verts->data;
-
- imm.batch = GWN_batch_create_ex(prim_type, verts, NULL, GWN_BATCH_OWNS_VBO);
- imm.batch->phase = GWN_BATCH_BUILDING;
-
- return imm.batch;
- }
-
-Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType prim_type, unsigned vertex_len)
- {
- imm.strict_vertex_len = false;
- return immBeginBatch(prim_type, vertex_len);
- }
-
-#endif // IMM_BATCH_COMBO
-
-static void immDrawSetup(void)
- {
- // set up VAO -- can be done during Begin or End really
- glBindVertexArray(imm.vao_id);
-
- // enable/disable vertex attribs as needed
- if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits)
- {
- for (unsigned loc = 0; loc < GWN_VERT_ATTR_MAX_LEN; ++loc)
- {
- bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc);
- bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc);
-
- if (is_enabled && !was_enabled)
- {
-// printf("enabling attrib %u\n", loc);
- glEnableVertexAttribArray(loc);
- }
- else if (was_enabled && !is_enabled)
- {
-// printf("disabling attrib %u\n", loc);
- glDisableVertexAttribArray(loc);
- }
- }
-
- imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits;
- }
-
- const unsigned stride = imm.vertex_format.stride;
-
- for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx)
- {
- const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx;
-
- const unsigned offset = imm.buffer_offset + a->offset;
- const GLvoid* pointer = (const GLubyte*)0 + offset;
-
- const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx);
-
-// printf("specifying attrib %u '%s' with offset %u, stride %u\n", loc, a->name, offset, stride);
-
- switch (a->fetch_mode)
- {
- case GWN_FETCH_FLOAT:
- case GWN_FETCH_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer);
- break;
- case GWN_FETCH_INT_TO_FLOAT_UNIT:
- glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer);
- break;
- case GWN_FETCH_INT:
- glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer);
- }
- }
-
- if (gpuMatricesDirty())
- gpuBindMatrices(imm.shader_interface);
- }
-
-void immEnd(void)
- {
-#if TRUST_NO_ONE
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- unsigned buffer_bytes_used;
- if (imm.strict_vertex_len)
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx == imm.vertex_len); // with all vertices defined
-#endif
- buffer_bytes_used = imm.buffer_bytes_mapped;
- }
- else
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx <= imm.vertex_len);
-#endif
- // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_len);
- if (imm.vertex_idx == imm.vertex_len)
- {
- buffer_bytes_used = imm.buffer_bytes_mapped;
- }
- else
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type));
-#endif
- imm.vertex_len = imm.vertex_idx;
- buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len);
- // unused buffer bytes are available to the next immBegin
- // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
- }
-
- // tell OpenGL what range was modified so it doesn't copy the whole mapped range
- // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
- glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used);
- }
-
-#if IMM_BATCH_COMBO
- if (imm.batch)
- {
- if (buffer_bytes_used != imm.buffer_bytes_mapped)
- {
- GWN_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len);
- // TODO: resize only if vertex count is much smaller
- }
-
- GWN_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface);
- imm.batch->phase = GWN_BATCH_READY_TO_DRAW;
- imm.batch = NULL; // don't free, batch belongs to caller
- }
- else
-#endif
- {
- glUnmapBuffer(GL_ARRAY_BUFFER);
-
- if (imm.vertex_len > 0)
- {
- immDrawSetup();
- glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
-
- // prep for next immBegin
- imm.buffer_offset += buffer_bytes_used;
- }
-
- // prep for next immBegin
- imm.prim_type = GWN_PRIM_NONE;
- imm.strict_vertex_len = true;
- }
-
-static void setAttribValueBit(unsigned attrib_id)
- {
- uint16_t mask = 1 << attrib_id;
-
-#if TRUST_NO_ONE
- assert(imm.unassigned_attrib_bits & mask); // not already set
-#endif
-
- imm.unassigned_attrib_bits &= ~mask;
- }
-
-
-// --- generic attribute functions ---
-
-void immAttrib1f(unsigned attrib_id, float x)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 1);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- }
-
-void immAttrib2f(unsigned attrib_id, float x, float y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib3f(unsigned attrib_id, float x, float y, float z)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 3);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- data[2] = z;
- }
-
-void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 4);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- data[2] = z;
- data[3] = w;
- }
-
-void immAttrib1u(unsigned attrib_id, unsigned x)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U32);
- assert(attrib->comp_len == 1);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- unsigned* data = (unsigned*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- }
-
-void immAttrib2i(unsigned attrib_id, int x, int y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_I32);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- int* data = (int*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib2s(unsigned attrib_id, short x, short y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_I16);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- short* data = (short*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib2fv(unsigned attrib_id, const float data[2])
- {
- immAttrib2f(attrib_id, data[0], data[1]);
- }
-
-void immAttrib3fv(unsigned attrib_id, const float data[3])
- {
- immAttrib3f(attrib_id, data[0], data[1], data[2]);
- }
-
-void immAttrib4fv(unsigned attrib_id, const float data[4])
- {
- immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]);
- }
-
-void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U8);
- assert(attrib->comp_len == 3);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- GLubyte* data = imm.vertex_data + attrib->offset;
-// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
-
- data[0] = r;
- data[1] = g;
- data[2] = b;
- }
-
-void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U8);
- assert(attrib->comp_len == 4);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- GLubyte* data = imm.vertex_data + attrib->offset;
-// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
-
- data[0] = r;
- data[1] = g;
- data[2] = b;
- data[3] = a;
- }
-
-void immAttrib3ubv(unsigned attrib_id, const unsigned char data[3])
- {
- immAttrib3ub(attrib_id, data[0], data[1], data[2]);
- }
-
-void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4])
- {
- immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]);
- }
-
-void immSkipAttrib(unsigned attrib_id)
- {
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
- }
-
-static void immEndVertex(void) // and move on to the next vertex
- {
-#if TRUST_NO_ONE
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
- assert(imm.vertex_idx < imm.vertex_len);
-#endif
-
- // have all attribs been assigned values?
- // if not, copy value from previous vertex
- if (imm.unassigned_attrib_bits)
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx > 0); // first vertex must have all attribs specified
-#endif
-
- for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx)
- {
- if ((imm.unassigned_attrib_bits >> a_idx) & 1)
- {
- const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx;
-
-// printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx);
-
- GLubyte* data = imm.vertex_data + a->offset;
- memcpy(data, data - imm.vertex_format.stride, a->sz);
- // TODO: consolidate copy of adjacent attributes
- }
- }
- }
-
- imm.vertex_idx++;
- imm.vertex_data += imm.vertex_format.stride;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
- }
-
-void immVertex2f(unsigned attrib_id, float x, float y)
- {
- immAttrib2f(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex3f(unsigned attrib_id, float x, float y, float z)
- {
- immAttrib3f(attrib_id, x, y, z);
- immEndVertex();
- }
-
-void immVertex4f(unsigned attrib_id, float x, float y, float z, float w)
- {
- immAttrib4f(attrib_id, x, y, z, w);
- immEndVertex();
- }
-
-void immVertex2i(unsigned attrib_id, int x, int y)
- {
- immAttrib2i(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex2s(unsigned attrib_id, short x, short y)
- {
- immAttrib2s(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex2fv(unsigned attrib_id, const float data[2])
- {
- immAttrib2f(attrib_id, data[0], data[1]);
- immEndVertex();
- }
-
-void immVertex3fv(unsigned attrib_id, const float data[3])
- {
- immAttrib3f(attrib_id, data[0], data[1], data[2]);
- immEndVertex();
- }
-
-void immVertex2iv(unsigned attrib_id, const int data[2])
- {
- immAttrib2i(attrib_id, data[0], data[1]);
- immEndVertex();
- }
-
-
-// --- generic uniform functions ---
-
-#if 0
- #if TRUST_NO_ONE
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); assert(uniform);
- #else
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name);
- #endif
-#else
- // NOTE: It is possible to have uniform fully optimized out from the shader.
- // In this case we can't assert failure or allow NULL-pointer dereference.
- // TODO(sergey): How can we detect existing-but-optimized-out uniform but still
- // catch typos in uniform names passed to immUniform*() functions?
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); if (uniform == NULL) return;
-#endif
-
-void immUniform1f(const char* name, float x)
- {
- GET_UNIFORM
- glUniform1f(uniform->location, x);
- }
-
-void immUniform2f(const char* name, float x, float y)
- {
- GET_UNIFORM
- glUniform2f(uniform->location, x, y);
- }
-
-void immUniform2fv(const char* name, const float data[2])
- {
- GET_UNIFORM
- glUniform2fv(uniform->location, 1, data);
- }
-
-void immUniform3f(const char* name, float x, float y, float z)
- {
- GET_UNIFORM
- glUniform3f(uniform->location, x, y, z);
- }
-
-void immUniform3fv(const char* name, const float data[3])
- {
- GET_UNIFORM
- glUniform3fv(uniform->location, 1, data);
- }
-
-// can increase this limit or move to another file
-#define MAX_UNIFORM_NAME_LEN 60
-
-void immUniformArray3fv(const char* bare_name, const float *data, int count)
- {
- // look up "name[0]" when given "name"
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
- GET_UNIFORM
- glUniform3fv(uniform->location, count, data);
- }
-
-void immUniform4f(const char* name, float x, float y, float z, float w)
- {
- GET_UNIFORM
- glUniform4f(uniform->location, x, y, z, w);
- }
-
-void immUniform4fv(const char* name, const float data[4])
- {
- GET_UNIFORM
- glUniform4fv(uniform->location, 1, data);
- }
-
-void immUniformArray4fv(const char* bare_name, const float *data, int count)
- {
- // look up "name[0]" when given "name"
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
- GET_UNIFORM
- glUniform4fv(uniform->location, count, data);
- }
-
-void immUniformMatrix4fv(const char* name, const float data[4][4])
- {
- GET_UNIFORM
- glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data);
- }
-
-void immUniform1i(const char* name, int x)
- {
- GET_UNIFORM
- glUniform1i(uniform->location, x);
- }
-
-void immUniform4iv(const char* name, const int data[4])
- {
- GET_UNIFORM
- glUniform4iv(uniform->location, 1, data);
- }
-
-// --- convenience functions for setting "uniform vec4 color" ---
-
-void immUniformColor4f(float r, float g, float b, float a)
- {
- const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform_builtin(imm.shader_interface, GWN_UNIFORM_COLOR);
-
-#if TRUST_NO_ONE
- assert(uniform != NULL);
-#endif
-
- glUniform4f(uniform->location, r, g, b, a);
- }
-
-void immUniformColor4fv(const float rgba[4])
- {
- immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
-
-void immUniformColor3f(float r, float g, float b)
- {
- immUniformColor4f(r, g, b, 1.0f);
- }
-
-void immUniformColor3fv(const float rgb[3])
- {
- immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f);
- }
-
-void immUniformColor3fvAlpha(const float rgb[3], float a)
- {
- immUniformColor4f(rgb[0], rgb[1], rgb[2], a);
- }
-
-// TODO: v-- treat as sRGB? --v
-
-void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
- {
- const float scale = 1.0f / 255.0f;
- immUniformColor4f(scale * r, scale * g, scale * b, 1.0f);
- }
-
-void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
- {
- const float scale = 1.0f / 255.0f;
- immUniformColor4f(scale * r, scale * g, scale * b, scale * a);
- }
-
-void immUniformColor3ubv(const unsigned char rgb[3])
- {
- immUniformColor3ub(rgb[0], rgb[1], rgb[2]);
- }
-
-void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char alpha)
- {
- immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha);
- }
-
-void immUniformColor4ubv(const unsigned char rgba[4])
- {
- immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
diff --git a/intern/gawain/src/gwn_primitive.c b/intern/gawain/src/gwn_primitive.c
deleted file mode 100644
index c2638bcc8c8..00000000000
--- a/intern/gawain/src/gwn_primitive.c
+++ /dev/null
@@ -1,67 +0,0 @@
-
-// 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 "gwn_primitive.h"
-#include "gwn_primitive_private.h"
-
-Gwn_PrimClass GWN_primtype_class(Gwn_PrimType prim_type)
- {
- static const Gwn_PrimClass classes[] =
- {
- [GWN_PRIM_POINTS] = GWN_PRIM_CLASS_POINT,
- [GWN_PRIM_LINES] = GWN_PRIM_CLASS_LINE,
- [GWN_PRIM_LINE_STRIP] = GWN_PRIM_CLASS_LINE,
- [GWN_PRIM_LINE_LOOP] = GWN_PRIM_CLASS_LINE,
- [GWN_PRIM_TRIS] = GWN_PRIM_CLASS_SURFACE,
- [GWN_PRIM_TRI_STRIP] = GWN_PRIM_CLASS_SURFACE,
- [GWN_PRIM_TRI_FAN] = GWN_PRIM_CLASS_SURFACE,
-
- [GWN_PRIM_LINES_ADJ] = GWN_PRIM_CLASS_LINE,
- [GWN_PRIM_LINE_STRIP_ADJ] = GWN_PRIM_CLASS_LINE,
- [GWN_PRIM_TRIS_ADJ] = GWN_PRIM_CLASS_SURFACE,
-
- [GWN_PRIM_NONE] = GWN_PRIM_CLASS_NONE
- };
-
- return classes[prim_type];
- }
-
-bool GWN_primtype_belongs_to_class(Gwn_PrimType prim_type, Gwn_PrimClass prim_class)
- {
- if (prim_class == GWN_PRIM_CLASS_NONE && prim_type == GWN_PRIM_NONE)
- return true;
-
- return prim_class & GWN_primtype_class(prim_type);
- }
-
-GLenum convert_prim_type_to_gl(Gwn_PrimType prim_type)
- {
-#if TRUST_NO_ONE
- assert(prim_type != GWN_PRIM_NONE);
-#endif
-
- static const GLenum table[] =
- {
- [GWN_PRIM_POINTS] = GL_POINTS,
- [GWN_PRIM_LINES] = GL_LINES,
- [GWN_PRIM_LINE_STRIP] = GL_LINE_STRIP,
- [GWN_PRIM_LINE_LOOP] = GL_LINE_LOOP,
- [GWN_PRIM_TRIS] = GL_TRIANGLES,
- [GWN_PRIM_TRI_STRIP] = GL_TRIANGLE_STRIP,
- [GWN_PRIM_TRI_FAN] = GL_TRIANGLE_FAN,
-
- [GWN_PRIM_LINES_ADJ] = GL_LINES_ADJACENCY,
- [GWN_PRIM_LINE_STRIP_ADJ] = GL_LINE_STRIP_ADJACENCY,
- [GWN_PRIM_TRIS_ADJ] = GL_TRIANGLES_ADJACENCY,
- };
-
- return table[prim_type];
- }
diff --git a/intern/gawain/src/gwn_shader_interface.c b/intern/gawain/src/gwn_shader_interface.c
deleted file mode 100644
index d18af234fb0..00000000000
--- a/intern/gawain/src/gwn_shader_interface.c
+++ /dev/null
@@ -1,362 +0,0 @@
-
-// 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 "gwn_batch_private.h"
-#include "gwn_shader_interface.h"
-#include "gwn_vertex_array_id.h"
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-
-#define DEBUG_SHADER_INTERFACE 0
-
-#if DEBUG_SHADER_INTERFACE
- #include <stdio.h>
-#endif
-
-static const char* BuiltinUniform_name(Gwn_UniformBuiltin u)
- {
- static const char* names[] =
- {
- [GWN_UNIFORM_NONE] = NULL,
-
- [GWN_UNIFORM_MODEL] = "ModelMatrix",
- [GWN_UNIFORM_VIEW] = "ViewMatrix",
- [GWN_UNIFORM_MODELVIEW] = "ModelViewMatrix",
- [GWN_UNIFORM_PROJECTION] = "ProjectionMatrix",
- [GWN_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix",
- [GWN_UNIFORM_MVP] = "ModelViewProjectionMatrix",
-
- [GWN_UNIFORM_MODEL_INV] = "ModelMatrixInverse",
- [GWN_UNIFORM_VIEW_INV] = "ViewMatrixInverse",
- [GWN_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse",
- [GWN_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse",
- [GWN_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse",
-
- [GWN_UNIFORM_NORMAL] = "NormalMatrix",
- [GWN_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix",
- [GWN_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors",
- [GWN_UNIFORM_ORCO] = "OrcoTexCoFactors",
-
- [GWN_UNIFORM_COLOR] = "color",
- [GWN_UNIFORM_EYE] = "eye",
- [GWN_UNIFORM_CALLID] = "callId",
-
- [GWN_UNIFORM_CUSTOM] = NULL,
- [GWN_NUM_UNIFORMS] = NULL,
- };
-
- return names[u];
- }
-
-GWN_INLINE bool match(const char* a, const char* b)
- {
- return strcmp(a, b) == 0;
- }
-
-GWN_INLINE unsigned hash_string(const char *str)
- {
- unsigned i = 0, c;
-
- while ((c = *str++))
- {
- i = i * 37 + c;
- }
-
- return i;
- }
-
-GWN_INLINE void set_input_name(Gwn_ShaderInterface* shaderface, Gwn_ShaderInput* input,
- const char* name, uint32_t name_len)
- {
- input->name_offset = shaderface->name_buffer_offset;
- input->name_hash = hash_string(name);
- shaderface->name_buffer_offset += name_len + 1; // include NULL terminator
- }
-
-GWN_INLINE void shader_input_to_bucket(Gwn_ShaderInput* input,
- Gwn_ShaderInput* buckets[GWN_NUM_SHADERINTERFACE_BUCKETS])
- {
- const unsigned bucket_index = input->name_hash % GWN_NUM_SHADERINTERFACE_BUCKETS;
- input->next = buckets[bucket_index];
- buckets[bucket_index] = input;
- }
-
-GWN_INLINE const Gwn_ShaderInput* buckets_lookup(Gwn_ShaderInput* const buckets[GWN_NUM_SHADERINTERFACE_BUCKETS],
- const char *name_buffer, const char *name)
- {
- const unsigned name_hash = hash_string(name);
- const unsigned bucket_index = name_hash % GWN_NUM_SHADERINTERFACE_BUCKETS;
- const Gwn_ShaderInput* input = buckets[bucket_index];
- if (input == NULL)
- {
- // Requested uniform is not found at all.
- return NULL;
- }
- // Optimization bit: if there is no hash collision detected when constructing shader interface
- // it means we can only request the single possible uniform. Surely, it's possible we request
- // uniform which causes hash collision, but that will be detected in debug builds.
- if (input->next == NULL)
- {
- if (name_hash == input->name_hash)
- {
-#if TRUST_NO_ONE
- assert(match(name_buffer + input->name_offset, name));
-#endif
- return input;
- }
- return NULL;
- }
- // Work through possible collisions.
- const Gwn_ShaderInput* next = input;
- while (next != NULL)
- {
- input = next;
- next = input->next;
-
- if (input->name_hash != name_hash)
- {
- continue;
- }
- if (match(name_buffer + input->name_offset, name))
- {
- return input;
- }
- }
- return NULL; // not found
- }
-
-GWN_INLINE void buckets_free(Gwn_ShaderInput* buckets[GWN_NUM_SHADERINTERFACE_BUCKETS])
- {
- for (unsigned bucket_index = 0; bucket_index < GWN_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index)
- {
- Gwn_ShaderInput *input = buckets[bucket_index];
- while (input != NULL)
- {
- Gwn_ShaderInput *input_next = input->next;
- free(input);
- input = input_next;
- }
- }
- }
-
-static bool setup_builtin_uniform(Gwn_ShaderInput* input, const char* name)
- {
- // TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types
-
- // detect built-in uniforms (name must match)
- for (Gwn_UniformBuiltin u = GWN_UNIFORM_NONE + 1; u < GWN_UNIFORM_CUSTOM; ++u)
- {
- const char* builtin_name = BuiltinUniform_name(u);
- if (match(name, builtin_name))
- {
- input->builtin_type = u;
- return true;
- }
- }
-
- input->builtin_type = GWN_UNIFORM_CUSTOM;
- return false;
- }
-
-static const Gwn_ShaderInput* add_uniform(Gwn_ShaderInterface* shaderface, const char* name)
- {
- Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput));
-
- input->location = glGetUniformLocation(shaderface->program, name);
-
- unsigned name_len = strlen(name);
- shaderface->name_buffer = realloc(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); // include NULL terminator
- char* name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
- strcpy(name_buffer, name);
-
- set_input_name(shaderface, input, name, name_len);
- setup_builtin_uniform(input, name);
-
- shader_input_to_bucket(input, shaderface->uniform_buckets);
- if (input->builtin_type != GWN_UNIFORM_NONE &&
- input->builtin_type != GWN_UNIFORM_CUSTOM)
- {
- shaderface->builtin_uniforms[input->builtin_type] = input;
- }
-#if DEBUG_SHADER_INTERFACE
- printf("Gwn_ShaderInterface %p, program %d, uniform[] '%s' at location %d\n", shaderface, shaderface->program, name, input->location);
-#endif
- return input;
- }
-
-Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program)
- {
- Gwn_ShaderInterface* shaderface = calloc(1, sizeof(Gwn_ShaderInterface));
- shaderface->program = program;
-
-#if DEBUG_SHADER_INTERFACE
- printf("%s {\n", __func__); // enter function
- printf("Gwn_ShaderInterface %p, program %d\n", shaderface, program);
-#endif
-
- GLint max_attrib_name_len, attr_len;
- glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len);
- glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len);
-
- GLint max_ubo_name_len, ubo_len;
- glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
- glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
-
- const uint32_t name_buffer_len = attr_len * max_attrib_name_len + ubo_len * max_ubo_name_len;
- shaderface->name_buffer = malloc(name_buffer_len);
-
- // Attributes
- for (uint32_t i = 0; i < attr_len; ++i)
- {
- Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput));
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char* name = shaderface->name_buffer + shaderface->name_buffer_offset;
- GLsizei name_len = 0;
-
- glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
-
- // remove "[0]" from array name
- if (name[name_len-1] == ']')
- {
- name[name_len-3] = '\0';
- name_len -= 3;
- }
-
- // TODO: reject DOUBLE gl_types
-
- input->location = glGetAttribLocation(program, name);
-
- set_input_name(shaderface, input, name, name_len);
-
- shader_input_to_bucket(input, shaderface->attrib_buckets);
-
-#if DEBUG_SHADER_INTERFACE
- printf("attrib[%u] '%s' at location %d\n", i, name, input->location);
-#endif
- }
-
- // Uniform Blocks
- for (uint32_t i = 0; i < ubo_len; ++i)
- {
- Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput));
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char* name = shaderface->name_buffer + shaderface->name_buffer_offset;
- GLsizei name_len = 0;
-
- glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
-
- input->location = i;
-
- set_input_name(shaderface, input, name, name_len);
-
- shader_input_to_bucket(input, shaderface->ubo_buckets);
-
-#if DEBUG_SHADER_INTERFACE
- printf("ubo '%s' at location %d\n", name, input->location);
-#endif
- }
-
- // Builtin Uniforms
- for (Gwn_UniformBuiltin u = GWN_UNIFORM_NONE + 1; u < GWN_UNIFORM_CUSTOM; ++u)
- {
- const char* builtin_name = BuiltinUniform_name(u);
- if (glGetUniformLocation(program, builtin_name) != -1)
- add_uniform((Gwn_ShaderInterface*)shaderface, builtin_name);
- }
-
- // Batches ref buffer
- shaderface->batches_len = GWN_SHADERINTERFACE_REF_ALLOC_COUNT;
- shaderface->batches = calloc(shaderface->batches_len, sizeof(Gwn_Batch*));
-
- return shaderface;
- }
-
-void GWN_shaderinterface_discard(Gwn_ShaderInterface* shaderface)
- {
- // Free memory used by buckets and has entries.
- buckets_free(shaderface->uniform_buckets);
- buckets_free(shaderface->attrib_buckets);
- buckets_free(shaderface->ubo_buckets);
- // Free memory used by name_buffer.
- free(shaderface->name_buffer);
- // Remove this interface from all linked Batches vao cache.
- for (int i = 0; i < shaderface->batches_len; ++i)
- if (shaderface->batches[i] != NULL)
- gwn_batch_remove_interface_ref(shaderface->batches[i], shaderface);
-
- free(shaderface->batches);
- // Free memory used by shader interface by its self.
- free(shaderface);
- }
-
-const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface* shaderface, const char* name)
- {
- // TODO: Warn if we find a matching builtin, since these can be looked up much quicker.
- const Gwn_ShaderInput* input = buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
-
- // If input is not found add it so it's found next time.
- if (input == NULL)
- input = add_uniform((Gwn_ShaderInterface*)shaderface, name);
-
- return (input->location != -1) ? input : NULL;
- }
-
-const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface* shaderface, Gwn_UniformBuiltin builtin)
- {
-#if TRUST_NO_ONE
- assert(builtin != GWN_UNIFORM_NONE);
- assert(builtin != GWN_UNIFORM_CUSTOM);
- assert(builtin != GWN_NUM_UNIFORMS);
-#endif
- return shaderface->builtin_uniforms[builtin];
- }
-
-const Gwn_ShaderInput* GWN_shaderinterface_ubo(const Gwn_ShaderInterface* shaderface, const char* name)
- {
- return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
- }
-
-const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface* shaderface, const char* name)
- {
- return buckets_lookup(shaderface->attrib_buckets, shaderface->name_buffer, name);
- }
-
-void GWN_shaderinterface_add_batch_ref(Gwn_ShaderInterface* shaderface, Gwn_Batch* batch)
- {
- int i; // find first unused slot
- for (i = 0; i < shaderface->batches_len; ++i)
- if (shaderface->batches[i] == NULL)
- break;
-
- if (i == shaderface->batches_len)
- {
- // Not enough place, realloc the array.
- i = shaderface->batches_len;
- shaderface->batches_len += GWN_SHADERINTERFACE_REF_ALLOC_COUNT;
- shaderface->batches = realloc(shaderface->batches, sizeof(Gwn_Batch*) * shaderface->batches_len);
- memset(shaderface->batches + i, 0, sizeof(Gwn_Batch*) * GWN_SHADERINTERFACE_REF_ALLOC_COUNT);
- }
-
- shaderface->batches[i] = batch;
- }
-
-void GWN_shaderinterface_remove_batch_ref(Gwn_ShaderInterface* shaderface, Gwn_Batch* batch)
- {
- for (int i = 0; i < shaderface->batches_len; ++i)
- {
- if (shaderface->batches[i] == batch)
- {
- shaderface->batches[i] = NULL;
- break; // cannot have duplicates
- }
- }
- }
diff --git a/intern/gawain/src/gwn_vertex_array_id.cpp b/intern/gawain/src/gwn_vertex_array_id.cpp
deleted file mode 100644
index 70294565e6a..00000000000
--- a/intern/gawain/src/gwn_vertex_array_id.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-
-// Gawain vertex array IDs
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 Mike Erwin, Clément Foucault
-//
-// 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 "buffer_id.h"
-
-#include "gwn_batch_private.h"
-#include "gwn_vertex_array_id.h"
-#include "gwn_context.h"
-#include <vector>
-#include <string.h>
-#include <pthread.h>
-#include <mutex>
-#include <unordered_set>
-
-#if TRUST_NO_ONE
-#if 0
-extern "C" {
-extern int BLI_thread_is_main(void); // Blender-specific function
-}
-
-static bool thread_is_main()
- {
- // "main" here means the GL context's thread
- return BLI_thread_is_main();
- }
-#endif
-#endif
-
-struct Gwn_Context {
- GLuint default_vao;
- std::unordered_set<Gwn_Batch*> batches; // Batches that have VAOs from this context
- std::vector<GLuint> orphaned_vertarray_ids;
- std::mutex orphans_mutex; // todo: try spinlock instead
-#if TRUST_NO_ONE
- pthread_t thread; // Thread on which this context is active.
- bool thread_is_used;
-
- Gwn_Context()
- {
- thread_is_used = false;
- }
-#endif
-};
-
-#if defined(_MSC_VER) && (_MSC_VER == 1800)
-#define thread_local __declspec(thread)
-thread_local Gwn_Context* active_ctx = NULL;
-#else
-static thread_local Gwn_Context* active_ctx = NULL;
-#endif
-
-static void clear_orphans(Gwn_Context* ctx)
- {
- ctx->orphans_mutex.lock();
- if (!ctx->orphaned_vertarray_ids.empty())
- {
- unsigned orphan_len = (unsigned)ctx->orphaned_vertarray_ids.size();
- glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data());
- ctx->orphaned_vertarray_ids.clear();
- }
- ctx->orphans_mutex.unlock();
- }
-
-Gwn_Context* GWN_context_create(void)
- {
-#if TRUST_NO_ONE
- // assert(thread_is_main());
-#endif
- Gwn_Context* ctx = new Gwn_Context;
- glGenVertexArrays(1, &ctx->default_vao);
- GWN_context_active_set(ctx);
- return ctx;
- }
-
-// to be called after GWN_context_active_set(ctx_to_destroy)
-void GWN_context_discard(Gwn_Context* ctx)
- {
-#if TRUST_NO_ONE
- // Make sure no other thread has locked it.
- assert(ctx == active_ctx);
- assert(pthread_equal(pthread_self(), ctx->thread));
- assert(ctx->orphaned_vertarray_ids.empty());
-#endif
- // delete remaining vaos
- while (!ctx->batches.empty())
- {
- // this removes the array entry
- gwn_batch_vao_cache_clear(*ctx->batches.begin());
- }
- glDeleteVertexArrays(1, &ctx->default_vao);
- delete ctx;
- active_ctx = NULL;
- }
-
-// ctx can be NULL
-void GWN_context_active_set(Gwn_Context* ctx)
- {
-#if TRUST_NO_ONE
- if (active_ctx)
- active_ctx->thread_is_used = false;
- // Make sure no other context is already bound to this thread.
- if (ctx)
- {
- // Make sure no other thread has locked it.
- assert(ctx->thread_is_used == false);
- ctx->thread = pthread_self();
- ctx->thread_is_used = true;
- }
-#endif
- if (ctx)
- clear_orphans(ctx);
- active_ctx = ctx;
- }
-
-Gwn_Context* GWN_context_active_get(void)
- {
- return active_ctx;
- }
-
-GLuint GWN_vao_default(void)
- {
-#if TRUST_NO_ONE
- assert(active_ctx); // need at least an active context
- assert(pthread_equal(pthread_self(), active_ctx->thread)); // context has been activated by another thread!
-#endif
- return active_ctx->default_vao;
- }
-
-GLuint GWN_vao_alloc(void)
- {
-#if TRUST_NO_ONE
- assert(active_ctx); // need at least an active context
- assert(pthread_equal(pthread_self(), active_ctx->thread)); // context has been activated by another thread!
-#endif
- clear_orphans(active_ctx);
-
- GLuint new_vao_id = 0;
- glGenVertexArrays(1, &new_vao_id);
- return new_vao_id;
- }
-
-// this can be called from multiple thread
-void GWN_vao_free(GLuint vao_id, Gwn_Context* ctx)
- {
-#if TRUST_NO_ONE
- assert(ctx);
-#endif
- if (ctx == active_ctx)
- glDeleteVertexArrays(1, &vao_id);
- else
- {
- ctx->orphans_mutex.lock();
- ctx->orphaned_vertarray_ids.emplace_back(vao_id);
- ctx->orphans_mutex.unlock();
- }
- }
-
-void gwn_context_add_batch(Gwn_Context* ctx, Gwn_Batch* batch)
- {
- ctx->batches.emplace(batch);
- }
-
-void gwn_context_remove_batch(Gwn_Context* ctx, Gwn_Batch* batch)
- {
- ctx->orphans_mutex.lock();
- ctx->batches.erase(batch);
- ctx->orphans_mutex.unlock();
- }
diff --git a/intern/gawain/src/gwn_vertex_buffer.c b/intern/gawain/src/gwn_vertex_buffer.c
deleted file mode 100644
index a372c62bd0a..00000000000
--- a/intern/gawain/src/gwn_vertex_buffer.c
+++ /dev/null
@@ -1,258 +0,0 @@
-
-// Gawain vertex buffer
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_vertex_buffer.h"
-#include "gwn_buffer_id.h"
-#include "gwn_vertex_format_private.h"
-#include <stdlib.h>
-#include <string.h>
-
-#define KEEP_SINGLE_COPY 1
-
-static unsigned vbo_memory_usage;
-
-static GLenum convert_usage_type_to_gl(Gwn_UsageType type)
- {
- static const GLenum table[] = {
- [GWN_USAGE_STREAM] = GL_STREAM_DRAW,
- [GWN_USAGE_STATIC] = GL_STATIC_DRAW,
- [GWN_USAGE_DYNAMIC] = GL_DYNAMIC_DRAW
- };
- return table[type];
- }
-
-Gwn_VertBuf* GWN_vertbuf_create(Gwn_UsageType usage)
- {
- Gwn_VertBuf* verts = malloc(sizeof(Gwn_VertBuf));
- GWN_vertbuf_init(verts, usage);
- return verts;
- }
-
-Gwn_VertBuf* GWN_vertbuf_create_with_format_ex(const Gwn_VertFormat* format, Gwn_UsageType usage)
- {
- Gwn_VertBuf* verts = GWN_vertbuf_create(usage);
- GWN_vertformat_copy(&verts->format, format);
- if (!format->packed)
- VertexFormat_pack(&verts->format);
- return verts;
-
- // this function might seem redundant, but there is potential for memory savings here...
- // TODO: implement those memory savings
- }
-
-void GWN_vertbuf_init(Gwn_VertBuf* verts, Gwn_UsageType usage)
- {
- memset(verts, 0, sizeof(Gwn_VertBuf));
- verts->usage = usage;
- verts->dirty = true;
- }
-
-void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf* verts, const Gwn_VertFormat* format, Gwn_UsageType usage)
- {
- GWN_vertbuf_init(verts, usage);
- GWN_vertformat_copy(&verts->format, format);
- if (!format->packed)
- VertexFormat_pack(&verts->format);
- }
-
-void GWN_vertbuf_discard(Gwn_VertBuf* verts)
- {
- if (verts->vbo_id)
- {
- GWN_buf_id_free(verts->vbo_id);
-#if VRAM_USAGE
- vbo_memory_usage -= GWN_vertbuf_size_get(verts);
-#endif
- }
-
- if (verts->data)
- free(verts->data);
-
- free(verts);
- }
-
-unsigned GWN_vertbuf_size_get(const Gwn_VertBuf* verts)
- {
- return vertex_buffer_size(&verts->format, verts->vertex_len);
- }
-
-// create a new allocation, discarding any existing data
-void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, unsigned v_len)
- {
- Gwn_VertFormat* format = &verts->format;
- if (!format->packed)
- VertexFormat_pack(format);
-
-#if TRUST_NO_ONE
- // catch any unnecessary use
- assert(verts->vertex_alloc != v_len || verts->data == NULL);
-#endif
-
- // only create the buffer the 1st time
- if (verts->vbo_id == 0)
- verts->vbo_id = GWN_buf_id_alloc();
-
- // discard previous data if any
- if (verts->data)
- free(verts->data);
-
-#if VRAM_USAGE
- unsigned new_size = vertex_buffer_size(&verts->format, v_len);
- vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts);
-#endif
-
- verts->dirty = true;
- verts->vertex_len = verts->vertex_alloc = v_len;
- verts->data = malloc(sizeof(GLubyte) * GWN_vertbuf_size_get(verts));
- }
-
-// resize buffer keeping existing data
-void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, unsigned v_len)
- {
-#if TRUST_NO_ONE
- assert(verts->data != NULL);
- assert(verts->vertex_alloc != v_len);
-#endif
-
-#if VRAM_USAGE
- unsigned new_size = vertex_buffer_size(&verts->format, v_len);
- vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts);
-#endif
-
- verts->dirty = true;
- verts->vertex_len = verts->vertex_alloc = v_len;
- verts->data = realloc(verts->data, sizeof(GLubyte) * GWN_vertbuf_size_get(verts));
- }
-
-// set vertex count but does not change allocation
-// only this many verts will be uploaded to the GPU and rendered
-// this is usefull for streaming data
-void GWN_vertbuf_vertex_count_set(Gwn_VertBuf* verts, unsigned v_len)
- {
-#if TRUST_NO_ONE
- assert(verts->data != NULL); // only for dynamic data
- assert(v_len <= verts->vertex_alloc);
-#endif
-
-#if VRAM_USAGE
- unsigned new_size = vertex_buffer_size(&verts->format, v_len);
- vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts);
-#endif
-
- verts->vertex_len = v_len;
- }
-
-void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, const void* data)
- {
- const Gwn_VertFormat* format = &verts->format;
- const Gwn_VertAttr* a = format->attribs + a_idx;
-
-#if TRUST_NO_ONE
- assert(a_idx < format->attr_len);
- assert(v_idx < verts->vertex_alloc);
- assert(verts->data != NULL);
-#endif
-
- verts->dirty = true;
- memcpy((GLubyte*)verts->data + a->offset + v_idx * format->stride, data, a->sz);
- }
-
-void GWN_vertbuf_attr_fill(Gwn_VertBuf* verts, unsigned a_idx, const void* data)
- {
- const Gwn_VertFormat* format = &verts->format;
- const Gwn_VertAttr* a = format->attribs + a_idx;
-
-#if TRUST_NO_ONE
- assert(a_idx < format->attr_len);
-#endif
-
- const unsigned stride = a->sz; // tightly packed input data
-
- GWN_vertbuf_attr_fill_stride(verts, a_idx, stride, data);
- }
-
-void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned stride, const void* data)
- {
- const Gwn_VertFormat* format = &verts->format;
- const Gwn_VertAttr* a = format->attribs + a_idx;
-
-#if TRUST_NO_ONE
- assert(a_idx < format->attr_len);
- assert(verts->data != NULL);
-#endif
-
- verts->dirty = true;
- const unsigned vertex_len = verts->vertex_len;
-
- if (format->attr_len == 1 && stride == format->stride)
- {
- // we can copy it all at once
- memcpy(verts->data, data, vertex_len * a->sz);
- }
- else
- {
- // we must copy it per vertex
- for (unsigned v = 0; v < vertex_len; ++v)
- memcpy((GLubyte*)verts->data + a->offset + v * format->stride, (const GLubyte*)data + v * stride, a->sz);
- }
- }
-
-void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertBufRaw *access)
- {
- const Gwn_VertFormat* format = &verts->format;
- const Gwn_VertAttr* a = format->attribs + a_idx;
-
-#if TRUST_NO_ONE
- assert(a_idx < format->attr_len);
- assert(verts->data != NULL);
-#endif
-
- verts->dirty = true;
-
- access->size = a->sz;
- access->stride = format->stride;
- access->data = (GLubyte*)verts->data + a->offset;
- access->data_init = access->data;
-#if TRUST_NO_ONE
- access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride);
-#endif
- }
-
-static void VertBuffer_upload_data(Gwn_VertBuf* verts)
- {
- unsigned buffer_sz = GWN_vertbuf_size_get(verts);
-
- // orphan the vbo to avoid sync
- glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage));
- // upload data
- glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data);
-
- if (verts->usage == GWN_USAGE_STATIC)
- {
- free(verts->data);
- verts->data = NULL;
- }
-
- verts->dirty = false;
- }
-
-void GWN_vertbuf_use(Gwn_VertBuf* verts)
- {
- glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
-
- if (verts->dirty)
- VertBuffer_upload_data(verts);
- }
-
-unsigned GWN_vertbuf_get_memory_usage(void)
- {
- return vbo_memory_usage;
- }
diff --git a/intern/gawain/src/gwn_vertex_format.c b/intern/gawain/src/gwn_vertex_format.c
deleted file mode 100644
index 122de12ec6e..00000000000
--- a/intern/gawain/src/gwn_vertex_format.c
+++ /dev/null
@@ -1,291 +0,0 @@
-
-// Gawain vertex format
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 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 "gwn_vertex_format.h"
-#include "gwn_vertex_format_private.h"
-#include <stddef.h>
-#include <string.h>
-
-#define PACK_DEBUG 0
-
-#if PACK_DEBUG
- #include <stdio.h>
-#endif
-
-void GWN_vertformat_clear(Gwn_VertFormat* format)
- {
-#if TRUST_NO_ONE
- memset(format, 0, sizeof(Gwn_VertFormat));
-#else
- format->attr_len = 0;
- format->packed = false;
- format->name_offset = 0;
- format->name_len = 0;
-
- for (unsigned i = 0; i < GWN_VERT_ATTR_MAX_LEN; i++)
- format->attribs[i].name_len = 0;
-#endif
- }
-
-void GWN_vertformat_copy(Gwn_VertFormat* dest, const Gwn_VertFormat* src)
- {
- // copy regular struct fields
- memcpy(dest, src, sizeof(Gwn_VertFormat));
-
- for (unsigned i = 0; i < dest->attr_len; i++)
- for (unsigned j = 0; j < dest->attribs[i].name_len; j++)
- dest->attribs[i].name[j] = (char *)dest + (src->attribs[i].name[j] - ((char *)src));
- }
-
-static GLenum convert_comp_type_to_gl(Gwn_VertCompType type)
- {
- static const GLenum table[] = {
- [GWN_COMP_I8] = GL_BYTE,
- [GWN_COMP_U8] = GL_UNSIGNED_BYTE,
- [GWN_COMP_I16] = GL_SHORT,
- [GWN_COMP_U16] = GL_UNSIGNED_SHORT,
- [GWN_COMP_I32] = GL_INT,
- [GWN_COMP_U32] = GL_UNSIGNED_INT,
-
- [GWN_COMP_F32] = GL_FLOAT,
-
- [GWN_COMP_I10] = GL_INT_2_10_10_10_REV
- };
- return table[type];
- }
-
-static unsigned comp_sz(Gwn_VertCompType type)
- {
-#if TRUST_NO_ONE
- assert(type <= GWN_COMP_F32); // other types have irregular sizes (not bytes)
-#endif
-
- const GLubyte sizes[] = {1,1,2,2,4,4,4};
- return sizes[type];
- }
-
-static unsigned attrib_sz(const Gwn_VertAttr *a)
- {
- if (a->comp_type == GWN_COMP_I10)
- return 4; // always packed as 10_10_10_2
-
- return a->comp_len * comp_sz(a->comp_type);
- }
-
-static unsigned attrib_align(const Gwn_VertAttr *a)
- {
- if (a->comp_type == GWN_COMP_I10)
- return 4; // always packed as 10_10_10_2
-
- unsigned c = comp_sz(a->comp_type);
- if (a->comp_len == 3 && c <= 2)
- return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?)
- else
- return c; // most fetches are ok if components are naturally aligned
- }
-
-unsigned vertex_buffer_size(const Gwn_VertFormat* format, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(format->packed && format->stride > 0);
-#endif
-
- return format->stride * vertex_len;
- }
-
-static const char* copy_attrib_name(Gwn_VertFormat* format, const char* name)
- {
- // strncpy does 110% of what we need; let's do exactly 100%
- char* name_copy = format->names + format->name_offset;
- unsigned available = GWN_VERT_ATTR_NAMES_BUF_LEN - format->name_offset;
- bool terminated = false;
-
- for (unsigned i = 0; i < available; ++i)
- {
- const char c = name[i];
- name_copy[i] = c;
- if (c == '\0')
- {
- terminated = true;
- format->name_offset += (i + 1);
- break;
- }
- }
-
-#if TRUST_NO_ONE
- assert(terminated);
- assert(format->name_offset <= GWN_VERT_ATTR_NAMES_BUF_LEN);
-#else
- (void)terminated;
-#endif
-
- return name_copy;
- }
-
-unsigned GWN_vertformat_attr_add(Gwn_VertFormat* format, const char* name, Gwn_VertCompType comp_type, unsigned comp_len, Gwn_VertFetchMode fetch_mode)
- {
-#if TRUST_NO_ONE
- assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more
- assert(format->attr_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more
- assert(!format->packed); // packed means frozen/locked
- assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16);
- switch (comp_type)
- {
- case GWN_COMP_F32:
- // float type can only kept as float
- assert(fetch_mode == GWN_FETCH_FLOAT);
- break;
- case GWN_COMP_I10:
- // 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_len == 3 || comp_len == 4);
- assert(fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT); // not strictly required, may relax later
- break;
- default:
- // integer types can be kept as int or converted/normalized to float
- assert(fetch_mode != GWN_FETCH_FLOAT);
- // only support float matrices (see Batch_update_program_bindings)
- assert(comp_len != 8 && comp_len != 12 && comp_len != 16);
- }
-#endif
- format->name_len++; // multiname support
-
- const unsigned attrib_id = format->attr_len++;
- Gwn_VertAttr* attrib = format->attribs + attrib_id;
-
- attrib->name[attrib->name_len++] = copy_attrib_name(format, name);
- attrib->comp_type = comp_type;
- attrib->gl_comp_type = convert_comp_type_to_gl(comp_type);
- attrib->comp_len = (comp_type == GWN_COMP_I10) ? 4 : comp_len; // system needs 10_10_10_2 to be 4 or BGRA
- attrib->sz = attrib_sz(attrib);
- attrib->offset = 0; // offsets & stride are calculated later (during pack)
- attrib->fetch_mode = fetch_mode;
-
- return attrib_id;
- }
-
-void GWN_vertformat_alias_add(Gwn_VertFormat* format, const char* alias)
- {
- Gwn_VertAttr* attrib = format->attribs + (format->attr_len - 1);
-#if TRUST_NO_ONE
- assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more
- assert(attrib->name_len < GWN_VERT_ATTR_MAX_NAMES);
-#endif
- format->name_len++; // multiname support
- attrib->name[attrib->name_len++] = copy_attrib_name(format, alias);
- }
-
-unsigned padding(unsigned offset, unsigned alignment)
- {
- const unsigned mod = offset % alignment;
- return (mod == 0) ? 0 : (alignment - mod);
- }
-
-#if PACK_DEBUG
-static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
- {
- const char c = 'A' + a_idx;
- for (unsigned i = 0; i < pad; ++i)
- putchar('-');
- for (unsigned i = 0; i < sz; ++i)
- putchar(c);
- }
-#endif
-
-void VertexFormat_pack(Gwn_VertFormat* format)
- {
- // for now, attributes are packed in the order they were added,
- // making sure each attrib is naturally aligned (add padding where necessary)
-
- // later we can implement more efficient packing w/ reordering
- // (keep attrib ID order, adjust their offsets to reorder in buffer)
-
- // TODO:
- // realloc just enough to hold the final combo string. And just enough to
- // hold used attribs, not all 16.
-
- Gwn_VertAttr* a0 = format->attribs + 0;
- a0->offset = 0;
- unsigned offset = a0->sz;
-
-#if PACK_DEBUG
- show_pack(0, a0->sz, 0);
-#endif
-
- for (unsigned a_idx = 1; a_idx < format->attr_len; ++a_idx)
- {
- Gwn_VertAttr* a = format->attribs + a_idx;
- unsigned mid_padding = padding(offset, attrib_align(a));
- offset += mid_padding;
- a->offset = offset;
- offset += a->sz;
-
-#if PACK_DEBUG
- show_pack(a_idx, a->sz, mid_padding);
-#endif
- }
-
- unsigned end_padding = padding(offset, attrib_align(a0));
-
-#if PACK_DEBUG
- show_pack(0, 0, end_padding);
- putchar('\n');
-#endif
-
- format->stride = offset + end_padding;
- format->packed = true;
- }
-
-
-// OpenGL ES packs in a different order as desktop GL but component conversion is the same.
-// Of the code here, only struct Gwn_PackedNormal needs to change.
-
-#define SIGNED_INT_10_MAX 511
-#define SIGNED_INT_10_MIN -512
-
-static int clampi(int x, int min_allowed, int max_allowed)
- {
-#if TRUST_NO_ONE
- assert(min_allowed <= max_allowed);
-#endif
-
- if (x < min_allowed)
- return min_allowed;
- else if (x > max_allowed)
- return max_allowed;
- else
- return x;
- }
-
-static int quantize(float x)
- {
- int qx = x * 511.0f;
- return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX);
- }
-
-static int convert_i16(short x)
- {
- // 16-bit signed --> 10-bit signed
- return x >> 6;
- // TODO: round?
- }
-
-Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3])
- {
- Gwn_PackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) };
- return n;
- }
-
-Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3])
- {
- Gwn_PackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]) };
- return n;
- }
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
index 1ba591bd0b2..3b3cf7a2962 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.cpp
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -55,6 +55,7 @@ GHOST_ContextSDL::GHOST_ContextSDL(
int contextResetNotificationStrategy)
: GHOST_Context(stereoVisual, numOfAASamples),
m_window(window),
+ m_hidden_window(NULL),
m_contextProfileMask(contextProfileMask),
m_contextMajorVersion(contextMajorVersion),
m_contextMinorVersion(contextMinorVersion),
@@ -62,7 +63,7 @@ GHOST_ContextSDL::GHOST_ContextSDL(
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
m_context(NULL)
{
- assert(m_window != NULL);
+ // assert(m_window != NULL);
}
@@ -70,7 +71,7 @@ GHOST_ContextSDL::~GHOST_ContextSDL()
{
if (m_context != NULL) {
if (m_window != NULL && m_context == SDL_GL_GetCurrentContext())
- SDL_GL_MakeCurrent(m_window, m_context);
+ SDL_GL_MakeCurrent(m_window, NULL);
if (m_context != s_sharedContext || s_sharedCount == 1) {
assert(s_sharedCount > 0);
@@ -82,6 +83,9 @@ GHOST_ContextSDL::~GHOST_ContextSDL()
SDL_GL_DeleteContext(m_context);
}
+
+ if (m_hidden_window != NULL)
+ SDL_DestroyWindow(m_hidden_window);
}
}
@@ -160,6 +164,18 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, m_numOfAASamples);
}
+ if (m_window == NULL) {
+ m_hidden_window = SDL_CreateWindow(
+ "Offscreen Context Windows",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ 1, 1,
+ SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN
+ );
+
+ m_window = m_hidden_window;
+ }
+
m_context = SDL_GL_CreateContext(m_window);
GHOST_TSuccess success;
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
index 681d24bb7c6..1829819300c 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.h
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -120,6 +120,7 @@ public:
private:
SDL_Window *m_window;
+ SDL_Window *m_hidden_window;
const int m_contextProfileMask;
const int m_contextMajorVersion;
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 0629eacc3ff..4a8a8c48018 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -219,10 +219,12 @@ bool GHOST_System::getFullScreen(void)
void GHOST_System::dispatchEvents()
{
#ifdef WITH_INPUT_NDOF
+ #ifndef WIN32
// NDOF Motion event is sent only once per dispatch, so do it now:
if (m_ndofManager) {
m_ndofManager->sendMotionEvent();
}
+ #endif
#endif
if (m_eventManager) {
@@ -297,7 +299,9 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown
#ifdef WITH_INPUT_NDOF
void GHOST_System::setNDOFDeadZone(float deadzone)
{
- this->m_ndofManager->setDeadZone(deadzone);
+ if (this->m_ndofManager) {
+ this->m_ndofManager->setDeadZone(deadzone);
+ }
}
#endif
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 7c8d26d7486..ac3dfd71d63 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -53,6 +53,8 @@ public:
void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
bool supportsNativeDialogs(void) { return false;}
+ GHOST_IContext *createOffscreenContext() { return NULL; }
+ GHOST_TSuccess disposeContext(GHOST_IContext *context) { return GHOST_kFailure; }
GHOST_TSuccess init() {
GHOST_TSuccess success = GHOST_System::init();
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index d7860577338..094cbe76cb2 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -26,6 +26,7 @@
#include <assert.h>
+#include "GHOST_ContextSDL.h"
#include "GHOST_SystemSDL.h"
#include "GHOST_WindowSDL.h"
@@ -149,6 +150,34 @@ GHOST_SystemSDL::getNumDisplays() const
return SDL_GetNumVideoDisplays();
}
+GHOST_IContext *
+GHOST_SystemSDL::createOffscreenContext()
+{
+ GHOST_Context *context = new GHOST_ContextSDL(
+ 0,
+ 0,
+ NULL,
+ 0, // profile bit
+ 3, 3,
+ GHOST_OPENGL_SDL_CONTEXT_FLAGS,
+ GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+
+ return NULL;
+}
+
+GHOST_TSuccess
+GHOST_SystemSDL::disposeContext(GHOST_IContext *context)
+{
+ delete context;
+
+ return GHOST_kSuccess;
+}
+
GHOST_TSuccess
GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const
{
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 41f110ed15d..0610a80ea5f 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -95,6 +95,12 @@ public:
getMainDisplayDimensions(GHOST_TUns32& width,
GHOST_TUns32& height) const;
+ GHOST_IContext *
+ createOffscreenContext();
+
+ GHOST_TSuccess
+ disposeContext(GHOST_IContext *context);
+
/**
* Informs if the system provides native dialogs (eg. confirm quit)
*/
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 17c41e96be4..924173a6c68 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -1110,8 +1110,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
break;
#ifdef WITH_INPUT_NDOF
case RIM_TYPEHID:
- if (system->processNDOF(raw))
+ if (system->processNDOF(raw)) {
+ system->m_ndofManager->sendMotionEvent();
eventHandled = true;
+ }
break;
#endif
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index fcda5d8b72d..5d383f68e9d 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -261,7 +261,7 @@ GHOST_SystemX11::
#endif /* WITH_X11_XINPUT */
if (m_xkb_descr) {
- XkbFreeNames(m_xkb_descr, XkbKeyNamesMask, false);
+ XkbFreeKeyboard (m_xkb_descr, XkbAllComponentsMask, true);
}
XCloseDisplay(m_display);
diff --git a/intern/ghost/intern/GHOST_TaskbarX11.cpp b/intern/ghost/intern/GHOST_TaskbarX11.cpp
index 2ef82dc6636..9826ccdfa37 100644
--- a/intern/ghost/intern/GHOST_TaskbarX11.cpp
+++ b/intern/ghost/intern/GHOST_TaskbarX11.cpp
@@ -44,7 +44,7 @@ static unity_event_loop_t unity_event_loop;
static bool libunity_initialized = false;
static bool libunity_available = false;
-void* libunity_handle = NULL;
+static void *libunity_handle = NULL;
void GHOST_TaskBarX11::free()
{
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 2b986428fd3..22dc772fff0 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -865,30 +865,30 @@ void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST
void GHOST_WindowCocoa::screenToClientIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
{
- NSPoint screenCoord;
- NSPoint baseCoord;
+ NSRect screenCoord;
+ NSRect baseCoord;
- screenCoord.x = inX;
- screenCoord.y = inY;
+ screenCoord.origin.x = inX;
+ screenCoord.origin.y = inY;
- baseCoord = [m_window convertScreenToBase:screenCoord];
+ baseCoord = [m_window convertRectFromScreen:screenCoord];
- outX = baseCoord.x;
- outY = baseCoord.y;
+ outX = baseCoord.origin.x;
+ outY = baseCoord.origin.y;
}
void GHOST_WindowCocoa::clientToScreenIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
{
- NSPoint screenCoord;
- NSPoint baseCoord;
+ NSRect screenCoord;
+ NSRect baseCoord;
- baseCoord.x = inX;
- baseCoord.y = inY;
+ baseCoord.origin.x = inX;
+ baseCoord.origin.y = inY;
- screenCoord = [m_window convertBaseToScreen:baseCoord];
+ screenCoord = [m_window convertRectToScreen:baseCoord];
- outX = screenCoord.x;
- outY = screenCoord.y;
+ outX = screenCoord.origin.x;
+ outY = screenCoord.origin.y;
}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index aeb6188daef..9c41087bd59 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -93,7 +93,7 @@ GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type)
m_wantNumOfAASamples,
m_sdl_win,
0, // profile bit
- 0, 0,
+ 3, 3,
GHOST_OPENGL_SDL_CONTEXT_FLAGS,
GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index e740542961e..11aa2094997 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -598,13 +598,15 @@ GHOST_WindowX11(GHOST_SystemX11 *system,
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
+static Bool destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
{
GHOST_PRINT("XIM input context destroyed\n");
if (ptr) {
*(XIC *)ptr = NULL;
}
+ /* Ignored by X11. */
+ return True;
}
bool GHOST_WindowX11::createX11_XIC()
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 2611477252a..10898e4239b 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -27,8 +27,8 @@ set(INC
.
../glew-mx
../guardedalloc
- ../gawain
../../source/blender/blenlib
+ ../../source/blender/gpu
)
set(INC_SYS
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 090422ff795..78c73a6e3bf 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -49,7 +49,7 @@
#endif
extern "C" {
-#include "gawain/gwn_immediate.h"
+#include "GPU_immediate.h"
}
using namespace OCIO_NAMESPACE;
@@ -98,7 +98,7 @@ typedef struct OCIO_GLSLShader {
GLuint ocio_shader;
GLuint vert_shader;
GLuint program;
- Gwn_ShaderInterface *shader_interface;
+ GPUShaderInterface *shader_interface;
} GLSLDrawState;
typedef struct OCIO_GLSLDrawState {
@@ -251,7 +251,7 @@ static void freeGLSLShader(OCIO_GLSLShader *shader)
}
if (shader->shader_interface) {
- GWN_shaderinterface_discard(shader->shader_interface);
+ GPU_shaderinterface_discard(shader->shader_interface);
}
if (shader->ocio_shader) {
@@ -424,9 +424,9 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
if (shader->program) {
if (shader->shader_interface) {
- GWN_shaderinterface_discard(shader->shader_interface);
+ GPU_shaderinterface_discard(shader->shader_interface);
}
- shader->shader_interface = GWN_shaderinterface_create(shader->program);
+ shader->shader_interface = GPU_shaderinterface_create(shader->program);
}
}
}
@@ -461,9 +461,9 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
*
* TODO(sergey): Look into some nicer solution.
*/
- Gwn_VertFormat *format = immVertexFormat();
- GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindProgram(shader->program, shader->shader_interface);
immUniform1i("image_texture", 0);
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index 876b5c0181f..887eb399224 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -34,20 +34,40 @@ set(INC_SYS
)
set(SRC
- opensubdiv_capi.cc
- opensubdiv_converter.cc
- opensubdiv_device_context_cuda.cc
- opensubdiv_device_context_opencl.cc
- opensubdiv_evaluator_capi.cc
- opensubdiv_gpu_capi.cc
- opensubdiv_utils_capi.cc
+ internal/opensubdiv.cc
+ internal/opensubdiv_converter_factory.cc
+ internal/opensubdiv_converter_internal.cc
+ internal/opensubdiv_converter_orient.cc
+ internal/opensubdiv_device_context_cuda.cc
+ internal/opensubdiv_device_context_opencl.cc
+ internal/opensubdiv_evaluator.cc
+ internal/opensubdiv_evaluator_internal.cc
+ internal/opensubdiv_gl_mesh.cc
+ internal/opensubdiv_gl_mesh_draw.cc
+ internal/opensubdiv_gl_mesh_fvar.cc
+ internal/opensubdiv_gl_mesh_internal.cc
+ internal/opensubdiv_topology_refiner.cc
+ internal/opensubdiv_topology_refiner_internal.cc
+ internal/opensubdiv_util.cc
+
+ internal/opensubdiv_converter_internal.h
+ internal/opensubdiv_converter_orient.h
+ internal/opensubdiv_converter_orient_impl.h
+ internal/opensubdiv_device_context_cuda.h
+ internal/opensubdiv_device_context_opencl.h
+ internal/opensubdiv_evaluator_internal.h
+ internal/opensubdiv_gl_mesh_fvar.h
+ internal/opensubdiv_gl_mesh_internal.h
+ internal/opensubdiv_internal.h
+ internal/opensubdiv_topology_refiner_internal.h
+ internal/opensubdiv_util.h
opensubdiv_capi.h
+ opensubdiv_capi_type.h
opensubdiv_converter_capi.h
- opensubdiv_device_context_cuda.h
- opensubdiv_device_context_opencl.h
- opensubdiv_intern.h
- opensubdiv_topology_refiner.h
+ opensubdiv_evaluator_capi.h
+ opensubdiv_gl_mesh_capi.h
+ opensubdiv_topology_refiner_capi.h
)
macro(OPENSUBDIV_DEFINE_COMPONENT component)
@@ -64,9 +84,9 @@ OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_OPENMP)
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_COMPUTE)
-data_to_c_simple(gpu_shader_opensubdiv_vertex.glsl SRC)
-data_to_c_simple(gpu_shader_opensubdiv_geometry.glsl SRC)
-data_to_c_simple(gpu_shader_opensubdiv_fragment.glsl SRC)
+data_to_c_simple(shader/gpu_shader_opensubdiv_vertex.glsl SRC)
+data_to_c_simple(shader/gpu_shader_opensubdiv_geometry.glsl SRC)
+data_to_c_simple(shader/gpu_shader_opensubdiv_fragment.glsl SRC)
add_definitions(-DGLEW_STATIC)
diff --git a/intern/opensubdiv/internal/opensubdiv.cc b/intern/opensubdiv/internal/opensubdiv.cc
new file mode 100644
index 00000000000..c2945ed25ab
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv.cc
@@ -0,0 +1,99 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+// Contributor(s): Brecht van Lommel
+
+#include "opensubdiv_capi.h"
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <GL/glew.h>
+
+#include "opensubdiv_device_context_opencl.h"
+#include "opensubdiv_device_context_cuda.h"
+#include "opensubdiv_gl_mesh_capi.h"
+
+void openSubdiv_init(void) {
+ // Ensure all OpenGL strings are cached.
+ openSubdiv_getAvailableEvaluators();
+}
+
+void openSubdiv_cleanup(void) {
+ openSubdiv_deinitGLMeshDrawingResources();
+}
+
+int openSubdiv_getAvailableEvaluators(void) {
+ int flags = OPENSUBDIV_EVALUATOR_CPU;
+
+#ifdef OPENSUBDIV_HAS_OPENMP
+ flags |= OPENSUBDIV_EVALUATOR_OPENMP;
+#endif
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+ if (CLDeviceContext::HAS_CL_VERSION_1_1()) {
+ flags |= OPENSUBDIV_EVALUATOR_OPENCL;
+ }
+#endif
+
+#ifdef OPENSUBDIV_HAS_CUDA
+ if (CudaDeviceContext::HAS_CUDA_VERSION_4_0()) {
+ flags |= OPENSUBDIV_EVALUATOR_CUDA;
+ }
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+ if (GLEW_VERSION_4_1) {
+ flags |= OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK;
+ }
+#endif
+
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+ if (GLEW_VERSION_4_3 || GLEW_ARB_compute_shader) {
+ flags |= OPENSUBDIV_EVALUATOR_GLSL_COMPUTE;
+ }
+#endif
+
+ return flags;
+}
+
+int openSubdiv_getVersionHex(void) {
+#if defined(OPENSUBDIV_VERSION_NUMBER)
+ return OPENSUBDIV_VERSION_NUMBER;
+#elif defined(OPENSUBDIV_VERSION_MAJOR)
+ return OPENSUBDIV_VERSION_MAJOR * 10000 +
+ OPENSUBDIV_VERSION_MINOR * 100 +
+ OPENSUBDIV_VERSION_PATCH;
+#elif defined(OPENSUBDIV_VERSION)
+ const char* version = STRINGIFY(OPENSUBDIV_VERSION);
+ if (version[0] == 'v') {
+ version += 1;
+ }
+ int major = 0, minor = 0, patch = 0;
+ vector<string> tokens;
+ opensubdiv_capi::stringSplit(&tokens, version, "_", true);
+ if (tokens.size() == 3) {
+ major = atoi(tokens[0].c_str());
+ minor = atoi(tokens[1].c_str());
+ patch = atoi(tokens[2].c_str());
+ }
+ return major * 10000 + minor * 100 + patch;
+#else
+ return 0;
+#endif
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
new file mode 100644
index 00000000000..901a421314a
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
@@ -0,0 +1,469 @@
+// Copyright 2015 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include "internal/opensubdiv_converter_factory.h"
+
+#include <cassert>
+#include <cstdio>
+#include <stack>
+#include <vector>
+
+#include <opensubdiv/far/topologyRefinerFactory.h>
+
+#include "internal/opensubdiv_converter_internal.h"
+#include "internal/opensubdiv_converter_orient.h"
+#include "internal/opensubdiv_internal.h"
+#include "opensubdiv_converter_capi.h"
+
+struct TopologyRefinerData {
+ const OpenSubdiv_Converter* converter;
+};
+
+namespace OpenSubdiv {
+namespace OPENSUBDIV_VERSION {
+namespace Far {
+
+template <>
+inline bool
+TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data) {
+ const OpenSubdiv_Converter* converter = cb_data.converter;
+ // Faces and face-vertices.
+ const int num_faces = converter->getNumFaces(converter);
+ setNumBaseFaces(refiner, num_faces);
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ const int num_face_vertices =
+ converter->getNumFaceVertices(converter, face_index);
+ setNumBaseFaceVertices(refiner, face_index, num_face_vertices);
+ }
+ // Vertices.
+ const int num_vertices = converter->getNumVertices(converter);
+ setNumBaseVertices(refiner, num_vertices);
+ // If converter does not provide full topology, we are done.
+ if (!converter->specifiesFullTopology(converter)) {
+ return true;
+ }
+ // Edges and edge-faces.
+ const int num_edges = converter->getNumEdges(converter);
+ setNumBaseEdges(refiner, num_edges);
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ const int num_edge_faces =
+ converter->getNumEdgeFaces(converter, edge_index);
+ setNumBaseEdgeFaces(refiner, edge_index, num_edge_faces);
+ }
+ // Vertex-faces and vertex-edges.
+ for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
+ const int num_vert_edges =
+ converter->getNumVertexEdges(converter, vertex_index);
+ const int num_vert_faces =
+ converter->getNumVertexFaces(converter, vertex_index);
+ setNumBaseVertexEdges(refiner, vertex_index, num_vert_edges);
+ setNumBaseVertexFaces(refiner, vertex_index, num_vert_faces);
+ }
+ return true;
+}
+
+template <>
+inline bool
+TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data) {
+ using Far::IndexArray;
+ const OpenSubdiv_Converter* converter = cb_data.converter;
+ const bool full_topology_specified =
+ converter->specifiesFullTopology(converter);
+ // Face relations.
+ const int num_faces = converter->getNumFaces(converter);
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ IndexArray dst_face_verts = getBaseFaceVertices(refiner, face_index);
+ converter->getFaceVertices(converter, face_index, &dst_face_verts[0]);
+ if (full_topology_specified) {
+ IndexArray dst_face_edges = getBaseFaceEdges(refiner, face_index);
+ converter->getFaceEdges(converter, face_index, &dst_face_edges[0]);
+ }
+ }
+ // If converter does not provide full topology, we are done.
+ if (!full_topology_specified) {
+ return true;
+ }
+ // Edge relations.
+ const int num_edges = converter->getNumEdges(converter);
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ // Edge-vertices.
+ IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index);
+ converter->getEdgeVertices(converter, edge_index, &dst_edge_vertices[0]);
+ // Edge-faces.
+ IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index);
+ converter->getEdgeFaces(converter, edge_index, &dst_edge_faces[0]);
+ }
+ // TODO(sergey): Find a way to move this to an utility function.
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ // Make face normals consistent.
+ std::vector<bool> face_used(num_faces, false);
+ std::stack<int> traverse_stack;
+ int face_start = 0, num_traversed_faces = 0;
+ // Traverse all islands.
+ while (num_traversed_faces != num_faces) {
+ // Find first face of any untraversed islands.
+ while (face_used[face_start]) {
+ ++face_start;
+ }
+ // Add first face to the stack.
+ traverse_stack.push(face_start);
+ face_used[face_start] = true;
+ // Go over whole connected component.
+ while (!traverse_stack.empty()) {
+ int face = traverse_stack.top();
+ traverse_stack.pop();
+ IndexArray face_edges = getBaseFaceEdges(refiner, face);
+ ConstIndexArray face_vertices = getBaseFaceVertices(refiner, face);
+ for (int i = 0; i < face_edges.size(); ++i) {
+ const int edge = face_edges[i];
+ ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
+ if (edge_faces.size() != 2) {
+ /* Can't make consistent normals for non-manifolds. */
+ continue;
+ }
+ ConstIndexArray edge_vertices = getBaseEdgeVertices(refiner, edge);
+ // Get winding of the reference face.
+ const int vert0_of_face = face_vertices.FindIndex(edge_vertices[0]);
+ const int vert1_of_face = face_vertices.FindIndex(edge_vertices[1]);
+ const int delta_face =
+ opensubdiv_capi::getLoopWinding(vert0_of_face, vert1_of_face);
+ for (int edge_face = 0; edge_face < edge_faces.size(); ++edge_face) {
+ const int other_face_index = edge_faces[edge_face];
+ // Never re-traverse faces, only move forward.
+ if (face_used[other_face_index]) {
+ continue;
+ }
+ IndexArray other_face_vertics =
+ getBaseFaceVertices(refiner, other_face_index);
+ const int vert0_of_other_face =
+ other_face_vertics.FindIndex(edge_vertices[0]);
+ const int vert1_of_other_face =
+ other_face_vertics.FindIndex(edge_vertices[1]);
+ const int delta_other_face = opensubdiv_capi::getLoopWinding(
+ vert0_of_other_face, vert1_of_other_face);
+ if (delta_face * delta_other_face > 0) {
+ IndexArray other_face_vertices =
+ getBaseFaceVertices(refiner, other_face_index);
+ IndexArray other_face_edges =
+ getBaseFaceEdges(refiner, other_face_index);
+ opensubdiv_capi::reverseFaceLoops(&other_face_vertices,
+ &other_face_edges);
+ }
+ traverse_stack.push(other_face_index);
+ face_used[other_face_index] = true;
+ }
+ }
+ ++num_traversed_faces;
+ }
+ }
+#endif // OPENSUBDIV_ORIENT_TOPOLOGY
+ // Vertex relations.
+ const int num_vertices = converter->getNumVertices(converter);
+ std::vector<int> vertex_faces, vertex_edges;
+ for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
+ // Vertex-faces.
+ IndexArray dst_vertex_faces = getBaseVertexFaces(refiner, vertex_index);
+ const int num_vertex_faces =
+ converter->getNumVertexFaces(converter, vertex_index);
+ vertex_faces.resize(num_vertex_faces);
+ converter->getVertexFaces(converter, vertex_index, &vertex_faces[0]);
+ // Vertex-edges.
+ IndexArray dst_vertex_edges = getBaseVertexEdges(refiner, vertex_index);
+ const int num_vertex_edges =
+ converter->getNumVertexEdges(converter, vertex_index);
+ vertex_edges.resize(num_vertex_edges);
+ converter->getVertexEdges(converter, vertex_index, &vertex_edges[0]);
+// TODO(sergey): Find a way to move this to an utility function.
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ // Order vertex edges and faces to be in a CCW order.
+ std::fill(face_used.begin(), face_used.end(), false);
+ // Number of edges and faces added to the ordered array.
+ int edge_count_ordered = 0, face_count_ordered = 0;
+ // Add loose edges straight into the edges array.
+ bool has_fan_connections = false;
+ for (int i = 0; i < num_vertex_edges; ++i) {
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, vertex_edges[i]);
+ if (edge_faces.size() == 0) {
+ dst_vertex_edges[edge_count_ordered++] = vertex_edges[i];
+ } else if (edge_faces.size() > 2) {
+ has_fan_connections = true;
+ }
+ }
+ if (has_fan_connections) {
+ // OpenSubdiv currently doesn't give us clues how to handle fan face
+ // connections. and since handling such connections complicates the loop
+ // below we simply don't do special orientation for them.
+ memcpy(&dst_vertex_edges[0], &vertex_edges[0],
+ sizeof(int) * num_vertex_edges);
+ memcpy(&dst_vertex_faces[0], &vertex_faces[0],
+ sizeof(int) * num_vertex_faces);
+ continue;
+ }
+ // Perform at max numbder of vert-edges iteration and try to avoid
+ // deadlock here for malformed mesh.
+ for (int global_iter = 0; global_iter < num_vertex_edges; ++global_iter) {
+ // Number of edges and faces which are still to be ordered.
+ const int num_vertex_edges_remained =
+ num_vertex_edges - edge_count_ordered;
+ const int num_vertex_faces_remained =
+ num_vertex_faces - face_count_ordered;
+ if (num_vertex_edges_remained == 0 && num_vertex_faces_remained == 0) {
+ // All done, nothing to do anymore.
+ break;
+ }
+ // Face, edge and face-vertex index to start traversal from.
+ int face_start = -1, edge_start = -1, face_vertex_start = -1;
+ if (num_vertex_edges_remained == num_vertex_faces_remained) {
+ // Vertex is either complete manifold or is connected to several
+ // manifold islands (hourglass-like configuration), can pick up
+ // random edge unused and start from it.
+ //
+ // TODO(sergey): Start from previous edge from which traversal began at
+ // previous iteration.
+ for (int i = 0; i < num_vertex_edges; ++i) {
+ face_start = vertex_faces[i];
+ if (!face_used[face_start]) {
+ ConstIndexArray face_vertices =
+ getBaseFaceVertices(refiner, face_start);
+ ConstIndexArray face_edges = getBaseFaceEdges(refiner, face_start);
+ face_vertex_start = face_vertices.FindIndex(vertex_index);
+ edge_start = face_edges[face_vertex_start];
+ break;
+ }
+ }
+ } else {
+ // Special handle of non-manifold vertex.
+ for (int i = 0; i < num_vertex_edges; ++i) {
+ edge_start = vertex_edges[i];
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_start);
+ if (edge_faces.size() == 1) {
+ face_start = edge_faces[0];
+ if (!face_used[face_start]) {
+ ConstIndexArray face_vertices =
+ getBaseFaceVertices(refiner, face_start);
+ ConstIndexArray face_edges =
+ getBaseFaceEdges(refiner, face_start);
+ face_vertex_start = face_vertices.FindIndex(vertex_index);
+ if (edge_start == face_edges[face_vertex_start]) {
+ break;
+ }
+ }
+ }
+ // Reset indices for sanity check below.
+ face_start = edge_start = face_vertex_start = -1;
+ }
+ }
+ // Sanity check.
+ assert(face_start != -1);
+ assert(edge_start != -1);
+ assert(face_vertex_start != -1);
+ // Traverse faces starting from the current one. */
+ int edge_first = edge_start;
+ dst_vertex_faces[face_count_ordered++] = face_start;
+ dst_vertex_edges[edge_count_ordered++] = edge_start;
+ face_used[face_start] = true;
+ while (edge_count_ordered < num_vertex_edges) {
+ IndexArray face_vertices = getBaseFaceVertices(refiner, face_start);
+ IndexArray face_edges = getBaseFaceEdges(refiner, face_start);
+ int face_edge_start = face_vertex_start;
+ int face_edge_next = (face_edge_start > 0) ? (face_edge_start - 1)
+ : (face_vertices.size() - 1);
+ Index edge_next = face_edges[face_edge_next];
+ if (edge_next == edge_first) {
+ // Multiple manifolds found, stop for now and handle rest
+ // in the next iteration.
+ break;
+ }
+ dst_vertex_edges[edge_count_ordered++] = edge_next;
+ if (face_count_ordered < num_vertex_faces) {
+ IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_next);
+ assert(edge_faces.size() != 0);
+ if (edge_faces.size() == 1) {
+ assert(edge_faces[0] == face_start);
+ break;
+ } else if (edge_faces.size() != 2) {
+ break;
+ }
+ assert(edge_faces.size() == 2);
+ face_start = edge_faces[(edge_faces[0] == face_start) ? 1 : 0];
+ face_vertex_start =
+ getBaseFaceEdges(refiner, face_start).FindIndex(edge_next);
+ dst_vertex_faces[face_count_ordered++] = face_start;
+ face_used[face_start] = true;
+ }
+ edge_start = edge_next;
+ }
+ }
+ // Verify ordering doesn't ruin connectivity information.
+ assert(face_count_ordered == num_vertex_faces);
+ assert(edge_count_ordered == num_vertex_edges);
+ opensubdiv_capi::checkOrientedVertexConnectivity(
+ num_vertex_edges, num_vertex_faces, &vertex_edges[0], &vertex_faces[0],
+ &dst_vertex_edges[0], &dst_vertex_faces[0]);
+ // For the release builds we're failing mesh construction so instead of
+ // nasty bugs the unsupported mesh will simply disappear from the viewport.
+ if (face_count_ordered != num_vertex_faces ||
+ edge_count_ordered != num_vertex_edges) {
+ return false;
+ }
+#else // OPENSUBDIV_ORIENT_TOPOLOGY
+ memcpy(&dst_vertex_edges[0], &vertex_edges[0],
+ sizeof(int) * num_vertex_edges);
+ memcpy(&dst_vertex_faces[0], &vertex_faces[0],
+ sizeof(int) * num_vertex_faces);
+#endif // OPENSUBDIV_ORIENT_TOPOLOGY
+ }
+ populateBaseLocalIndices(refiner);
+ return true;
+}
+
+template <>
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data) {
+ using OpenSubdiv::Sdc::Crease;
+ const OpenSubdiv_Converter* converter = cb_data.converter;
+ const bool full_topology_specified =
+ converter->specifiesFullTopology(converter);
+ const int num_edges = converter->getNumEdges(converter);
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ const float sharpness =
+ converter->getEdgeSharpness(converter, edge_index);
+ if (sharpness < 1e-6f) {
+ continue;
+ }
+ if (full_topology_specified) {
+ setBaseEdgeSharpness(refiner, edge_index, sharpness);
+ } else {
+ int edge_vertices[2];
+ converter->getEdgeVertices(converter, edge_index, edge_vertices);
+ const int base_edge_index = findBaseEdge(
+ refiner, edge_vertices[0], edge_vertices[1]);
+ if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) {
+ printf("OpenSubdiv Error: failed to find reconstructed edge\n");
+ return false;
+ }
+ setBaseEdgeSharpness(refiner, base_edge_index, sharpness);
+ }
+ }
+ // OpenSubdiv expects non-manifold vertices to be sharp but at the time it
+ // handles correct cases when vertex is a corner of plane. Currently mark
+ // vertices which are adjacent to a loose edge as sharp, but this decision
+ // needs some more investigation.
+ const int num_vertices = converter->getNumVertices(converter);
+ for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
+ ConstIndexArray vertex_edges = getBaseVertexEdges(refiner, vertex_index);
+ if (converter->isInfiniteSharpVertex(converter, vertex_index)) {
+ setBaseVertexSharpness(
+ refiner, vertex_index, Crease::SHARPNESS_INFINITE);
+ continue;
+ }
+ float sharpness = converter->getVertexSharpness(converter, vertex_index);
+ if (vertex_edges.size() == 2) {
+ const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
+ const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
+ const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
+ // TODO(sergey): Find a better mixing between edge and vertex sharpness.
+ sharpness += std::min(sharpness0, sharpness1);
+ sharpness = std::min(sharpness, 1.0f);
+ }
+ setBaseVertexSharpness(refiner, vertex_index, sharpness);
+ }
+ return true;
+}
+
+template <>
+inline bool
+TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data) {
+ const OpenSubdiv_Converter* converter = cb_data.converter;
+ const int num_layers = converter->getNumUVLayers(converter);
+ if (num_layers <= 0) {
+ // No UV maps, we can skip any face-varying data.
+ return true;
+ }
+ const int num_faces = getNumBaseFaces(refiner);
+ for (int layer_index = 0; layer_index < num_layers; ++layer_index) {
+ converter->precalcUVLayer(converter, layer_index);
+ const int num_uvs = converter->getNumUVCoordinates(converter);
+ // Fill in per-corner index of the UV.
+ const int channel = createBaseFVarChannel(refiner, num_uvs);
+ // TODO(sergey): Need to check whether converter changed the winding of
+ // face to match OpenSubdiv's expectations.
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ Far::IndexArray dst_face_uvs =
+ getBaseFaceFVarValues(refiner, face_index, channel);
+ for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
+ const int uv_index =
+ converter->getFaceCornerUVIndex(converter, face_index, corner);
+ dst_face_uvs[corner] = uv_index;
+ }
+ }
+ converter->finishUVLayer(converter);
+ }
+ return true;
+}
+
+template <>
+inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
+ TopologyError /*errCode*/, const char* msg,
+ const TopologyRefinerData& /*mesh*/) {
+ printf("OpenSubdiv Error: %s\n", msg);
+}
+
+} /* namespace Far */
+} /* namespace OPENSUBDIV_VERSION */
+} /* namespace OpenSubdiv */
+
+namespace opensubdiv_capi {
+
+OpenSubdiv::Far::TopologyRefiner* createOSDTopologyRefinerFromConverter(
+ OpenSubdiv_Converter* converter) {
+ using OpenSubdiv::Sdc::Options;
+ using OpenSubdiv::Far::TopologyRefinerFactory;
+ const OpenSubdiv::Sdc::SchemeType scheme_type =
+ getSchemeTypeFromCAPI(converter->getSchemeType(converter));
+ const Options::FVarLinearInterpolation linear_interpolation =
+ getFVarLinearInterpolationFromCAPI(
+ converter->getFVarLinearInterpolation(converter));
+ Options options;
+ options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
+ options.SetCreasingMethod(Options::CREASE_UNIFORM);
+ options.SetFVarLinearInterpolation(linear_interpolation);
+
+ TopologyRefinerFactory<TopologyRefinerData>::Options topology_options(
+ scheme_type, options);
+#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
+ topology_options.validateFullTopology = true;
+#endif
+ TopologyRefinerData cb_data;
+ cb_data.converter = converter;
+ return TopologyRefinerFactory<TopologyRefinerData>::Create(
+ cb_data, topology_options);
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.h b/intern/opensubdiv/internal/opensubdiv_converter_factory.h
new file mode 100644
index 00000000000..451418813e1
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.h
@@ -0,0 +1,37 @@
+// Copyright 2015 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CONVERTER_FACTORY_H_
+#define OPENSUBDIV_CONVERTER_FACTORY_H_
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/far/topologyRefiner.h>
+
+struct OpenSubdiv_Converter;
+
+namespace opensubdiv_capi {
+
+OpenSubdiv::Far::TopologyRefiner* createOSDTopologyRefinerFromConverter(
+ struct OpenSubdiv_Converter* converter);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_CONVERTER_FACTORY_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_internal.cc b/intern/opensubdiv/internal/opensubdiv_converter_internal.cc
new file mode 100644
index 00000000000..2f7a7109ea1
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_internal.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include "internal/opensubdiv_converter_internal.h"
+
+#include <opensubdiv/sdc/crease.h>
+#include <cassert>
+
+namespace opensubdiv_capi {
+
+OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type) {
+ switch (type) {
+ case OSD_SCHEME_BILINEAR:
+ return OpenSubdiv::Sdc::SCHEME_BILINEAR;
+ case OSD_SCHEME_CATMARK:
+ return OpenSubdiv::Sdc::SCHEME_CATMARK;
+ case OSD_SCHEME_LOOP:
+ return OpenSubdiv::Sdc::SCHEME_LOOP;
+ }
+ assert(!"Unknown scheme type passed via C-API");
+ return OpenSubdiv::Sdc::SCHEME_CATMARK;
+}
+
+OpenSubdiv::Sdc::Options::FVarLinearInterpolation
+getFVarLinearInterpolationFromCAPI(
+ OpenSubdiv_FVarLinearInterpolation linear_interpolation) {
+ typedef OpenSubdiv::Sdc::Options Options;
+ switch (linear_interpolation) {
+ case OSD_FVAR_LINEAR_INTERPOLATION_NONE:
+ return Options::FVAR_LINEAR_NONE;
+ case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY:
+ return Options::FVAR_LINEAR_CORNERS_ONLY;
+ case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1:
+ return Options::FVAR_LINEAR_CORNERS_PLUS1;
+ case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2:
+ return Options::FVAR_LINEAR_CORNERS_PLUS2;
+ case OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES:
+ return Options::FVAR_LINEAR_BOUNDARIES;
+ case OSD_FVAR_LINEAR_INTERPOLATION_ALL:
+ return Options::FVAR_LINEAR_ALL;
+ }
+ assert(!"Unknown fvar linear interpolation passed via C-API");
+ return Options::FVAR_LINEAR_NONE;
+}
+
+OpenSubdiv_FVarLinearInterpolation
+getCAPIFVarLinearInterpolationFromOSD(
+ OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation) {
+ typedef OpenSubdiv::Sdc::Options Options;
+ switch (linear_interpolation) {
+ case Options::FVAR_LINEAR_NONE:
+ return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
+ case Options::FVAR_LINEAR_CORNERS_ONLY:
+ return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY;
+ case Options::FVAR_LINEAR_CORNERS_PLUS1:
+ return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1;
+ case Options::FVAR_LINEAR_CORNERS_PLUS2:
+ return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2;
+ case Options::FVAR_LINEAR_BOUNDARIES:
+ return OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES;
+ case Options::FVAR_LINEAR_ALL:
+ return OSD_FVAR_LINEAR_INTERPOLATION_ALL;
+ }
+ assert(!"Unknown fvar linear interpolation passed via C-API");
+ return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_internal.h b/intern/opensubdiv/internal/opensubdiv_converter_internal.h
new file mode 100644
index 00000000000..411514c45dc
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_internal.h
@@ -0,0 +1,51 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CONVERTER_INTERNAL_H_
+#define OPENSUBDIV_CONVERTER_INTERNAL_H_
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/sdc/options.h>
+#include <opensubdiv/sdc/types.h>
+
+#include "opensubdiv_converter_capi.h"
+
+struct OpenSubdiv_Converter;
+
+namespace opensubdiv_capi {
+
+// Convert scheme type from C-API enum to an OpenSubdiv native enum.
+OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type);
+
+// Convert face-varying interpolation type from C-API to an OpenSubdiv
+// native enum.
+OpenSubdiv::Sdc::Options::FVarLinearInterpolation
+getFVarLinearInterpolationFromCAPI(
+ OpenSubdiv_FVarLinearInterpolation linear_interpolation);
+
+// Similar to above, just other way around.
+OpenSubdiv_FVarLinearInterpolation
+getCAPIFVarLinearInterpolationFromOSD(
+ OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_CONVERTER_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient.cc b/intern/opensubdiv/internal/opensubdiv_converter_orient.cc
new file mode 100644
index 00000000000..449e9028180
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_orient.cc
@@ -0,0 +1,66 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_converter_orient.h"
+
+#include "internal/opensubdiv_internal.h"
+
+namespace opensubdiv_capi {
+
+void checkOrientedVertexConnectivity(const int num_vertex_edges,
+ const int num_vertex_faces,
+ const int* vertex_edges,
+ const int* vertex_faces,
+ const int* dst_vertex_edges,
+ const int* dst_vertex_faces) {
+#ifndef NDEBUG
+ for (int i = 0; i < num_vertex_faces; ++i) {
+ bool found = false;
+ for (int j = 0; j < num_vertex_faces; ++j) {
+ if (vertex_faces[i] == dst_vertex_faces[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert(!"vert-faces connectivity ruined");
+ }
+ }
+ for (int i = 0; i < num_vertex_edges; ++i) {
+ bool found = false;
+ for (int j = 0; j < num_vertex_edges; ++j) {
+ if (vertex_edges[i] == dst_vertex_edges[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert(!"vert-edges connectivity ruined");
+ }
+ }
+#else
+ (void) num_vertex_edges;
+ (void) num_vertex_faces;
+ (void) vertex_edges;
+ (void) vertex_faces;
+ (void) dst_vertex_edges;
+ (void) dst_vertex_faces;
+#endif
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient.h b/intern/opensubdiv/internal/opensubdiv_converter_orient.h
new file mode 100644
index 00000000000..b783007a0cb
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_orient.h
@@ -0,0 +1,50 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CONVERTER_ORIENT_H_
+#define OPENSUBDIV_CONVERTER_ORIENT_H_
+
+#include <opensubdiv/far/types.h>
+
+// Set of utility functions which are needed to bring topology to an orientation
+// (or, winding, if you wish) which OpenSubdiv expects.
+
+namespace opensubdiv_capi {
+
+inline void reverseFaceVertices(int* face_vertices, const int num_vertices);
+
+// TODO(sergey): Document which value corresponds to which winding.
+inline int getLoopWinding(int vert0_of_face, int vert1_of_face);
+
+inline void reverseFaceLoops(
+ OpenSubdiv::Far::IndexArray* face_vertices,
+ OpenSubdiv::Far::IndexArray* face_edges);
+
+// Used for debugging, checks whether orientation happened correct.
+void checkOrientedVertexConnectivity(const int num_vertex_edges,
+ const int num_vertex_faces,
+ const int* vertex_edges,
+ const int* vertex_faces,
+ const int* dst_vertex_edges,
+ const int* dst_vertex_faces);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_CONVERTER_ORIENT_H_
+
+#include "internal/opensubdiv_converter_orient_impl.h"
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h b/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h
new file mode 100644
index 00000000000..3125bc600e5
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h
@@ -0,0 +1,66 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
+#define OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
+
+#include "internal/opensubdiv_converter_orient.h"
+
+#include <algorithm>
+#include <cmath>
+#include <utility>
+
+namespace opensubdiv_capi {
+
+inline void reverseFaceVertices(int* face_vertices, const int num_vertices) {
+ int last_vert = face_vertices[num_vertices - 1];
+ for (int i = num_vertices - 1; i > 0; --i) {
+ face_vertices[i] = face_vertices[i - 1];
+ }
+ face_vertices[0] = last_vert;
+}
+
+inline int getLoopWinding(int vert0_of_face, int vert1_of_face) {
+ int delta_face = vert1_of_face - vert0_of_face;
+ if (abs(delta_face) != 1) {
+ if (delta_face > 0) {
+ delta_face = -1;
+ } else {
+ delta_face = 1;
+ }
+ }
+ return delta_face;
+}
+
+inline void reverseFaceLoops(
+ OpenSubdiv::Far::IndexArray* face_vertices,
+ OpenSubdiv::Far::IndexArray* face_edges) {
+ const int num_face_vertices = face_vertices->size();
+ for (int i = 0; i < num_face_vertices / 2; ++i) {
+ const int j = num_face_vertices - i - 1;
+ if (i != j) {
+ std::swap((*face_vertices)[i], (*face_vertices)[j]);
+ std::swap((*face_edges)[i], (*face_edges)[j]);
+ }
+ }
+ reverseFaceVertices(&(*face_vertices)[0], num_face_vertices);
+}
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_device_context_cuda.cc b/intern/opensubdiv/internal/opensubdiv_device_context_cuda.cc
new file mode 100644
index 00000000000..875f503b9ab
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_device_context_cuda.cc
@@ -0,0 +1,226 @@
+// Adopted from OpenSubdiv with the following license:
+//
+// Copyright 2015 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+
+#ifdef OPENSUBDIV_HAS_CUDA
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include "opensubdiv_device_context_cuda.h"
+
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(__APPLE__)
+# include <OpenGL/OpenGL.h>
+#else
+# include <GL/glx.h>
+# include <X11/Xlib.h>
+#endif
+
+#include <cuda.h>
+#include <cuda_gl_interop.h>
+#include <cuda_runtime_api.h>
+#include <algorithm>
+#include <cstdio>
+
+#define message(fmt, ...)
+// #define message(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+#define error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+
+namespace {
+
+int getCudaDeviceForCurrentGLContext() {
+ // Find and use the CUDA device for the current GL context
+ unsigned int interop_device_count = 0;
+ int interopDevices[1];
+ cudaError_t status = cudaGLGetDevices(&interop_device_count,
+ interopDevices,
+ 1,
+ cudaGLDeviceListCurrentFrame);
+ if (status == cudaErrorNoDevice || interop_device_count != 1) {
+ message("CUDA no interop devices found.\n");
+ return 0;
+ }
+ int device = interopDevices[0];
+#if defined(_WIN32)
+ return device;
+#elif defined(__APPLE__)
+ return device;
+#else // X11
+ Display* display = glXGetCurrentDisplay();
+ int screen = DefaultScreen(display);
+ if (device != screen) {
+ error("The CUDA interop device (%d) does not match "
+ "the screen used by the current GL context (%d), "
+ "which may cause slow performance on systems "
+ "with multiple GPU devices.",
+ device, screen);
+ }
+ message("CUDA init using device for current GL context: %d\n", device);
+ return device;
+#endif
+}
+
+// Beginning of GPU Architecture definitions.
+int convertSMVer2Cores_local(int major, int minor) {
+ // Defines for GPU Architecture types (using the SM version to determine
+ // the # of cores per SM
+ typedef struct {
+ int SM; // 0xMm (hexidecimal notation),
+ // M = SM Major version,
+ // and m = SM minor version
+ int Cores;
+ } sSMtoCores;
+
+ sSMtoCores nGpuArchCoresPerSM[] = {
+ {0x10, 8}, // Tesla Generation (SM 1.0) G80 class.
+ {0x11, 8}, // Tesla Generation (SM 1.1) G8x class.
+ {0x12, 8}, // Tesla Generation (SM 1.2) G9x class.
+ {0x13, 8}, // Tesla Generation (SM 1.3) GT200 class.
+ {0x20, 32}, // Fermi Generation (SM 2.0) GF100 class.
+ {0x21, 48}, // Fermi Generation (SM 2.1) GF10x class.
+ {0x30, 192}, // Fermi Generation (SM 3.0) GK10x class.
+ {-1, -1}};
+ int index = 0;
+ while (nGpuArchCoresPerSM[index].SM != -1) {
+ if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor)) {
+ return nGpuArchCoresPerSM[index].Cores;
+ }
+ index++;
+ }
+ printf("MapSMtoCores undefined SMversion %d.%d!\n", major, minor);
+ return -1;
+}
+
+// This function returns the best GPU (with maximum GFLOPS).
+int cutGetMaxGflopsDeviceId() {
+ int current_device = 0, sm_per_multiproc = 0;
+ int max_compute_perf = 0, max_perf_device = -1;
+ int device_count = 0, best_SM_arch = 0;
+ int compat_major, compat_minor;
+ cuDeviceGetCount(&device_count);
+ // Find the best major SM Architecture GPU device.
+ while (current_device < device_count) {
+ cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
+ if (compat_major > 0 && compat_major < 9999) {
+ best_SM_arch = std::max(best_SM_arch, compat_major);
+ }
+ current_device++;
+ }
+ // Find the best CUDA capable GPU device.
+ current_device = 0;
+ while (current_device < device_count) {
+ cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
+ if (compat_major == 9999 && compat_minor == 9999) {
+ sm_per_multiproc = 1;
+ } else {
+ sm_per_multiproc = convertSMVer2Cores_local(compat_major, compat_minor);
+ }
+ int multi_processor_count;
+ cuDeviceGetAttribute(&multi_processor_count,
+ CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+ current_device);
+ int clock_rate;
+ cuDeviceGetAttribute(&clock_rate, CU_DEVICE_ATTRIBUTE_CLOCK_RATE,
+ current_device);
+ int compute_perf = multi_processor_count * sm_per_multiproc * clock_rate;
+ if (compute_perf > max_compute_perf) {
+ /* If we find GPU with SM major > 2, search only these */
+ if (best_SM_arch > 2) {
+ /* If our device==dest_SM_arch, choose this, or else pass. */
+ if (compat_major == best_SM_arch) {
+ max_compute_perf = compute_perf;
+ max_perf_device = current_device;
+ }
+ } else {
+ max_compute_perf = compute_perf;
+ max_perf_device = current_device;
+ }
+ }
+ ++current_device;
+ }
+ return max_perf_device;
+}
+
+} // namespace
+
+bool CudaDeviceContext::HAS_CUDA_VERSION_4_0() {
+#ifdef OPENSUBDIV_HAS_CUDA
+ static bool cuda_initialized = false;
+ static bool cuda_load_success = true;
+ if (!cuda_initialized) {
+ cuda_initialized = true;
+
+#ifdef OPENSUBDIV_HAS_CUEW
+ cuda_load_success = cuewInit(CUEW_INIT_CUDA) == CUEW_SUCCESS;
+ if (!cuda_load_success) {
+ fprintf(stderr, "Loading CUDA failed.\n");
+ }
+#endif
+ // Need to initialize CUDA here so getting device
+ // with the maximum FPLOS works fine.
+ if (cuInit(0) == CUDA_SUCCESS) {
+ // This is to deal with cases like NVidia Optimus,
+ // when there might be CUDA library installed but
+ // NVidia card is not being active.
+ if (cutGetMaxGflopsDeviceId() < 0) {
+ cuda_load_success = false;
+ }
+ } else {
+ cuda_load_success = false;
+ }
+ }
+ return cuda_load_success;
+#else
+ return false;
+#endif
+}
+
+CudaDeviceContext::CudaDeviceContext()
+ : initialized_(false) {
+}
+
+CudaDeviceContext::~CudaDeviceContext() {
+ cudaDeviceReset();
+}
+
+bool CudaDeviceContext::Initialize() {
+ // See if any cuda device is available.
+ int device_count = 0;
+ cudaGetDeviceCount(&device_count);
+ message("CUDA device count: %d\n", device_count);
+ if (device_count <= 0) {
+ return false;
+ }
+ cudaGLSetGLDevice(getCudaDeviceForCurrentGLContext());
+ initialized_ = true;
+ return true;
+}
+
+bool CudaDeviceContext::IsInitialized() const {
+ return initialized_;
+}
+
+#endif // OPENSUBDIV_HAS_CUDA
diff --git a/intern/opensubdiv/internal/opensubdiv_device_context_cuda.h b/intern/opensubdiv/internal/opensubdiv_device_context_cuda.h
new file mode 100644
index 00000000000..ef212df10f0
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_device_context_cuda.h
@@ -0,0 +1,54 @@
+// Adopted from OpenSubdiv with the following license:
+//
+// Copyright 2013 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http: //www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+
+#ifndef OPENSUBDIV_DEVICE_CONTEXT_CUDA_H_
+#define OPENSUBDIV_DEVICE_CONTEXT_CUDA_H_
+
+#ifdef OPENSUBDIV_HAS_CUDA
+
+struct ID3D11Device;
+
+class CudaDeviceContext {
+ public:
+ CudaDeviceContext();
+ ~CudaDeviceContext();
+
+ static bool HAS_CUDA_VERSION_4_0();
+
+ // Initialze cuda device from the current GL context.
+ bool Initialize();
+
+ // Initialze cuda device from the ID3D11Device.
+ bool Initialize(ID3D11Device* device);
+
+ // Returns true if the cuda device has already been initialized.
+ bool IsInitialized() const;
+
+ private:
+ bool initialized_;
+};
+
+#endif // OPENSUBDIV_HAS_CUDA
+
+#endif // _OPENSUBDIV_DEVICE_CONTEXT_CUDA_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_device_context_opencl.cc b/intern/opensubdiv/internal/opensubdiv_device_context_opencl.cc
new file mode 100644
index 00000000000..00f58af894a
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_device_context_opencl.cc
@@ -0,0 +1,269 @@
+// Adopted from OpenSubdiv with the following license:
+//
+// Copyright 2015 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+
+#include "opensubdiv_device_context_opencl.h"
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(__APPLE__)
+# include <OpenGL/OpenGL.h>
+#else
+# include <GL/glx.h>
+#endif
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <vector>
+
+#define message(...) // fprintf(stderr, __VA_ARGS__)
+#define error(...) fprintf(stderr, __VA_ARGS__)
+
+namespace {
+
+// Returns the first found platform.
+cl_platform_id findPlatform() {
+ cl_uint num_platforms;
+ cl_int ci_error_number = clGetPlatformIDs(0, NULL, &num_platforms);
+ if (ci_error_number != CL_SUCCESS) {
+ error("Error %d in clGetPlatformIDs call.\n", ci_error_number);
+ return NULL;
+ }
+ if (num_platforms == 0) {
+ error("No OpenCL platform found.\n");
+ return NULL;
+ }
+ std::vector<cl_platform_id> cl_platform_ids(num_platforms);
+ ci_error_number = clGetPlatformIDs(num_platforms, &cl_platform_ids[0], NULL);
+ char ch_buffer[1024];
+ for (cl_uint i = 0; i < num_platforms; ++i) {
+ ci_error_number = clGetPlatformInfo(cl_platform_ids[i],
+ CL_PLATFORM_NAME,
+ sizeof(ch_buffer),
+ ch_buffer,
+ NULL);
+ if (ci_error_number == CL_SUCCESS) {
+ cl_platform_id platform_id = cl_platform_ids[i];
+ return platform_id;
+ }
+ }
+ return NULL;
+}
+
+// Return the device in cl_devices which supports the extension.
+int findExtensionSupportedDevice(cl_device_id* cl_devices,
+ int num_devices,
+ const char* extension_name) {
+ // Find a device that supports sharing with GL/D3D11
+ // (SLI / X-fire configurations)
+ cl_int cl_error_number;
+ for (int i = 0; i < num_devices; ++i) {
+ // Get extensions string size.
+ size_t extensions_size;
+ cl_error_number = clGetDeviceInfo(cl_devices[i],
+ CL_DEVICE_EXTENSIONS,
+ 0,
+ NULL,
+ &extensions_size);
+ if (cl_error_number != CL_SUCCESS) {
+ error("Error %d in clGetDeviceInfo\n", cl_error_number);
+ return -1;
+ }
+ if (extensions_size > 0) {
+ // Get extensions string.
+ std::string extensions('\0', extensions_size);
+ cl_error_number = clGetDeviceInfo(cl_devices[i],
+ CL_DEVICE_EXTENSIONS,
+ extensions_size,
+ &extensions[0],
+ &extensions_size);
+ if (cl_error_number != CL_SUCCESS) {
+ error("Error %d in clGetDeviceInfo\n", cl_error_number);
+ continue;
+ }
+ // Parse string. This is bit deficient since the extentions
+ // is space separated.
+ //
+ // The actual string would be "cl_khr_d3d11_sharing"
+ // or "cl_nv_d3d11_sharing"
+ if (extensions.find(extension_name) != std::string::npos) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+} // namespace
+
+CLDeviceContext::CLDeviceContext()
+ : cl_context_(NULL),
+ cl_command_queue_(NULL) {
+}
+
+CLDeviceContext::~CLDeviceContext() {
+ if (cl_command_queue_) {
+ clReleaseCommandQueue(cl_command_queue_);
+ }
+ if (cl_context_) {
+ clReleaseContext(cl_context_);
+ }
+}
+
+bool CLDeviceContext::HAS_CL_VERSION_1_1() {
+#ifdef OPENSUBDIV_HAS_CLEW
+ static bool clew_initialized = false;
+ static bool clew_load_success;
+ if (!clew_initialized) {
+ clew_initialized = true;
+ clew_load_success = clewInit() == CLEW_SUCCESS;
+ if (!clew_load_success) {
+ error("Loading OpenCL failed.\n");
+ }
+ }
+ return clew_load_success;
+#endif
+ return true;
+}
+
+bool CLDeviceContext::Initialize() {
+#ifdef OPENSUBDIV_HAS_CLEW
+ if (!clGetPlatformIDs) {
+ error("Error clGetPlatformIDs function not bound.\n");
+ return false;
+ }
+#endif
+ cl_int cl_error_number;
+ cl_platform_id cp_platform = findPlatform();
+
+#if defined(_WIN32)
+ cl_context_properties props[] = {
+ CL_GL_CONTEXT_KHR,
+ (cl_context_properties)wglGetCurrentContext(),
+ CL_WGL_HDC_KHR,
+ (cl_context_properties)wglGetCurrentDC(),
+ CL_CONTEXT_PLATFORM,
+ (cl_context_properties)cp_platform,
+ 0};
+#elif defined(__APPLE__)
+ CGLContextObj kCGLContext = CGLGetCurrentContext();
+ CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
+ cl_context_properties props[] = {CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
+ (cl_context_properties)kCGLShareGroup,
+ 0};
+#else
+ cl_context_properties props[] = {
+ CL_GL_CONTEXT_KHR,
+ (cl_context_properties)glXGetCurrentContext(),
+ CL_GLX_DISPLAY_KHR,
+ (cl_context_properties)glXGetCurrentDisplay(),
+ CL_CONTEXT_PLATFORM,
+ (cl_context_properties)cp_platform,
+ 0};
+#endif
+
+#if defined(__APPLE__)
+ _clContext = clCreateContext(props, 0, NULL, clLogMessagesToStdoutAPPLE, NULL,
+ &cl_error_number);
+ if (cl_error_number != CL_SUCCESS) {
+ error("Error %d in clCreateContext\n", cl_error_number);
+ return false;
+ }
+ size_t devices_size = 0;
+ clGetGLContextInfoAPPLE(_clContext, kCGLContext,
+ CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
+ 0,
+ NULL,
+ &devices_size);
+ const int num_devices = devices_size / sizeof(cl_device_id);
+ if (num_devices == 0) {
+ error("No sharable devices.\n");
+ return false;
+ }
+ std::vector<cl_device_id> cl_devices(num_devices);
+ clGetGLContextInfoAPPLE(_clContext, kCGLContext,
+ CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
+ num_devices * sizeof(cl_device_id),
+ &cl_devices[0],
+ NULL);
+ int cl_device_used = 0;
+#else // not __APPLE__
+ // Get the number of GPU devices available to the platform.
+ cl_uint num_devices = 0;
+ clGetDeviceIDs(cp_platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices);
+ if (num_devices == 0) {
+ error("No CL GPU device found.\n");
+ return false;
+ }
+ // Create the device list.
+ std::vector<cl_device_id> cl_devices(num_devices);
+ clGetDeviceIDs(cp_platform,
+ CL_DEVICE_TYPE_GPU,
+ num_devices,
+ &cl_devices[0],
+ NULL);
+ const char* extension = "cl_khr_gl_sharing";
+ int cl_device_used = findExtensionSupportedDevice(&cl_devices[0],
+ num_devices,
+ extension);
+ if (cl_device_used < 0) {
+ error("No device found that supports CL/GL context sharing\n");
+ return false;
+ }
+ cl_context_ = clCreateContext(props,
+ 1,
+ &cl_devices[cl_device_used],
+ NULL, NULL,
+ &cl_error_number);
+#endif // not __APPLE__
+ if (cl_error_number != CL_SUCCESS) {
+ error("Error %d in clCreateContext\n", cl_error_number);
+ return false;
+ }
+ cl_command_queue_ = clCreateCommandQueue(cl_context_,
+ cl_devices[cl_device_used],
+ 0,
+ &cl_error_number);
+ if (cl_error_number != CL_SUCCESS) {
+ error("Error %d in clCreateCommandQueue\n", cl_error_number);
+ return false;
+ }
+ return true;
+}
+
+bool CLDeviceContext::IsInitialized() const {
+ return (cl_context_ != NULL);
+}
+
+cl_context CLDeviceContext::GetContext() const {
+ return cl_context_;
+}
+
+cl_command_queue CLDeviceContext::GetCommandQueue() const {
+ return cl_command_queue_;
+}
+
+#endif // OPENSUBDIV_HAS_OPENCL
diff --git a/intern/opensubdiv/internal/opensubdiv_device_context_opencl.h b/intern/opensubdiv/internal/opensubdiv_device_context_opencl.h
new file mode 100644
index 00000000000..bc751cb6954
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_device_context_opencl.h
@@ -0,0 +1,52 @@
+// Adopted from OpenSubdiv with the following license:
+//
+// Copyright 2015 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+
+#ifndef OPENSUBDIV_DEVICE_CONTEXT_OPENCL_H_
+#define OPENSUBDIV_DEVICE_CONTEXT_OPENCL_H_
+
+#ifdef OPENSUBDIV_HAS_OPENCL
+#include <opensubdiv/osd/opencl.h>
+
+class CLDeviceContext {
+ public:
+ static bool HAS_CL_VERSION_1_1();
+
+ CLDeviceContext();
+ ~CLDeviceContext();
+
+ bool Initialize();
+
+ bool IsInitialized() const;
+
+ cl_context GetContext() const;
+ cl_command_queue GetCommandQueue() const;
+
+ protected:
+ cl_context cl_context_;
+ cl_command_queue cl_command_queue_;
+};
+
+#endif // OPENSUBDIV_HAS_OPENCL
+
+#endif // _OPENSUBDIV_DEVICE_CONTEXT_OPENCL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_evaluator.cc b/intern/opensubdiv/internal/opensubdiv_evaluator.cc
new file mode 100644
index 00000000000..49b8626448b
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_evaluator.cc
@@ -0,0 +1,158 @@
+// Copyright 2015 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "opensubdiv_evaluator_capi.h"
+
+#include <new>
+#include "MEM_guardedalloc.h"
+
+#include "internal/opensubdiv_evaluator_internal.h"
+
+namespace {
+
+void setCoarsePositions(OpenSubdiv_Evaluator* evaluator,
+ const float* positions,
+ const int start_vertex_index, const int num_vertices) {
+ evaluator->internal->eval_output->setCoarsePositions(positions,
+ start_vertex_index,
+ num_vertices);
+}
+
+void setVaryingData(OpenSubdiv_Evaluator* evaluator,
+ const float* varying_data,
+ const int start_vertex_index, const int num_vertices) {
+ evaluator->internal->eval_output->setVaryingData(varying_data,
+ start_vertex_index,
+ num_vertices);
+}
+
+void setFaceVaryingData(OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const float* face_varying_data,
+ const int start_vertex_index, const int num_vertices) {
+ evaluator->internal->eval_output->setFaceVaryingData(face_varying_channel,
+ face_varying_data,
+ start_vertex_index,
+ num_vertices);
+}
+
+void setCoarsePositionsFromBuffer(OpenSubdiv_Evaluator* evaluator,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ evaluator->internal->eval_output->setCoarsePositionsFromBuffer(
+ buffer,
+ start_offset,
+ stride,
+ start_vertex_index,
+ num_vertices);
+}
+
+void setVaryingDataFromBuffer(OpenSubdiv_Evaluator* evaluator,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ evaluator->internal->eval_output->setVaryingDataFromBuffer(
+ buffer,
+ start_offset,
+ stride,
+ start_vertex_index,
+ num_vertices);
+}
+
+void setFaceVaryingDataFromBuffer(OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ evaluator->internal->eval_output->setFaceVaryingDataFromBuffer(
+ face_varying_channel,
+ buffer,
+ start_offset,
+ stride,
+ start_vertex_index,
+ num_vertices);
+}
+
+void refine(OpenSubdiv_Evaluator* evaluator) {
+ evaluator->internal->eval_output->refine();
+}
+
+void evaluateLimit(OpenSubdiv_Evaluator* evaluator,
+ const int ptex_face_index,
+ const float face_u, const float face_v,
+ float P[3], float dPdu[3], float dPdv[3]) {
+ evaluator->internal->eval_output->evaluateLimit(ptex_face_index,
+ face_u, face_v,
+ P, dPdu, dPdv);
+}
+
+void evaluateVarying(OpenSubdiv_Evaluator* evaluator,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float varying[3]) {
+ evaluator->internal->eval_output->evaluateVarying(ptex_face_index,
+ face_u, face_v,
+ varying);
+}
+
+void evaluateFaceVarying(OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float face_varying[2]) {
+ evaluator->internal->eval_output->evaluateFaceVarying(
+ face_varying_channel, ptex_face_index, face_u, face_v, face_varying);
+}
+
+void assignFunctionPointers(OpenSubdiv_Evaluator* evaluator) {
+ evaluator->setCoarsePositions = setCoarsePositions;
+ evaluator->setVaryingData = setVaryingData;
+ evaluator->setFaceVaryingData = setFaceVaryingData;
+
+ evaluator->setCoarsePositionsFromBuffer = setCoarsePositionsFromBuffer;
+ evaluator->setVaryingDataFromBuffer = setVaryingDataFromBuffer;
+ evaluator->setFaceVaryingDataFromBuffer = setFaceVaryingDataFromBuffer;
+
+ evaluator->refine = refine;
+
+ evaluator->evaluateLimit = evaluateLimit;
+ evaluator->evaluateVarying = evaluateVarying;
+ evaluator->evaluateFaceVarying = evaluateFaceVarying;
+}
+
+} // namespace
+
+OpenSubdiv_Evaluator* openSubdiv_createEvaluatorFromTopologyRefiner(
+ OpenSubdiv_TopologyRefiner* topology_refiner) {
+ OpenSubdiv_Evaluator* evaluator = OBJECT_GUARDED_NEW(OpenSubdiv_Evaluator);
+ assignFunctionPointers(evaluator);
+ evaluator->internal = openSubdiv_createEvaluatorInternal(topology_refiner);
+ return evaluator;
+}
+
+void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator* evaluator) {
+ openSubdiv_deleteEvaluatorInternal(evaluator->internal);
+ OBJECT_GUARDED_DELETE(evaluator, OpenSubdiv_Evaluator);
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
new file mode 100644
index 00000000000..33df7a45e39
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
@@ -0,0 +1,835 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_evaluator_internal.h"
+
+#include <cassert>
+#include <cstdio>
+#include <vector>
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/far/patchMap.h>
+#include <opensubdiv/far/patchTable.h>
+#include <opensubdiv/far/patchTableFactory.h>
+#include <opensubdiv/osd/cpuEvaluator.h>
+#include <opensubdiv/osd/cpuPatchTable.h>
+#include <opensubdiv/osd/cpuVertexBuffer.h>
+#include <opensubdiv/osd/mesh.h>
+#include <opensubdiv/osd/types.h>
+#include <opensubdiv/version.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "internal/opensubdiv_topology_refiner_internal.h"
+#include "internal/opensubdiv_util.h"
+#include "opensubdiv_topology_refiner_capi.h"
+
+using OpenSubdiv::Osd::BufferDescriptor;
+using OpenSubdiv::Osd::CpuEvaluator;
+using OpenSubdiv::Osd::CpuPatchTable;
+using OpenSubdiv::Osd::CpuVertexBuffer;
+using OpenSubdiv::Osd::PatchCoord;
+using OpenSubdiv::Far::PatchMap;
+using OpenSubdiv::Far::PatchTable;
+using OpenSubdiv::Far::PatchTableFactory;
+using OpenSubdiv::Far::StencilTable;
+using OpenSubdiv::Far::StencilTableFactory;
+using OpenSubdiv::Far::TopologyRefiner;
+
+// TODO(sergey): Remove after official requirement bump for OSD version.
+#if OPENSUBDIV_VERSION_NUMBER >= 30200
+# define OPENSUBDIV_HAS_FVAR_EVALUATION
+#else
+# undef OPENSUBDIV_HAS_FVAR_EVALUATION
+#endif
+
+namespace opensubdiv_capi {
+
+namespace {
+
+// Helper class to wrap numerous of patch coordinates into a buffer.
+// Used to pass coordinates to the CPU evaluator. Other evaluators are not
+// supported.
+class PatchCoordBuffer : public std::vector<PatchCoord> {
+ public:
+ static PatchCoordBuffer* Create(int size) {
+ PatchCoordBuffer* buffer = new PatchCoordBuffer();
+ buffer->resize(size);
+ return buffer;
+ }
+
+ PatchCoord* BindCpuBuffer() {
+ return reinterpret_cast<PatchCoord*>(&(*this)[0]);
+ }
+
+ int GetNumVertices() {
+ return size();
+ }
+
+ void UpdateData(const PatchCoord* patch_coords, int num_patch_coords) {
+ memcpy(&(*this)[0],
+ reinterpret_cast<const void*>(patch_coords),
+ sizeof(PatchCoord) * num_patch_coords);
+ }
+};
+
+// Helper class to wrap single of patch coord into a buffer. Used to pass
+// coordinates to the CPU evaluator. Other evaluators are not supported.
+class SinglePatchCoordBuffer {
+ public:
+ static SinglePatchCoordBuffer* Create() {
+ return new SinglePatchCoordBuffer();
+ }
+
+ SinglePatchCoordBuffer() {
+ }
+
+ explicit SinglePatchCoordBuffer(const PatchCoord &patch_coord)
+ : patch_coord_(patch_coord) {
+ }
+
+ PatchCoord* BindCpuBuffer() {
+ return &patch_coord_;
+ }
+
+ int GetNumVertices() {
+ return 1;
+ }
+
+ void UpdateData(const PatchCoord &patch_coord) {
+ patch_coord_ = patch_coord;
+ }
+
+ protected:
+ PatchCoord patch_coord_;
+};
+
+// Helper class which is aimed to be used in cases when buffer is small enough
+// and better to be allocated in stack rather than in heap.
+//
+// TODO(sergey): Check if bare arrays could be used by CPU evaluator.
+template <int element_size, int num_vertices>
+class StackAllocatedBuffer {
+ public:
+ static PatchCoordBuffer* Create(int /*size*/) {
+ // TODO(sergey): Validate that requested dize is smaller than static
+ // stack memory size.
+ return new StackAllocatedBuffer<element_size, num_vertices>();
+ }
+
+ float* BindCpuBuffer() {
+ return &data_[0];
+ }
+
+ int GetNumVertices() {
+ return num_vertices;
+ }
+
+ // TODO(sergey): Support UpdateData().
+ protected:
+ float data_[element_size * num_vertices];
+};
+
+template <typename EVAL_VERTEX_BUFFER,
+ typename STENCIL_TABLE,
+ typename PATCH_TABLE,
+ typename EVALUATOR,
+ typename DEVICE_CONTEXT = void>
+class FaceVaryingVolatileEval {
+ public:
+ typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
+
+ FaceVaryingVolatileEval(int face_varying_channel,
+ const StencilTable* face_varying_stencils,
+ int face_varying_width,
+ PATCH_TABLE* patch_table,
+ EvaluatorCache* evaluator_cache = NULL,
+ DEVICE_CONTEXT* device_context = NULL)
+ : face_varying_channel_(face_varying_channel),
+ src_face_varying_desc_(0, face_varying_width, face_varying_width),
+ patch_table_(patch_table),
+ evaluator_cache_(evaluator_cache),
+ device_context_(device_context) {
+ using OpenSubdiv::Osd::convertToCompatibleStencilTable;
+ num_coarse_face_varying_vertices_ =
+ face_varying_stencils->GetNumControlVertices();
+ const int num_total_face_varying_vertices =
+ face_varying_stencils->GetNumControlVertices() +
+ face_varying_stencils->GetNumStencils();
+ src_face_varying_data_ =
+ EVAL_VERTEX_BUFFER::Create(2,
+ num_total_face_varying_vertices,
+ device_context);
+ face_varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+ face_varying_stencils, device_context_);
+ }
+
+ ~FaceVaryingVolatileEval() {
+ delete src_face_varying_data_;
+ delete face_varying_stencils_;
+ }
+
+ void updateData(const float* src, int start_vertex, int num_vertices) {
+ src_face_varying_data_->UpdateData(src,
+ start_vertex,
+ num_vertices,
+ device_context_);
+ }
+
+ void refine() {
+ BufferDescriptor dst_face_varying_desc = src_face_varying_desc_;
+ dst_face_varying_desc.offset += num_coarse_face_varying_vertices_ *
+ src_face_varying_desc_.stride;
+ const EVALUATOR* eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
+ evaluator_cache_,
+ src_face_varying_desc_,
+ dst_face_varying_desc,
+ device_context_);
+ EVALUATOR::EvalStencils(src_face_varying_data_, src_face_varying_desc_,
+ src_face_varying_data_, dst_face_varying_desc,
+ face_varying_stencils_,
+ eval_instance,
+ device_context_);
+ }
+
+ void evalPatch(const PatchCoord& patch_coord, float face_varying[2]) {
+ StackAllocatedBuffer<2, 1> face_varying_data;
+ BufferDescriptor face_varying_desc(0, 2, 2);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR* eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_face_varying_desc_,
+ face_varying_desc,
+ device_context_);
+ EVALUATOR::EvalPatchesFaceVarying(
+ src_face_varying_data_, src_face_varying_desc_,
+ &face_varying_data, face_varying_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_,
+ face_varying_channel_,
+ eval_instance,
+ device_context_);
+ const float* refined_face_varying = face_varying_data.BindCpuBuffer();
+ memcpy(face_varying, refined_face_varying, sizeof(float) * 2);
+ }
+
+ protected:
+ int face_varying_channel_;
+
+ BufferDescriptor src_face_varying_desc_;
+
+ int num_coarse_face_varying_vertices_;
+ EVAL_VERTEX_BUFFER* src_face_varying_data_;
+ const STENCIL_TABLE* face_varying_stencils_;
+
+ // NOTE: We reference this, do not own it.
+ PATCH_TABLE* patch_table_;
+
+ EvaluatorCache* evaluator_cache_;
+ DEVICE_CONTEXT* device_context_;
+};
+
+// Volatile evaluator which can be used from threads.
+//
+// TODO(sergey): Make it possible to evaluate coordinates in chunks.
+// TODO(sergey): Make it possible to evaluate multiple face varying layers.
+// (or maybe, it's cheap to create new evaluator for existing
+// topology to evaluate all needed face varying layers?)
+template <typename SRC_VERTEX_BUFFER,
+ typename EVAL_VERTEX_BUFFER,
+ typename STENCIL_TABLE,
+ typename PATCH_TABLE,
+ typename EVALUATOR,
+ typename DEVICE_CONTEXT = void>
+class VolatileEvalOutput {
+ public:
+ typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
+ typedef FaceVaryingVolatileEval<EVAL_VERTEX_BUFFER,
+ STENCIL_TABLE,
+ PATCH_TABLE,
+ EVALUATOR,
+ DEVICE_CONTEXT> FaceVaryingEval;
+
+ VolatileEvalOutput(
+ const StencilTable* vertex_stencils,
+ const StencilTable* varying_stencils,
+ const vector<const StencilTable*>& all_face_varying_stencils,
+ const int face_varying_width,
+ const PatchTable* patch_table,
+ EvaluatorCache* evaluator_cache = NULL,
+ DEVICE_CONTEXT* device_context = NULL)
+ : src_desc_(0, 3, 3),
+ src_varying_desc_(0, 3, 3),
+ face_varying_width_(face_varying_width),
+ evaluator_cache_(evaluator_cache),
+ device_context_(device_context) {
+ // Total number of vertices = coarse points + refined points + local points.
+ int num_total_vertices = vertex_stencils->GetNumControlVertices() +
+ vertex_stencils->GetNumStencils();
+ num_coarse_vertices_ = vertex_stencils->GetNumControlVertices();
+ using OpenSubdiv::Osd::convertToCompatibleStencilTable;
+ src_data_ =
+ SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
+ src_varying_data_ =
+ SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
+ patch_table_ = PATCH_TABLE::Create(patch_table, device_context_);
+ patch_coords_ = NULL;
+ vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+ vertex_stencils, device_context_);
+ varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+ varying_stencils, device_context_);
+ // Create evaluators for every face varying channel.
+ face_varying_evaluators.reserve(all_face_varying_stencils.size());
+ int face_varying_channel = 0;
+ foreach (const StencilTable* face_varying_stencils,
+ all_face_varying_stencils) {
+ face_varying_evaluators.push_back(
+ new FaceVaryingEval(face_varying_channel,
+ face_varying_stencils,
+ face_varying_width,
+ patch_table_,
+ evaluator_cache_,
+ device_context_));
+ ++face_varying_channel;
+ }
+ }
+
+ ~VolatileEvalOutput() {
+ delete src_data_;
+ delete src_varying_data_;
+ delete patch_table_;
+ delete vertex_stencils_;
+ delete varying_stencils_;
+ foreach (FaceVaryingEval* face_varying_evaluator, face_varying_evaluators) {
+ delete face_varying_evaluator;
+ }
+ }
+
+ // TODO(sergey): Implement binding API.
+
+ void updateData(const float* src, int start_vertex, int num_vertices) {
+ src_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
+ }
+
+ void updateVaryingData(const float* src, int start_vertex, int num_vertices) {
+ src_varying_data_->UpdateData(src,
+ start_vertex,
+ num_vertices,
+ device_context_);
+ }
+
+ void updateFaceVaryingData(const int face_varying_channel,
+ const float* src,
+ int start_vertex,
+ int num_vertices) {
+ assert(face_varying_channel >= 0);
+ assert(face_varying_channel < face_varying_evaluators.size());
+ face_varying_evaluators[face_varying_channel]->updateData(
+ src, start_vertex, num_vertices);
+ }
+
+ bool hasVaryingData() const {
+ // return varying_stencils_ != NULL;
+ // TODO(sergey): Check this based on actual topology.
+ return false;
+ }
+
+ bool hasFaceVaryingData() const {
+ return face_varying_evaluators.size() != 0;
+ }
+
+ void refine() {
+ // Evaluate vertex positions.
+ BufferDescriptor dst_desc = src_desc_;
+ dst_desc.offset += num_coarse_vertices_ * src_desc_.stride;
+ const EVALUATOR* eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ dst_desc,
+ device_context_);
+ EVALUATOR::EvalStencils(src_data_, src_desc_,
+ src_data_, dst_desc,
+ vertex_stencils_,
+ eval_instance,
+ device_context_);
+ // Evaluate varying data.
+ if (hasVaryingData()) {
+ BufferDescriptor dst_varying_desc = src_varying_desc_;
+ dst_varying_desc.offset +=
+ num_coarse_vertices_ * src_varying_desc_.stride;
+ eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
+ evaluator_cache_,
+ src_varying_desc_,
+ dst_varying_desc,
+ device_context_);
+ EVALUATOR::EvalStencils(src_varying_data_, src_varying_desc_,
+ src_varying_data_, dst_varying_desc,
+ varying_stencils_,
+ eval_instance, device_context_);
+ }
+ // Evaluate face-varying data.
+ if (hasFaceVaryingData()) {
+ foreach (FaceVaryingEval* face_varying_evaluator,
+ face_varying_evaluators) {
+ face_varying_evaluator->refine();
+ }
+ }
+ }
+
+ void evalPatchCoord(const PatchCoord& patch_coord, float P[3]) {
+ StackAllocatedBuffer<6, 1> vertex_data;
+ // TODO(sergey): Varying data is interleaved in vertex array, so need to
+ // adjust stride if there is a varying data.
+ // BufferDescriptor vertex_desc(0, 3, 6);
+ BufferDescriptor vertex_desc(0, 3, 3);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR* eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ vertex_desc,
+ device_context_);
+ EVALUATOR::EvalPatches(src_data_,
+ src_desc_,
+ &vertex_data,
+ vertex_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_,
+ eval_instance,
+ device_context_);
+ const float* refined_vertices = vertex_data.BindCpuBuffer();
+ memcpy(P, refined_vertices, sizeof(float) * 3);
+ }
+
+ void evalPatchesWithDerivatives(const PatchCoord& patch_coord,
+ float P[3],
+ float dPdu[3], float dPdv[3]) {
+ StackAllocatedBuffer<6, 1> vertex_data, derivatives;
+ // TODO(sergey): Varying data is interleaved in vertex array, so need to
+ // adjust stride if there is a varying data.
+ // BufferDescriptor vertex_desc(0, 3, 6);
+ BufferDescriptor vertex_desc(0, 3, 3);
+ BufferDescriptor du_desc(0, 3, 6), dv_desc(3, 3, 6);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR* eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_desc_,
+ vertex_desc,
+ du_desc, dv_desc,
+ device_context_);
+ EVALUATOR::EvalPatches(src_data_, src_desc_,
+ &vertex_data, vertex_desc,
+ &derivatives, du_desc,
+ &derivatives, dv_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_,
+ eval_instance,
+ device_context_);
+ const float* refined_vertices = vertex_data.BindCpuBuffer();
+ memcpy(P, refined_vertices, sizeof(float) * 3);
+ if (dPdu != NULL || dPdv != NULL) {
+ const float* refined_derivatives = derivatives.BindCpuBuffer();
+ if (dPdu != NULL) {
+ memcpy(dPdu, refined_derivatives, sizeof(float) * 3);
+ }
+ if (dPdv != NULL) {
+ memcpy(dPdv, refined_derivatives + 3, sizeof(float) * 3);
+ }
+ }
+ }
+
+ void evalPatchVarying(const PatchCoord& patch_coord, float varying[3]) {
+ StackAllocatedBuffer<6, 1> varying_data;
+ BufferDescriptor varying_desc(3, 3, 6);
+ SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+ const EVALUATOR* eval_instance =
+ OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+ src_varying_desc_,
+ varying_desc,
+ device_context_);
+ EVALUATOR::EvalPatchesVarying(src_varying_data_, src_varying_desc_,
+ &varying_data, varying_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_,
+ eval_instance,
+ device_context_);
+ const float* refined_varying = varying_data.BindCpuBuffer();
+ memcpy(varying, refined_varying, sizeof(float) * 3);
+ }
+
+ void evalPatchFaceVarying(const int face_varying_channel,
+ const PatchCoord& patch_coord,
+ float face_varying[2]) {
+ assert(face_varying_channel >= 0);
+ assert(face_varying_channel < face_varying_evaluators.size());
+ face_varying_evaluators[face_varying_channel]->evalPatch(
+ patch_coord, face_varying);
+ }
+
+ private:
+ SRC_VERTEX_BUFFER* src_data_;
+ SRC_VERTEX_BUFFER* src_varying_data_;
+ PatchCoordBuffer* patch_coords_;
+ PATCH_TABLE* patch_table_;
+ BufferDescriptor src_desc_;
+ BufferDescriptor src_varying_desc_;
+
+ int num_coarse_vertices_;
+
+ const STENCIL_TABLE* vertex_stencils_;
+ const STENCIL_TABLE* varying_stencils_;
+
+ int face_varying_width_;
+ vector<FaceVaryingEval*> face_varying_evaluators;
+
+ EvaluatorCache* evaluator_cache_;
+ DEVICE_CONTEXT* device_context_;
+};
+
+} // namespace
+
+// Note: Define as a class instead of typedcef to make it possible
+// to have anonymous class in opensubdiv_evaluator_internal.h
+class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
+ CpuVertexBuffer,
+ StencilTable,
+ CpuPatchTable,
+ CpuEvaluator> {
+ public:
+ CpuEvalOutput(const StencilTable* vertex_stencils,
+ const StencilTable* varying_stencils,
+ const vector<const StencilTable*>& all_face_varying_stencils,
+ const int face_varying_width,
+ const PatchTable* patch_table,
+ EvaluatorCache* evaluator_cache = NULL)
+ : VolatileEvalOutput<CpuVertexBuffer,
+ CpuVertexBuffer,
+ StencilTable,
+ CpuPatchTable,
+ CpuEvaluator> (vertex_stencils,
+ varying_stencils,
+ all_face_varying_stencils,
+ face_varying_width,
+ patch_table,
+ evaluator_cache) {
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Evaluator wrapper for anonymous API.
+
+CpuEvalOutputAPI::CpuEvalOutputAPI(CpuEvalOutput* implementation,
+ OpenSubdiv::Far::PatchMap* patch_map)
+ : implementation_(implementation),
+ patch_map_(patch_map) {
+}
+
+CpuEvalOutputAPI::~CpuEvalOutputAPI() {
+ delete implementation_;
+}
+
+void CpuEvalOutputAPI::setCoarsePositions(const float* positions,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ implementation_->updateData(positions, start_vertex_index, num_vertices);
+}
+
+void CpuEvalOutputAPI::setVaryingData(const float* varying_data,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ implementation_->updateVaryingData(varying_data,
+ start_vertex_index,
+ num_vertices);
+}
+
+void CpuEvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
+ const float* face_varying_data,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ implementation_->updateFaceVaryingData(face_varying_channel,
+ face_varying_data,
+ start_vertex_index,
+ num_vertices);
+}
+
+void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ const unsigned char* current_buffer = (unsigned char *)buffer;
+ current_buffer += start_offset;
+ for (int i = 0; i < num_vertices; ++i) {
+ const int current_vertex_index = start_vertex_index + i;
+ implementation_->updateData(reinterpret_cast<const float*>(current_buffer),
+ current_vertex_index, 1);
+ current_buffer += stride;
+ }
+}
+
+void CpuEvalOutputAPI::setVaryingDataFromBuffer(
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ const unsigned char* current_buffer = (unsigned char *)buffer;
+ current_buffer += start_offset;
+ for (int i = 0; i < num_vertices; ++i) {
+ const int current_vertex_index = start_vertex_index + i;
+ implementation_->updateVaryingData(
+ reinterpret_cast<const float*>(current_buffer),
+ current_vertex_index, 1);
+ current_buffer += stride;
+ }
+}
+
+void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(
+ const int face_varying_channel,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices) {
+ // TODO(sergey): Add sanity check on indices.
+ const unsigned char* current_buffer = (unsigned char *)buffer;
+ current_buffer += start_offset;
+ for (int i = 0; i < num_vertices; ++i) {
+ const int current_vertex_index = start_vertex_index + i;
+ implementation_->updateFaceVaryingData(
+ face_varying_channel,
+ reinterpret_cast<const float*>(current_buffer),
+ current_vertex_index, 1);
+ current_buffer += stride;
+ }
+}
+
+void CpuEvalOutputAPI::refine() {
+ implementation_->refine();
+}
+
+void CpuEvalOutputAPI::evaluateLimit(const int ptex_face_index,
+ float face_u, float face_v,
+ float P[3], float dPdu[3], float dPdv[3]) {
+ assert(face_u >= 0.0f);
+ assert(face_u <= 1.0f);
+ assert(face_v >= 0.0f);
+ assert(face_v <= 1.0f);
+ const PatchTable::PatchHandle* handle =
+ patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ if (dPdu != NULL || dPdv != NULL) {
+ implementation_->evalPatchesWithDerivatives(patch_coord, P, dPdu, dPdv);
+ } else {
+ implementation_->evalPatchCoord(patch_coord, P);
+ }}
+
+void CpuEvalOutputAPI::evaluateVarying(const int ptex_face_index,
+ float face_u, float face_v,
+ float varying[3]) {
+ assert(face_u >= 0.0f);
+ assert(face_u <= 1.0f);
+ assert(face_v >= 0.0f);
+ assert(face_v <= 1.0f);
+ const PatchTable::PatchHandle* handle =
+ patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ implementation_->evalPatchVarying(patch_coord, varying);
+}
+
+void CpuEvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float face_varying[2]) {
+ assert(face_u >= 0.0f);
+ assert(face_u <= 1.0f);
+ assert(face_v >= 0.0f);
+ assert(face_v <= 1.0f);
+ const PatchTable::PatchHandle* handle =
+ patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ implementation_->evalPatchFaceVarying(
+ face_varying_channel, patch_coord, face_varying);
+}
+
+} // namespace opensubdiv_capi
+
+OpenSubdiv_EvaluatorInternal::OpenSubdiv_EvaluatorInternal()
+ : eval_output(NULL),
+ patch_map(NULL),
+ patch_table(NULL) {
+}
+
+OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal() {
+ delete eval_output;
+ delete patch_map;
+ delete patch_table;
+}
+
+OpenSubdiv_EvaluatorInternal* openSubdiv_createEvaluatorInternal(
+ OpenSubdiv_TopologyRefiner* topology_refiner) {
+ using opensubdiv_capi::vector;
+ TopologyRefiner* refiner = topology_refiner->internal->osd_topology_refiner;
+ if (refiner == NULL) {
+ // Happens on bad topology.
+ return NULL;
+ }
+ // TODO(sergey): Base this on actual topology.
+ // const bool bas_varying_data = false;
+ const int num_face_varying_channels = refiner->GetNumFVarChannels();
+ const bool has_face_varying_data = (num_face_varying_channels != 0);
+ const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
+ // TODO(sergey): Query from topology refiner.
+ const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
+ // Refine the topology with given settings.
+ // TODO(sergey): What if topology is already refined?
+ if (is_adaptive) {
+ TopologyRefiner::AdaptiveOptions options(level);
+ options.considerFVarChannels = has_face_varying_data;
+ options.useInfSharpPatch = true;
+ refiner->RefineAdaptive(options);
+ } else {
+ TopologyRefiner::UniformOptions options(level);
+ refiner->RefineUniform(options);
+ }
+ // Generate stencil table to update the bi-cubic patches control vertices
+ // after they have been re-posed (both for vertex & varying interpolation).
+ //
+ // Vertex stencils.
+ StencilTableFactory::Options vertex_stencil_options;
+ vertex_stencil_options.generateOffsets = true;
+ vertex_stencil_options.generateIntermediateLevels = is_adaptive;
+ const StencilTable* vertex_stencils =
+ StencilTableFactory::Create(*refiner, vertex_stencil_options);
+ // Varying stencils.
+ //
+ // TODO(sergey): Seems currently varying stencils are always required in
+ // OpenSubdiv itself.
+ const StencilTable* varying_stencils = NULL;
+ StencilTableFactory::Options varying_stencil_options;
+ varying_stencil_options.generateOffsets = true;
+ varying_stencil_options.generateIntermediateLevels = is_adaptive;
+ varying_stencil_options.interpolationMode =
+ StencilTableFactory::INTERPOLATE_VARYING;
+ varying_stencils =
+ StencilTableFactory::Create(*refiner, varying_stencil_options);
+ // Face warying stencil.
+vector<const StencilTable*> all_face_varying_stencils;
+#ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
+ all_face_varying_stencils.reserve(num_face_varying_channels);
+ for (int face_varying_channel = 0;
+ face_varying_channel < num_face_varying_channels;
+ ++face_varying_channel) {
+ StencilTableFactory::Options face_varying_stencil_options;
+ face_varying_stencil_options.generateOffsets = true;
+ face_varying_stencil_options.generateIntermediateLevels = is_adaptive;
+ face_varying_stencil_options.interpolationMode =
+ StencilTableFactory::INTERPOLATE_FACE_VARYING;
+ face_varying_stencil_options.fvarChannel = face_varying_channel;
+ all_face_varying_stencils.push_back(
+ StencilTableFactory::Create(*refiner, face_varying_stencil_options));
+ }
+#endif
+ // Generate bi-cubic patch table for the limit surface.
+ // TODO(sergey): Ideally we would want to expose end-cap settings via
+ // C-API to make it more generic. Currently it matches old Blender's
+ // subsurf code.
+ PatchTableFactory::Options patch_options(level);
+ patch_options.SetEndCapType(PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
+ patch_options.useInfSharpPatch = true;
+ patch_options.generateFVarTables = has_face_varying_data;
+ patch_options.generateFVarLegacyLinearPatches = false;
+ const PatchTable* patch_table = PatchTableFactory::Create(
+ *refiner, patch_options);
+ // Append local points stencils.
+ const StencilTable* local_point_stencil_table =
+ patch_table->GetLocalPointStencilTable();
+ if (local_point_stencil_table != NULL) {
+ const StencilTable* table =
+ StencilTableFactory::AppendLocalPointStencilTable(
+ *refiner, vertex_stencils, local_point_stencil_table);
+ delete vertex_stencils;
+ vertex_stencils = table;
+ }
+ const StencilTable* local_point_varying_stencil_table =
+ patch_table->GetLocalPointVaryingStencilTable();
+ if (local_point_varying_stencil_table != NULL) {
+ const StencilTable* table =
+ StencilTableFactory::AppendLocalPointStencilTable(
+ *refiner, varying_stencils, local_point_varying_stencil_table);
+ delete varying_stencils;
+ varying_stencils = table;
+ }
+#ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
+ for (int face_varying_channel = 0;
+ face_varying_channel < num_face_varying_channels;
+ ++face_varying_channel) {
+ const StencilTable* table =
+ StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
+ *refiner,
+ all_face_varying_stencils[face_varying_channel],
+ patch_table->GetLocalPointFaceVaryingStencilTable(
+ face_varying_channel),
+ face_varying_channel);
+ if (table != NULL) {
+ delete all_face_varying_stencils[face_varying_channel];
+ all_face_varying_stencils[face_varying_channel] = table;
+ }
+ }
+#endif
+ // Create OpenSubdiv's CPU side evaluator.
+ // TODO(sergey): Make it possible to use different evaluators.
+ opensubdiv_capi::CpuEvalOutput* eval_output =
+ new opensubdiv_capi::CpuEvalOutput(vertex_stencils,
+ varying_stencils,
+ all_face_varying_stencils,
+ 2,
+ patch_table);
+ OpenSubdiv::Far::PatchMap* patch_map = new PatchMap(*patch_table);
+ // Wrap everything we need into an object which we control from our side.
+ OpenSubdiv_EvaluatorInternal* evaluator_descr;
+ evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorInternal);
+ evaluator_descr->eval_output =
+ new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
+ evaluator_descr->patch_map = patch_map;
+ evaluator_descr->patch_table = patch_table;
+ // TOOD(sergey): Look into whether we've got duplicated stencils arrays.
+ delete vertex_stencils;
+ delete varying_stencils;
+ foreach (const StencilTable* table, all_face_varying_stencils) {
+ delete table;
+ }
+ return evaluator_descr;
+}
+
+void openSubdiv_deleteEvaluatorInternal(
+ OpenSubdiv_EvaluatorInternal* evaluator) {
+ OBJECT_GUARDED_DELETE(evaluator, OpenSubdiv_EvaluatorInternal);
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
new file mode 100644
index 00000000000..7d9178f38dc
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
@@ -0,0 +1,137 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_EVALUATOR_INTERNAL_H_
+#define OPENSUBDIV_EVALUATOR_INTERNAL_H_
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/far/patchMap.h>
+#include <opensubdiv/far/patchTable.h>
+
+struct OpenSubdiv_TopologyRefiner;
+
+namespace opensubdiv_capi {
+
+// Anonymous forward declaration of actual evaluator implementation.
+class CpuEvalOutput;
+
+// Wrapper around implementaiton, which defines API which we are capable to
+// provide over the implementation.
+//
+// TODO(sergey): It is almost the same as C-API object, so ideally need to
+// merge them somehow, but how to do this and keep files with all the templates
+// and such separate?
+class CpuEvalOutputAPI {
+ public:
+ // NOTE: API object becomes an owner of evaluator. Patch we are referencing.
+ CpuEvalOutputAPI(CpuEvalOutput* implementation,
+ OpenSubdiv::Far::PatchMap* patch_map);
+ ~CpuEvalOutputAPI();
+
+ // Set coarse positions from a continuous array of coordinates.
+ void setCoarsePositions(const float* positions,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set varying data from a continuous array of data.
+ void setVaryingData(const float* varying_data,
+ const int start_vertex_index, const int num_vertices);
+ // Set face varying data from a continuous array of data.
+ //
+ // TODO(sergey): Find a better name for vertex here. It is not the vertex of
+ // geometry, but a vertex of UV map.
+ void setFaceVaryingData(const int face_varying_channel,
+ const float* varying_data,
+ const int start_vertex_index, const int num_vertices);
+
+ // Set coarse vertex position from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ void setCoarsePositionsFromBuffer(const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set varying data from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ void setVaryingDataFromBuffer(const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set face varying data from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ //
+ // TODO(sergey): Find a better name for vertex here. It is not the vertex of
+ // geometry, but a vertex of UV map.
+ void setFaceVaryingDataFromBuffer(const int face_varying_channel,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+
+ // Refine after coarse positions update.
+ void refine();
+
+ // Evaluate given ptex face at given bilinear coordinate.
+ // If derivatives are NULL, they will not be evaluated.
+ void evaluateLimit(const int ptex_face_index,
+ float face_u, float face_v,
+ float P[3], float dPdu[3], float dPdv[3]);
+
+ // Evaluate varying data at a given bilinear coordinate of given ptex face.
+ void evaluateVarying(const int ptes_face_index,
+ float face_u, float face_v,
+ float varying[3]);
+
+ // Evaluate facee-varying data at a given bilinear coordinate of given
+ // ptex face.
+ void evaluateFaceVarying(const int face_varying_channel,
+ const int ptes_face_index,
+ float face_u, float face_v,
+ float face_varying[2]);
+
+ protected:
+ CpuEvalOutput* implementation_;
+ OpenSubdiv::Far::PatchMap* patch_map_;
+};
+
+} // namespace opensubdiv_capi
+
+struct OpenSubdiv_EvaluatorInternal {
+ public:
+ OpenSubdiv_EvaluatorInternal();
+ ~OpenSubdiv_EvaluatorInternal();
+
+ opensubdiv_capi::CpuEvalOutputAPI* eval_output;
+ const OpenSubdiv::Far::PatchMap* patch_map;
+ const OpenSubdiv::Far::PatchTable* patch_table;
+};
+
+OpenSubdiv_EvaluatorInternal* openSubdiv_createEvaluatorInternal(
+ struct OpenSubdiv_TopologyRefiner* topology_refiner);
+
+void openSubdiv_deleteEvaluatorInternal(
+ OpenSubdiv_EvaluatorInternal* evaluator);
+
+#endif // OPENSUBDIV_EVALUATOR_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc
new file mode 100644
index 00000000000..34d27591d0b
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc
@@ -0,0 +1,287 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+// Contributor(s): Brecht van Lommel
+
+#include "opensubdiv_gl_mesh_capi.h"
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/osd/glMesh.h>
+#include <opensubdiv/osd/glPatchTable.h>
+
+using OpenSubdiv::Far::StencilTable;
+using OpenSubdiv::Osd::GLMeshInterface;
+using OpenSubdiv::Osd::GLPatchTable;
+using OpenSubdiv::Osd::Mesh;
+using OpenSubdiv::Osd::MeshBitset;
+
+// CPU backend.
+#include <opensubdiv/osd/cpuEvaluator.h>
+#include <opensubdiv/osd/cpuGLVertexBuffer.h>
+using OpenSubdiv::Osd::CpuGLVertexBuffer;
+using OpenSubdiv::Osd::CpuEvaluator;
+typedef Mesh<CpuGLVertexBuffer,
+ StencilTable,
+ CpuEvaluator,
+ GLPatchTable> OsdCpuMesh;
+// OpenMP backend.
+#ifdef OPENSUBDIV_HAS_OPENMP
+# include <opensubdiv/osd/ompEvaluator.h>
+using OpenSubdiv::Osd::OmpEvaluator;
+typedef Mesh<CpuGLVertexBuffer,
+ StencilTable,
+ OmpEvaluator,
+ GLPatchTable> OsdOmpMesh;
+#endif
+// OpenCL backend.
+#ifdef OPENSUBDIV_HAS_OPENCL
+# include <opensubdiv/osd/clEvaluator.h>
+# include <opensubdiv/osd/clGLVertexBuffer.h>
+# include "opensubdiv_device_context_opencl.h"
+using OpenSubdiv::Osd::CLEvaluator;
+using OpenSubdiv::Osd::CLGLVertexBuffer;
+using OpenSubdiv::Osd::CLStencilTable;
+/* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
+typedef Mesh<CLGLVertexBuffer,
+ CLStencilTable,
+ CLEvaluator,
+ GLPatchTable,
+ CLDeviceContext> OsdCLMesh;
+static CLDeviceContext g_cl_device_context;
+#endif
+// CUDA backend.
+#ifdef OPENSUBDIV_HAS_CUDA
+# include <opensubdiv/osd/cudaEvaluator.h>
+# include <opensubdiv/osd/cudaGLVertexBuffer.h>
+# include "opensubdiv_device_context_cuda.h"
+using OpenSubdiv::Osd::CudaEvaluator;
+using OpenSubdiv::Osd::CudaGLVertexBuffer;
+using OpenSubdiv::Osd::CudaStencilTable;
+typedef Mesh<CudaGLVertexBuffer,
+ CudaStencilTable,
+ CudaEvaluator,
+ GLPatchTable> OsdCudaMesh;
+static CudaDeviceContext g_cuda_device_context;
+#endif
+// Transform feedback backend.
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+# include <opensubdiv/osd/glVertexBuffer.h>
+# include <opensubdiv/osd/glXFBEvaluator.h>
+using OpenSubdiv::Osd::GLXFBEvaluator;
+using OpenSubdiv::Osd::GLStencilTableTBO;
+using OpenSubdiv::Osd::GLVertexBuffer;
+typedef Mesh<GLVertexBuffer,
+ GLStencilTableTBO,
+ GLXFBEvaluator,
+ GLPatchTable> OsdGLSLTransformFeedbackMesh;
+#endif
+// GLSL compute backend.
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+# include <opensubdiv/osd/glComputeEvaluator.h>
+# include <opensubdiv/osd/glVertexBuffer.h>
+using OpenSubdiv::Osd::GLComputeEvaluator;
+using OpenSubdiv::Osd::GLStencilTableSSBO;
+using OpenSubdiv::Osd::GLVertexBuffer;
+typedef Mesh<GLVertexBuffer,
+ GLStencilTableSSBO,
+ GLComputeEvaluator,
+ GLPatchTable> OsdGLSLComputeMesh;
+#endif
+
+#include <string>
+#include <vector>
+
+#include "MEM_guardedalloc.h"
+
+#include "opensubdiv_topology_refiner_capi.h"
+#include "internal/opensubdiv_gl_mesh_draw.h"
+#include "internal/opensubdiv_gl_mesh_fvar.h"
+#include "internal/opensubdiv_gl_mesh_internal.h"
+#include "internal/opensubdiv_topology_refiner_internal.h"
+
+namespace {
+
+GLMeshInterface* createGLMeshInterface(
+ OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const MeshBitset& bits,
+ const int num_vertex_elements,
+ const int num_varying_elements,
+ const int level,
+ eOpenSubdivEvaluator evaluator_type) {
+ GLMeshInterface* mesh = NULL;
+ switch (evaluator_type) {
+#define CHECK_EVALUATOR_TYPE(type, class) \
+ case OPENSUBDIV_EVALUATOR_##type: \
+ mesh = new class(topology_refiner, \
+ num_vertex_elements, \
+ num_varying_elements, \
+ level, \
+ bits); \
+ break;
+
+#define CHECK_EVALUATOR_TYPE_STUB(type) \
+ case OPENSUBDIV_EVALUATOR_##type: \
+ mesh = NULL; \
+ break;
+
+ CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
+#ifdef OPENSUBDIV_HAS_OPENMP
+ CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
+#else
+ CHECK_EVALUATOR_TYPE_STUB(OPENMP)
+#endif
+#ifdef OPENSUBDIV_HAS_OPENCL
+ CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
+#else
+ CHECK_EVALUATOR_TYPE_STUB(OPENCL)
+#endif
+#ifdef OPENSUBDIV_HAS_CUDA
+ CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
+#else
+ CHECK_EVALUATOR_TYPE_STUB(CUDA)
+#endif
+#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
+ CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
+#else
+ CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
+#endif
+#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
+ CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
+#else
+ CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
+#endif
+
+#undef CHECK_EVALUATOR_TYPE
+#undef CHECK_EVALUATOR_TYPE_STUB
+ }
+ return mesh;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GLMesh structure "methods".
+
+opensubdiv_capi::GLMeshFVarData* createFVarData(
+ OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ GLMeshInterface* mesh,
+ const float *fvar_src_buffer) {
+ using opensubdiv_capi::GLMeshFVarData;
+ GLMeshFVarData* fvar_data = new GLMeshFVarData();
+ fvar_data->create(topology_refiner,
+ mesh->GetFarPatchTable(),
+ 2,
+ fvar_src_buffer);
+ return fvar_data;
+}
+
+unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh* gl_mesh) {
+ return gl_mesh->internal->mesh_interface
+ ->GetPatchTable()
+ ->GetPatchIndexBuffer();
+}
+
+void bindVertexBuffer(OpenSubdiv_GLMesh* gl_mesh) {
+ gl_mesh->internal->mesh_interface->BindVertexBuffer();
+}
+
+void setCoarsePositions(OpenSubdiv_GLMesh* gl_mesh,
+ const float* positions,
+ const int start_vertex,
+ const int num_vertices) {
+ gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions,
+ start_vertex,
+ num_vertices);
+}
+
+void refine(OpenSubdiv_GLMesh* gl_mesh) {
+ gl_mesh->internal->mesh_interface->Refine();
+}
+
+void synchronize(struct OpenSubdiv_GLMesh* gl_mesh) {
+ gl_mesh->internal->mesh_interface->Synchronize();
+}
+
+void assignFunctionPointers(OpenSubdiv_GLMesh* gl_mesh) {
+ gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
+ gl_mesh->bindVertexBuffer = bindVertexBuffer;
+ gl_mesh->setCoarsePositions = setCoarsePositions;
+ gl_mesh->refine = refine;
+ gl_mesh->synchronize = synchronize;
+
+ gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
+ gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
+}
+
+} // namespace
+
+struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
+ OpenSubdiv_TopologyRefiner* topology_refiner,
+ eOpenSubdivEvaluator evaluator_type) {
+ using OpenSubdiv::Far::TopologyRefiner;
+ TopologyRefiner* osd_topology_refiner =
+ topology_refiner->internal->osd_topology_refiner;
+ // TODO(sergey): Query this from refiner.
+ const bool is_adaptive = false;
+ MeshBitset bits;
+ bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
+ bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
+ bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
+ bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
+ bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
+ const int num_vertex_elements = 3;
+ const int num_varying_elements = 3;
+ GLMeshInterface* mesh = createGLMeshInterface(
+ osd_topology_refiner,
+ bits,
+ num_vertex_elements,
+ num_varying_elements,
+ osd_topology_refiner->GetMaxLevel(),
+ evaluator_type);
+ if (mesh == NULL) {
+ return NULL;
+ }
+ OpenSubdiv_GLMesh* gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
+ assignFunctionPointers(gl_mesh);
+ gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
+ gl_mesh->internal->evaluator_type = evaluator_type;
+ gl_mesh->internal->mesh_interface = mesh;
+ // Face-varying support.
+ // TODO(sergey): This part needs to be re-done.
+ if (osd_topology_refiner->GetNumFVarChannels() > 0) {
+ // TODO(sergey): This is a temporary stub to get things compiled. Need
+ // to store base level UVs somewhere else.
+ std::vector<float> uvs;
+ std::vector<float> fvar_data_buffer;
+ opensubdiv_capi::interpolateFVarData(*osd_topology_refiner,
+ uvs,
+ &fvar_data_buffer);
+ gl_mesh->internal->fvar_data = createFVarData(osd_topology_refiner,
+ mesh,
+ &fvar_data_buffer[0]);
+ } else {
+ gl_mesh->internal->fvar_data = NULL;
+ }
+ return gl_mesh;
+}
+
+void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh) {
+ delete gl_mesh->internal;
+ OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc
new file mode 100644
index 00000000000..0d2f8dc9842
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc
@@ -0,0 +1,587 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_gl_mesh_draw.h"
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <GL/glew.h>
+#include <cmath>
+#include <cstdio>
+
+#include <opensubdiv/osd/glMesh.h>
+
+#ifdef OPENSUBDIV_HAS_CUDA
+# include <opensubdiv/osd/cudaGLVertexBuffer.h>
+#endif // OPENSUBDIV_HAS_CUDA
+
+#include <opensubdiv/osd/cpuEvaluator.h>
+#include <opensubdiv/osd/cpuGLVertexBuffer.h>
+
+#include "internal/opensubdiv_gl_mesh_fvar.h"
+#include "internal/opensubdiv_gl_mesh_internal.h"
+#include "opensubdiv_capi.h"
+#include "opensubdiv_gl_mesh_capi.h"
+
+using OpenSubdiv::Osd::GLMeshInterface;
+
+extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
+extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
+extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
+
+// TODO(sergey): Those are a bit of bad level calls :S
+extern "C" {
+void copy_m3_m3(float m1[3][3], float m2[3][3]);
+void copy_m3_m4(float m1[3][3], float m2[4][4]);
+void adjoint_m3_m3(float m1[3][3], float m[3][3]);
+float determinant_m3_array(float m[3][3]);
+bool invert_m3_m3(float m1[3][3], float m2[3][3]);
+bool invert_m3(float m[3][3]);
+void transpose_m3(float mat[3][3]);
+}
+
+#define MAX_LIGHTS 8
+#define SUPPORT_COLOR_MATERIAL
+
+typedef struct Light {
+ float position[4];
+ float ambient[4];
+ float diffuse[4];
+ float specular[4];
+ float spot_direction[4];
+#ifdef SUPPORT_COLOR_MATERIAL
+ float constant_attenuation;
+ float linear_attenuation;
+ float quadratic_attenuation;
+ float spot_cutoff;
+ float spot_exponent;
+ float spot_cos_cutoff;
+ float pad, pad2;
+#endif
+} Light;
+
+typedef struct Lighting {
+ Light lights[MAX_LIGHTS];
+ int num_enabled;
+} Lighting;
+
+typedef struct Transform {
+ float projection_matrix[16];
+ float model_view_matrix[16];
+ float normal_matrix[9];
+} Transform;
+
+static bool g_use_osd_glsl = false;
+static int g_active_uv_index = 0;
+
+static GLuint g_flat_fill_solid_program = 0;
+static GLuint g_flat_fill_texture2d_program = 0;
+static GLuint g_smooth_fill_solid_program = 0;
+static GLuint g_smooth_fill_texture2d_program = 0;
+
+static GLuint g_flat_fill_solid_shadeless_program = 0;
+static GLuint g_flat_fill_texture2d_shadeless_program = 0;
+static GLuint g_smooth_fill_solid_shadeless_program = 0;
+static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
+
+static GLuint g_wireframe_program = 0;
+
+static GLuint g_lighting_ub = 0;
+static Lighting g_lighting_data;
+static Transform g_transform;
+
+namespace {
+
+GLuint compileShader(GLenum shaderType,
+ const char* version,
+ const char* define,
+ const char* source) {
+ const char* sources[] = {
+ version, define,
+#ifdef SUPPORT_COLOR_MATERIAL
+ "#define SUPPORT_COLOR_MATERIAL\n",
+#else
+ "",
+#endif
+ source,
+ };
+
+ GLuint shader = glCreateShader(shaderType);
+ glShaderSource(shader, 4, sources, NULL);
+ glCompileShader(shader);
+
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLchar emsg[1024];
+ glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
+ fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
+ fprintf(stderr, "Version: %s\n", version);
+ fprintf(stderr, "Defines: %s\n", define);
+ fprintf(stderr, "Source: %s\n", source);
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint linkProgram(const char* version, const char* define) {
+ GLuint vertexShader =
+ compileShader(GL_VERTEX_SHADER, version, define,
+ datatoc_gpu_shader_opensubdiv_vertex_glsl);
+ if (vertexShader == 0) {
+ return 0;
+ }
+ GLuint geometryShader =
+ compileShader(GL_GEOMETRY_SHADER, version, define,
+ datatoc_gpu_shader_opensubdiv_geometry_glsl);
+ if (geometryShader == 0) {
+ return 0;
+ }
+ GLuint fragmentShader =
+ compileShader(GL_FRAGMENT_SHADER, version, define,
+ datatoc_gpu_shader_opensubdiv_fragment_glsl);
+ if (fragmentShader == 0) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, geometryShader);
+ glAttachShader(program, fragmentShader);
+
+ glBindAttribLocation(program, 0, "position");
+ glBindAttribLocation(program, 1, "normal");
+
+ glLinkProgram(program);
+
+ glDeleteShader(vertexShader);
+ glDeleteShader(geometryShader);
+ glDeleteShader(fragmentShader);
+
+ GLint status;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLchar emsg[1024];
+ glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
+ fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
+ fprintf(stderr, "Defines: %s\n", define);
+ glDeleteProgram(program);
+ return 0;
+ }
+
+ glUniformBlockBinding(program, glGetUniformBlockIndex(program, "Lighting"),
+ 0);
+
+ if (GLEW_VERSION_4_1) {
+ glProgramUniform1i(
+ program, glGetUniformLocation(program, "texture_buffer"), 0);
+ glProgramUniform1i(
+ program, glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
+ glProgramUniform1i(
+ program, glGetUniformLocation(program, "FVarDataBuffer"), 31);
+ } else {
+ glUseProgram(program);
+ glUniform1i(glGetUniformLocation(program, "texture_buffer"), 0);
+ glUniform1i(glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
+ glUniform1i(glGetUniformLocation(program, "FVarDataBuffer"), 31);
+ glUseProgram(0);
+ }
+
+ return program;
+}
+
+void bindProgram(OpenSubdiv_GLMesh* gl_mesh, int program) {
+ glUseProgram(program);
+ // Matrices
+ glUniformMatrix4fv(glGetUniformLocation(program, "modelViewMatrix"),
+ 1,
+ false,
+ g_transform.model_view_matrix);
+ glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"),
+ 1,
+ false,
+ g_transform.projection_matrix);
+ glUniformMatrix3fv(glGetUniformLocation(program, "normalMatrix"),
+ 1,
+ false,
+ g_transform.normal_matrix);
+ // Lighting.
+ glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
+ glBufferSubData(
+ GL_UNIFORM_BUFFER, 0, sizeof(g_lighting_data), &g_lighting_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
+ // Color.
+ {
+ // TODO(sergey): Stop using glGetMaterial.
+ float color[4];
+ glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
+ glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
+ glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
+ glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
+ glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
+ glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
+ }
+ // Face-vertex data.
+ opensubdiv_capi::GLMeshFVarData* fvar_data = gl_mesh->internal->fvar_data;
+ if (fvar_data != NULL) {
+ if (fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ if (fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+ fvar_data->fvar_width);
+ if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+ fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+}
+
+} // namespace
+
+bool openSubdiv_initGLMeshDrawingResources(void) {
+ static bool need_init = true;
+ static bool init_success = false;
+ if (!need_init) {
+ return init_success;
+ }
+ // TODO(sergey): Update OSD drawing to OpenGL 3.3 core,
+ // then remove following line.
+ return false;
+ const char* version = "";
+ if (GLEW_VERSION_3_2) {
+ version = "#version 150 compatibility\n";
+ } else if (GLEW_VERSION_3_1) {
+ version = "#version 140\n"
+ "#extension GL_ARB_compatibility: enable\n";
+ } else {
+ version = "#version 130\n";
+ // Minimum supported for OpenSubdiv.
+ }
+ g_flat_fill_solid_program = linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+
+ g_flat_fill_solid_shadeless_program =
+ linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_shadeless_program =
+ linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_shadeless_program =
+ linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_shadeless_program =
+ linkProgram(version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+ g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
+
+ glGenBuffers(1, &g_lighting_ub);
+ glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
+ glBufferData(GL_UNIFORM_BUFFER,
+ sizeof(g_lighting_data),
+ NULL,
+ GL_STATIC_DRAW);
+ need_init = false;
+ init_success = g_flat_fill_solid_program != 0 &&
+ g_flat_fill_texture2d_program != 0 &&
+ g_smooth_fill_solid_program != 0 &&
+ g_smooth_fill_texture2d_program != 0 && g_wireframe_program;
+ return init_success;
+}
+
+void openSubdiv_deinitGLMeshDrawingResources(void) {
+ if (g_lighting_ub != 0) {
+ glDeleteBuffers(1, &g_lighting_ub);
+ }
+#define SAFE_DELETE_PROGRAM(program) \
+ do { \
+ if (program) { \
+ glDeleteProgram(program); \
+ } \
+ } while (false)
+
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_wireframe_program);
+
+#undef SAFE_DELETE_PROGRAM
+}
+
+namespace opensubdiv_capi {
+
+namespace {
+
+GLuint prepare_patchDraw(OpenSubdiv_GLMesh* gl_mesh, bool fill_quads) {
+ GLint program = 0;
+ if (!g_use_osd_glsl) {
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ if (program) {
+ GLint model;
+ glGetIntegerv(GL_SHADE_MODEL, &model);
+ GLint location = glGetUniformLocation(program, "osd_flat_shading");
+ if (location != -1) {
+ glUniform1i(location, model == GL_FLAT);
+ }
+ // Face-vertex data.
+ opensubdiv_capi::GLMeshFVarData* fvar_data = gl_mesh->internal->fvar_data;
+ if (fvar_data != NULL) {
+ if (fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ if (fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ GLint location = glGetUniformLocation(program, "osd_fvar_count");
+ if (location != -1) {
+ glUniform1i(location, fvar_data->fvar_width);
+ }
+ location = glGetUniformLocation(program, "osd_active_uv_offset");
+ if (location != -1) {
+ if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
+ glUniform1i(location,
+ fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(location, 0);
+ }
+ }
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+ }
+ return program;
+ }
+ if (fill_quads) {
+ int model;
+ GLboolean use_texture_2d;
+ glGetIntegerv(GL_SHADE_MODEL, &model);
+ glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
+ if (model == GL_FLAT) {
+ if (use_texture_2d) {
+ program = g_flat_fill_texture2d_program;
+ } else {
+ program = g_flat_fill_solid_program;
+ }
+ } else {
+ if (use_texture_2d) {
+ program = g_smooth_fill_texture2d_program;
+ } else {
+ program = g_smooth_fill_solid_program;
+ }
+ }
+
+ } else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ program = g_wireframe_program;
+ }
+ bindProgram(gl_mesh, program);
+ return program;
+}
+
+void perform_drawElements(GLuint program,
+ int patch_index,
+ int num_elements,
+ int start_element) {
+ if (program) {
+ glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"), patch_index);
+ }
+ glDrawElements(GL_LINES_ADJACENCY,
+ num_elements,
+ GL_UNSIGNED_INT,
+ reinterpret_cast<void*>(start_element * sizeof(unsigned int)));
+}
+
+void finishPatchDraw(bool fill_quads) {
+ // TODO(sergey): Some of the stuff could be done once after the whole
+ // mesh is displayed.
+ /// Restore state.
+ if (!fill_quads) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ glBindVertexArray(0);
+ if (g_use_osd_glsl) {
+ // TODO(sergey): Store previously used program and roll back to it?
+ glUseProgram(0);
+ }
+}
+
+void drawPartitionPatchesRange(GLMeshInterface* mesh,
+ GLuint program,
+ int start_patch,
+ int num_patches) {
+ int traversed_patches = 0, num_remained_patches = num_patches;
+ const OpenSubdiv::Osd::PatchArrayVector &patches =
+ mesh->GetPatchTable()->GetPatchArrays();
+ for (int i = 0; i < patches.size(); ++i) {
+ const OpenSubdiv::Osd::PatchArray &patch = patches[i];
+ OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
+ OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
+ if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
+ const int num_block_patches = patch.GetNumPatches();
+ if (start_patch >= traversed_patches &&
+ start_patch < traversed_patches + num_block_patches) {
+ const int num_control_verts = desc.GetNumControlVertices();
+ const int start_draw_patch = start_patch - traversed_patches;
+ const int num_draw_patches = std::min(
+ num_remained_patches, num_block_patches - start_draw_patch);
+ perform_drawElements(
+ program, i + start_draw_patch, num_draw_patches * num_control_verts,
+ patch.GetIndexBase() + start_draw_patch * num_control_verts);
+ num_remained_patches -= num_draw_patches;
+ }
+ if (num_remained_patches == 0) {
+ break;
+ }
+ traversed_patches += num_block_patches;
+ }
+ }
+}
+
+static void drawAllPatches(GLMeshInterface* mesh, GLuint program) {
+ const OpenSubdiv::Osd::PatchArrayVector &patches =
+ mesh->GetPatchTable()->GetPatchArrays();
+ for (int i = 0; i < patches.size(); ++i) {
+ const OpenSubdiv::Osd::PatchArray &patch = patches[i];
+ OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
+ OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
+
+ if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
+ perform_drawElements(program, i,
+ patch.GetNumPatches() * desc.GetNumControlVertices(),
+ patch.GetIndexBase());
+ }
+ }
+}
+
+} // namespace
+
+void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh* /*gl_mesh*/,
+ const bool use_osd_glsl,
+ const int active_uv_index) {
+ g_active_uv_index = active_uv_index;
+ g_use_osd_glsl = (use_osd_glsl != 0);
+ // Update transformation matrices.
+ glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
+ glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
+ copy_m3_m4((float(*)[3])g_transform.normal_matrix,
+ (float(*)[4])g_transform.model_view_matrix);
+ invert_m3((float(*)[3])g_transform.normal_matrix);
+ transpose_m3((float(*)[3])g_transform.normal_matrix);
+ // Update OpenGL lights positions, colors etc.
+ g_lighting_data.num_enabled = 0;
+ for (int i = 0; i < MAX_LIGHTS; ++i) {
+ GLboolean enabled;
+ glGetBooleanv(GL_LIGHT0 + i, &enabled);
+ if (enabled) {
+ g_lighting_data.num_enabled++;
+ }
+ // TODO(sergey): Stop using glGetLight.
+ glGetLightfv(GL_LIGHT0 + i, GL_POSITION,
+ g_lighting_data.lights[i].position);
+ glGetLightfv(GL_LIGHT0 + i, GL_AMBIENT, g_lighting_data.lights[i].ambient);
+ glGetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, g_lighting_data.lights[i].diffuse);
+ glGetLightfv(GL_LIGHT0 + i, GL_SPECULAR,
+ g_lighting_data.lights[i].specular);
+ glGetLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION,
+ g_lighting_data.lights[i].spot_direction);
+#ifdef SUPPORT_COLOR_MATERIAL
+ glGetLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION,
+ &g_lighting_data.lights[i].constant_attenuation);
+ glGetLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION,
+ &g_lighting_data.lights[i].linear_attenuation);
+ glGetLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION,
+ &g_lighting_data.lights[i].quadratic_attenuation);
+ glGetLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF,
+ &g_lighting_data.lights[i].spot_cutoff);
+ glGetLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT,
+ &g_lighting_data.lights[i].spot_exponent);
+ g_lighting_data.lights[i].spot_cos_cutoff =
+ cos(g_lighting_data.lights[i].spot_cutoff);
+#endif
+ }
+}
+
+void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh* gl_mesh,
+ const bool fill_quads,
+ const int start_patch,
+ const int num_patches) {
+ GLMeshInterface* mesh = gl_mesh->internal->mesh_interface;
+ // Make sure all global invariants are initialized.
+ if (!openSubdiv_initGLMeshDrawingResources()) {
+ return;
+ }
+ /// Setup GLSL/OpenGL to draw patches in current context.
+ GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
+ if (start_patch != -1) {
+ drawPartitionPatchesRange(mesh, program, start_patch, num_patches);
+ } else {
+ drawAllPatches(mesh, program);
+ }
+ // Finish patch drawing by restoring all changes to the OpenGL context.
+ finishPatchDraw(fill_quads != 0);
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h
new file mode 100644
index 00000000000..5421b5cf707
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h
@@ -0,0 +1,39 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_GL_MESH_DRAW_H_
+#define OPENSUBDIV_GL_MESH_DRAW_H_
+
+#include <stdint.h> // for bool
+
+struct OpenSubdiv_GLMesh;
+
+namespace opensubdiv_capi {
+
+void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh* gl_mesh,
+ const bool use_osd_glsl,
+ const int active_uv_index);
+
+void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh* gl_mesh,
+ const bool fill_quads,
+ const int start_patch,
+ const int num_patches);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_GL_MESH_DRAW_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc
new file mode 100644
index 00000000000..5c9033c8dd1
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc
@@ -0,0 +1,175 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_gl_mesh_fvar.h"
+
+#include <GL/glew.h>
+#include <opensubdiv/far/primvarRefiner.h>
+
+namespace opensubdiv_capi {
+
+////////////////////////////////////////////////////////////////////////////////
+// GLMeshFVarData
+
+GLMeshFVarData::GLMeshFVarData()
+ : texture_buffer(0),
+ offset_buffer(0) {
+}
+
+GLMeshFVarData::~GLMeshFVarData() {
+ release();
+}
+
+void GLMeshFVarData::release() {
+ if (texture_buffer) {
+ glDeleteTextures(1, &texture_buffer);
+ }
+ if (offset_buffer) {
+ glDeleteTextures(1, &offset_buffer);
+ }
+ texture_buffer = 0;
+ offset_buffer = 0;
+ fvar_width = 0;
+ channel_offsets.clear();
+}
+
+void GLMeshFVarData::create(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv::Far::PatchTable* patch_table,
+ int fvar_width,
+ const float* fvar_src_data) {
+ release();
+ this->fvar_width = fvar_width;
+ /// Expand fvar data to per-patch array.
+ const int max_level = topology_refiner->GetMaxLevel();
+ const int num_channels = patch_table->GetNumFVarChannels();
+ std::vector<float> data;
+ int fvar_data_offset = 0;
+ channel_offsets.resize(num_channels);
+ for (int channel = 0; channel < num_channels; ++channel) {
+ OpenSubdiv::Far::ConstIndexArray indices =
+ patch_table->GetFVarValues(channel);
+ channel_offsets[channel] = data.size();
+ data.reserve(data.size() + indices.size() * fvar_width);
+ for (int fvert = 0; fvert < indices.size(); ++fvert) {
+ int index = indices[fvert] * fvar_width;
+ for (int i = 0; i < fvar_width; ++i) {
+ data.push_back(fvar_src_data[fvar_data_offset + index++]);
+ }
+ }
+ if (topology_refiner->IsUniform()) {
+ const int num_values_max =
+ topology_refiner->GetLevel(max_level).GetNumFVarValues(channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ const int num_values_total =
+ topology_refiner->GetNumFVarValuesTotal(channel);
+ fvar_data_offset += num_values_total * fvar_width;
+ }
+ }
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER,
+ data.size() * sizeof(float), &data[0],
+ GL_STATIC_DRAW);
+ glGenTextures(1, &texture_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
+ glDeleteBuffers(1, &buffer);
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER,
+ channel_offsets.size() * sizeof(int),
+ &channel_offsets[0],
+ GL_STATIC_DRAW);
+ glGenTextures(1, &offset_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper functions.
+
+struct FVarVertex {
+ float u, v;
+
+ void Clear() {
+ u = v = 0.0f;
+ }
+
+ void AddWithWeight(FVarVertex const& src, float weight) {
+ u += weight * src.u;
+ v += weight * src.v;
+ }
+};
+
+void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float>& uvs,
+ std::vector<float>* fvar_data) {
+ const int fvar_width = 2;
+ const int max_level = refiner.GetMaxLevel();
+ size_t fvar_data_offset = 0, values_offset = 0;
+ for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
+ const int num_values = refiner.GetLevel(0).GetNumFVarValues(channel) * 2;
+ const int num_values_max =
+ refiner.GetLevel(max_level).GetNumFVarValues(channel);
+ const int num_values_total = refiner.GetNumFVarValuesTotal(channel);
+ if (num_values_total <= 0) {
+ continue;
+ }
+ OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
+ if (refiner.IsUniform()) {
+ // For uniform we only keep the highest level of refinement.
+ fvar_data->resize(fvar_data->size() + num_values_max * fvar_width);
+ std::vector<FVarVertex> buffer(num_values_total - num_values_max);
+ FVarVertex* src = &buffer[0];
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ // Defer the last level to treat separately with its alternate
+ // destination.
+ for (int level = 1; level < max_level; ++level) {
+ FVarVertex* dst =
+ src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ FVarVertex* dst =
+ reinterpret_cast<FVarVertex*>(&(*fvar_data)[fvar_data_offset]);
+ primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ // For adaptive we keep all levels.
+ fvar_data->resize(fvar_data->size() + num_values_total * fvar_width);
+ FVarVertex* src =
+ reinterpret_cast<FVarVertex*>(&(*fvar_data)[fvar_data_offset]);
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ for (int level = 1; level <= max_level; ++level) {
+ FVarVertex* dst =
+ src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ fvar_data_offset += num_values_total * fvar_width;
+ }
+ values_offset += num_values;
+ }
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h
new file mode 100644
index 00000000000..039a94eaf86
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h
@@ -0,0 +1,57 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_GL_MESH_FVAR_H_
+#define OPENSUBDIV_GL_MESH_FVAR_H_
+
+// NOTE: This is a [sane(er)] port of previous ground work for getting UVs to
+// work. Still needs a lot of work to make it easy, correct and have proper
+// data ownership.
+
+#include <opensubdiv/far/topologyRefiner.h>
+#include <opensubdiv/far/patchTable.h>
+
+#include <vector>
+
+namespace opensubdiv_capi {
+
+// The buffer which holds GPU resources for face-varying elements.
+class GLMeshFVarData {
+ public:
+ GLMeshFVarData();
+ ~GLMeshFVarData();
+
+ void release();
+ void create(const OpenSubdiv::Far::TopologyRefiner* refiner,
+ const OpenSubdiv::Far::PatchTable* patch_table,
+ int fvar_width,
+ const float* fvar_src_data);
+
+ unsigned int texture_buffer;
+ unsigned int offset_buffer;
+ std::vector<int> channel_offsets;
+ int fvar_width;
+};
+
+void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float>& uvs,
+ std::vector<float>* fvar_data);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_GL_MESH_FVAR_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc
new file mode 100644
index 00000000000..3abba9cf8f8
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc
@@ -0,0 +1,32 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_gl_mesh_internal.h"
+
+#include "internal/opensubdiv_gl_mesh_fvar.h"
+
+OpenSubdiv_GLMeshInternal::OpenSubdiv_GLMeshInternal()
+ : evaluator_type(OPENSUBDIV_EVALUATOR_CPU),
+ mesh_interface(NULL),
+ fvar_data(NULL) {
+}
+
+OpenSubdiv_GLMeshInternal::~OpenSubdiv_GLMeshInternal() {
+ delete mesh_interface;
+ delete fvar_data;
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h
new file mode 100644
index 00000000000..7796b450e69
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h
@@ -0,0 +1,43 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_GL_MESH_INTERNAL_H_
+#define OPENSUBDIV_GL_MESH_INTERNAL_H_
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/osd/glMesh.h>
+
+#include "opensubdiv_capi_type.h"
+
+namespace opensubdiv_capi {
+class GLMeshFVarData;
+} // namespace opensubdiv_capi
+
+typedef struct OpenSubdiv_GLMeshInternal {
+ OpenSubdiv_GLMeshInternal();
+ ~OpenSubdiv_GLMeshInternal();
+
+ eOpenSubdivEvaluator evaluator_type;
+ OpenSubdiv::Osd::GLMeshInterface* mesh_interface;
+ opensubdiv_capi::GLMeshFVarData* fvar_data;
+} OpenSubdiv_GLMeshInternal;
+
+#endif // OPENSUBDIV_GL_MESH_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_internal.h b/intern/opensubdiv/internal/opensubdiv_internal.h
new file mode 100644
index 00000000000..16365896edf
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_internal.h
@@ -0,0 +1,35 @@
+// Copyright 2015 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_INTERNAL_H_
+#define OPENSUBDIV_INTERNAL_H_
+
+// Perform full topology validation when exporting it to OpenSubdiv.
+#ifdef NDEBUG
+// Never do for release builds.
+# undef OPENSUBDIV_VALIDATE_TOPOLOGY
+#else
+# define OPENSUBDIV_VALIDATE_TOPOLOGY
+#endif
+
+// Currently OpenSubdiv expects topology to be oriented, but sometimes it's
+// handy to disable orientation code to check whether it causes some weird
+// issues by using pre-oriented model.
+#define OPENSUBDIV_ORIENT_TOPOLOGY
+
+#endif // OPENSUBDIV_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
new file mode 100644
index 00000000000..5e1e0bd86b3
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
@@ -0,0 +1,367 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "opensubdiv_topology_refiner_capi.h"
+
+#include <vector>
+
+#include "MEM_guardedalloc.h"
+#include "internal/opensubdiv_converter_factory.h"
+#include "internal/opensubdiv_converter_internal.h"
+#include "internal/opensubdiv_internal.h"
+#include "internal/opensubdiv_topology_refiner_internal.h"
+
+namespace {
+
+const OpenSubdiv::Far::TopologyRefiner* getOSDTopologyRefiner(
+ const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return topology_refiner->internal->osd_topology_refiner;
+}
+
+const OpenSubdiv::Far::TopologyLevel* getOSDTopologyBaseLevel(
+ const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return &getOSDTopologyRefiner(topology_refiner)->GetLevel(0);
+}
+
+int getSubdivisionLevel(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return topology_refiner->internal->settings.level;
+}
+
+bool getIsAdaptive(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return topology_refiner->internal->settings.is_adaptive;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Query basic topology information from base level.
+
+int getNumVertices(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return getOSDTopologyBaseLevel(topology_refiner)->GetNumVertices();
+}
+
+int getNumEdges(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return getOSDTopologyBaseLevel(topology_refiner)->GetNumEdges();
+}
+
+int getNumFaces(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return getOSDTopologyBaseLevel(topology_refiner)->GetNumFaces();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PTex face geometry queries.
+
+int getNumFaceVertices(const OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index) {
+ const OpenSubdiv::Far::TopologyLevel* base_level =
+ getOSDTopologyBaseLevel(topology_refiner);
+ return base_level->GetFaceVertices(face_index).size();
+}
+
+int getNumFacePtexFaces(const OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index) {
+ const int num_face_vertices =
+ topology_refiner->getNumFaceVertices(topology_refiner, face_index);
+ if (num_face_vertices == 4) {
+ return 1;
+ } else {
+ return num_face_vertices;
+ }
+}
+
+int getNumPtexFaces(const OpenSubdiv_TopologyRefiner* topology_refiner) {
+ const int num_faces = topology_refiner->getNumFaces(topology_refiner);
+ int num_ptex_faces = 0;
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ num_ptex_faces +=
+ topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
+ }
+ return num_ptex_faces;
+}
+
+void fillFacePtexIndexOffset(const OpenSubdiv_TopologyRefiner* topology_refiner,
+ int* face_ptex_index_offset) {
+ const int num_faces = topology_refiner->getNumFaces(topology_refiner);
+ int num_ptex_faces = 0;
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ face_ptex_index_offset[face_index] = num_ptex_faces;
+ num_ptex_faces +=
+ topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Face-varying data.
+
+int getNumFVarChannels(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner) {
+ const OpenSubdiv::Far::TopologyLevel* base_level =
+ getOSDTopologyBaseLevel(topology_refiner);
+ return base_level->GetNumFVarChannels();
+}
+
+OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner) {
+ return opensubdiv_capi::getCAPIFVarLinearInterpolationFromOSD(
+ getOSDTopologyRefiner(topology_refiner)->GetFVarLinearInterpolation());
+}
+
+int getNumFVarValues(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int channel) {
+ const OpenSubdiv::Far::TopologyLevel* base_level =
+ getOSDTopologyBaseLevel(topology_refiner);
+ return base_level->GetNumFVarValues(channel);
+}
+
+const int* getFaceFVarValueIndices(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index,
+ const int channel) {
+ const OpenSubdiv::Far::TopologyLevel* base_level =
+ getOSDTopologyBaseLevel(topology_refiner);
+ return &base_level->GetFaceFVarValues(face_index, channel)[0];
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Internal helpers.
+
+void assignFunctionPointers(OpenSubdiv_TopologyRefiner* topology_refiner) {
+ topology_refiner->getSubdivisionLevel = getSubdivisionLevel;
+ topology_refiner->getIsAdaptive = getIsAdaptive;
+ // Basic topology information.
+ topology_refiner->getNumVertices = getNumVertices;
+ topology_refiner->getNumEdges = getNumEdges;
+ topology_refiner->getNumFaces = getNumFaces;
+ topology_refiner->getNumFaceVertices = getNumFaceVertices;
+ // PTex face geometry.
+ topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
+ topology_refiner->getNumPtexFaces = getNumPtexFaces;
+ topology_refiner->fillFacePtexIndexOffset = fillFacePtexIndexOffset;
+ // Face-varying data.
+ topology_refiner->getNumFVarChannels = getNumFVarChannels;
+ topology_refiner->getFVarLinearInterpolation = getFVarLinearInterpolation;
+ topology_refiner->getNumFVarValues = getNumFVarValues;
+ topology_refiner->getFaceFVarValueIndices = getFaceFVarValueIndices;
+}
+
+OpenSubdiv_TopologyRefiner* allocateTopologyRefiner() {
+ OpenSubdiv_TopologyRefiner* topology_refiner =
+ OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefiner);
+ topology_refiner->internal =
+ OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefinerInternal);
+ assignFunctionPointers(topology_refiner);
+ return topology_refiner;
+}
+
+} // namespace
+
+OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
+ OpenSubdiv_Converter* converter,
+ const OpenSubdiv_TopologyRefinerSettings* settings) {
+ OpenSubdiv::Far::TopologyRefiner* osd_topology_refiner =
+ opensubdiv_capi::createOSDTopologyRefinerFromConverter(converter);
+ if (osd_topology_refiner == NULL) {
+ // Happens on empty or bad topology.
+ return NULL;
+ }
+ OpenSubdiv_TopologyRefiner* topology_refiner = allocateTopologyRefiner();
+ topology_refiner->internal->osd_topology_refiner = osd_topology_refiner;
+ // Store setting which we want to keep track of and which can not be stored
+ // in OpenSubdiv's descriptor yet.
+ topology_refiner->internal->settings = *settings;
+ return topology_refiner;
+}
+
+void openSubdiv_deleteTopologyRefiner(
+ OpenSubdiv_TopologyRefiner* topology_refiner) {
+ OBJECT_GUARDED_DELETE(topology_refiner->internal,
+ OpenSubdiv_TopologyRefinerInternal);
+ OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefiner);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Comparison with converter.
+
+namespace {
+
+///////////////////////////////////////////////////////////
+// Quick preliminary checks.
+
+bool checkSchemeTypeMatches(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ const OpenSubdiv::Sdc::SchemeType converter_scheme_type =
+ opensubdiv_capi::getSchemeTypeFromCAPI(
+ converter->getSchemeType(converter));
+ return (converter_scheme_type == topology_refiner->GetSchemeType());
+}
+
+bool checkOptionsMatches(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ typedef OpenSubdiv::Sdc::Options Options;
+ const Options options = topology_refiner->GetSchemeOptions();
+ const Options::FVarLinearInterpolation fvar_interpolation =
+ options.GetFVarLinearInterpolation();
+ const Options::FVarLinearInterpolation converter_fvar_interpolation =
+ opensubdiv_capi::getFVarLinearInterpolationFromCAPI(
+ converter->getFVarLinearInterpolation(converter));
+ if (fvar_interpolation != converter_fvar_interpolation) {
+ return false;
+ }
+ return true;
+}
+
+bool checkGeometryCoountersMatches(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ using OpenSubdiv::Far::TopologyLevel;
+ const TopologyLevel& base_level = topology_refiner->GetLevel(0);
+ return (
+ (converter->getNumVertices(converter) == base_level.GetNumVertices()) &&
+ (converter->getNumEdges(converter) == base_level.GetNumEdges()) &&
+ (converter->getNumFaces(converter) == base_level.GetNumFaces()));
+}
+
+bool checkPreliminaryMatches(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ return checkSchemeTypeMatches(topology_refiner, converter) &&
+ checkOptionsMatches(topology_refiner, converter) &&
+ checkGeometryCoountersMatches(topology_refiner, converter);
+}
+
+///////////////////////////////////////////////////////////
+// Geometry comparison.
+
+bool checkGeometryEdgesMatch(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ using OpenSubdiv::Far::ConstIndexArray;
+ using OpenSubdiv::Far::TopologyLevel;
+ const TopologyLevel& base_level = topology_refiner->GetLevel(0);
+ const int num_edges = base_level.GetNumEdges();
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ const ConstIndexArray& edge_vertices =
+ base_level.GetEdgeVertices(edge_index);
+ int conv_edge_vertices[2];
+ converter->getEdgeVertices(converter, edge_index, conv_edge_vertices);
+ if (conv_edge_vertices[0] != edge_vertices[0] ||
+ conv_edge_vertices[1] != edge_vertices[1]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool checkGeometryFacesMatch(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ using OpenSubdiv::Far::ConstIndexArray;
+ using OpenSubdiv::Far::TopologyLevel;
+ const TopologyLevel& base_level = topology_refiner->GetLevel(0);
+ const int num_faces = base_level.GetNumFaces();
+ // TODO(sergey): Consider using data structure which keeps handful of
+ // elements on stack before doing heep allocation.
+ std::vector<int> conv_face_vertices;
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ const ConstIndexArray& face_vertices =
+ base_level.GetFaceVertices(face_index);
+ const int num_face_vertices = face_vertices.size();
+ if (num_face_vertices !=
+ converter->getNumFaceVertices(converter, face_index)) {
+ return false;
+ }
+ conv_face_vertices.resize(num_face_vertices);
+ converter->getFaceVertices(converter, face_index, &conv_face_vertices[0]);
+ // Check face-vertex indices in the direct order (assuming topology
+ // orientation is disabled or did not flip order of the face-vertices).
+ //
+ // TODO(sergey): Can we simply memcmp() with OpenSubdiv's array?
+ bool direct_match = true;
+ for (int face_vertex_index = 0; face_vertex_index < num_face_vertices;
+ ++face_vertex_index) {
+ if (conv_face_vertices[face_vertex_index] !=
+ face_vertices[face_vertex_index]) {
+ direct_match = false;
+ break;
+ }
+ }
+ if (!direct_match) {
+// If face didn't match in direct direction we also test if it matches in
+// reversed direction. This is because conversion might reverse loops to
+// make normals consistent.
+#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
+ for (int face_vertex_index = 0; face_vertex_index < num_face_vertices;
+ ++face_vertex_index) {
+ if (conv_face_vertices[face_vertex_index] !=
+ face_vertices[num_face_vertices - face_vertex_index - 1]) {
+ return false;
+ }
+ }
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+
+bool checkGeometryMatches(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ return checkGeometryEdgesMatch(topology_refiner, converter) &&
+ checkGeometryFacesMatch(topology_refiner, converter);
+}
+
+///////////////////////////////////////////////////////////
+// Compare attributes which affects on topology
+
+bool checkEdgeSharpnessMatch(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ using OpenSubdiv::Far::ConstIndexArray;
+ using OpenSubdiv::Far::TopologyLevel;
+ const TopologyLevel& base_level = topology_refiner->GetLevel(0);
+ const int num_edges = base_level.GetNumEdges();
+ for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
+ const float sharpness = base_level.GetEdgeSharpness(edge_index);
+ const float conv_sharpness =
+ converter->getEdgeSharpness(converter, edge_index);
+ if (sharpness != conv_sharpness) {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool checkTopologyAttributesMatch(
+ const OpenSubdiv::Far::TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ return checkEdgeSharpnessMatch(topology_refiner, converter);
+}
+
+} // namespace
+
+bool openSubdiv_topologyRefinerCompareWithConverter(
+ const OpenSubdiv_TopologyRefiner* topology_refiner,
+ const OpenSubdiv_Converter* converter) {
+ const OpenSubdiv::Far::TopologyRefiner* refiner =
+ getOSDTopologyRefiner(topology_refiner);
+ return (checkPreliminaryMatches(refiner, converter) &&
+ checkGeometryMatches(refiner, converter) &&
+ checkTopologyAttributesMatch(refiner, converter));
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.cc b/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.cc
new file mode 100644
index 00000000000..4636679761f
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.cc
@@ -0,0 +1,26 @@
+// Copyright 2016 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#include "internal/opensubdiv_topology_refiner_internal.h"
+
+OpenSubdiv_TopologyRefinerInternal::OpenSubdiv_TopologyRefinerInternal()
+ : osd_topology_refiner(NULL) {}
+
+OpenSubdiv_TopologyRefinerInternal::~OpenSubdiv_TopologyRefinerInternal() {
+ delete osd_topology_refiner;
+}
diff --git a/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.h b/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.h
new file mode 100644
index 00000000000..f7ca6a7ad5e
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_topology_refiner_internal.h
@@ -0,0 +1,47 @@
+// Copyright 2016 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_TOPOLOGY_REFINER_INTERNAL_H_
+#define OPENSUBDIV_TOPOLOGY_REFINER_INTERNAL_H_
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+#include <opensubdiv/far/topologyRefiner.h>
+
+#include "opensubdiv_topology_refiner_capi.h"
+
+struct OpenSubdiv_TopologyRefinerInternal {
+ public:
+ OpenSubdiv_TopologyRefinerInternal();
+ ~OpenSubdiv_TopologyRefinerInternal();
+
+ OpenSubdiv::Far::TopologyRefiner* osd_topology_refiner;
+
+ // Subdivision settingsa this refiner is created for.
+ //
+ // We store it here since OpenSubdiv's refiner will only know about level and
+ // "adaptivity" after performing actual "refine" step.
+ //
+ // Ideally, we would also support refining topology without re-importing it
+ // from external world, but that is for later.
+ OpenSubdiv_TopologyRefinerSettings settings;
+};
+
+#endif // OPENSUBDIV_TOPOLOGY_REFINER_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_util.cc b/intern/opensubdiv/internal/opensubdiv_util.cc
new file mode 100644
index 00000000000..87bfce2116c
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_util.cc
@@ -0,0 +1,61 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+// Contributor(s): Brecht van Lommel
+
+#include "internal/opensubdiv_util.h"
+
+#include <GL/glew.h>
+#include <cstring>
+
+#ifdef _MSC_VER
+# include <iso646.h>
+#endif
+
+namespace opensubdiv_capi {
+
+void stringSplit(std::vector<std::string>* tokens,
+ const std::string& str,
+ const std::string& separators,
+ bool skip_empty) {
+ size_t token_start = 0, token_length = 0;
+ for (size_t i = 0; i < str.length(); ++i) {
+ const char ch = str[i];
+ if (separators.find(ch) == std::string::npos) {
+ // Append non-separator char to a token.
+ ++token_length;
+ } else {
+ // Append current token to the list (if any).
+ if (token_length > 0 || !skip_empty) {
+ std::string token = str.substr(token_start, token_length);
+ tokens->push_back(token);
+ }
+ // Re-set token pointers,
+ token_start = i + 1;
+ token_length = 0;
+ }
+ }
+ // Append token which might be at the end of the string.
+ if ((token_length != 0) ||
+ (!skip_empty && token_start > 0 &&
+ separators.find(str[token_start-1]) != std::string::npos)) {
+ std::string token = str.substr(token_start, token_length);
+ tokens->push_back(token);
+ }
+}
+
+} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_util.h b/intern/opensubdiv/internal/opensubdiv_util.h
new file mode 100644
index 00000000000..db55504215d
--- /dev/null
+++ b/intern/opensubdiv/internal/opensubdiv_util.h
@@ -0,0 +1,44 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+// Contributor(s): Brecht van Lommel
+
+#ifndef OPENSUBDIV_UTIL_H_
+#define OPENSUBDIV_UTIL_H_
+
+#include <vector>
+#include <string>
+
+namespace opensubdiv_capi {
+
+using std::string;
+using std::vector;
+
+#define foreach(x, y) for(x : y)
+
+#define STRINGIFY_ARG(x) "" #x
+#define STRINGIFY_APPEND(a, b) "" a #b
+#define STRINGIFY(x) STRINGIFY_APPEND("", x)
+
+void stringSplit(std::vector<std::string>* tokens,
+ const std::string& str,
+ const std::string& separators,
+ bool skip_empty);
+
+} // namespace opensubdiv_capi
+
+#endif // OPENSUBDIV_UTIL_H_
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
deleted file mode 100644
index 638039f4f3e..00000000000
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ /dev/null
@@ -1,441 +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.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- * Brecht van Lommel
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "opensubdiv_capi.h"
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include <stdlib.h>
-#include <GL/glew.h>
-
-#include <opensubdiv/version.h>
-#include <opensubdiv/osd/glMesh.h>
-
-/* CPU Backend */
-#include <opensubdiv/osd/cpuGLVertexBuffer.h>
-#include <opensubdiv/osd/cpuEvaluator.h>
-
-#ifdef OPENSUBDIV_HAS_OPENMP
-# include <opensubdiv/osd/ompEvaluator.h>
-#endif /* OPENSUBDIV_HAS_OPENMP */
-
-#ifdef OPENSUBDIV_HAS_OPENCL
-# include <opensubdiv/osd/clGLVertexBuffer.h>
-# include <opensubdiv/osd/clEvaluator.h>
-# include "opensubdiv_device_context_opencl.h"
-#endif /* OPENSUBDIV_HAS_OPENCL */
-
-#ifdef OPENSUBDIV_HAS_CUDA
-# include <opensubdiv/osd/cudaGLVertexBuffer.h>
-# include <opensubdiv/osd/cudaEvaluator.h>
-# include "opensubdiv_device_context_cuda.h"
-#endif /* OPENSUBDIV_HAS_CUDA */
-
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
-# include <opensubdiv/osd/glXFBEvaluator.h>
-# include <opensubdiv/osd/glVertexBuffer.h>
-#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
-
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
-# include <opensubdiv/osd/glComputeEvaluator.h>
-# include <opensubdiv/osd/glVertexBuffer.h>
-#endif /* OPENSUBDIV_HAS_GLSL_COMPUTE */
-
-#include <opensubdiv/osd/glPatchTable.h>
-#include <opensubdiv/far/stencilTable.h>
-#include <opensubdiv/far/primvarRefiner.h>
-
-#include "opensubdiv_gl_mesh.h"
-#include "opensubdiv_intern.h"
-#include "opensubdiv_topology_refiner.h"
-
-#include "MEM_guardedalloc.h"
-
-#include <string>
-#include <vector>
-
-using std::string;
-using std::vector;
-
-#define STRINGIFY_ARG(x) "" #x
-#define STRINGIFY_APPEND(a, b) "" a #b
-#define STRINGIFY(x) STRINGIFY_APPEND("", x)
-
-/* **************** Types declaration **************** */
-
-using OpenSubdiv::Osd::GLMeshInterface;
-using OpenSubdiv::Osd::Mesh;
-using OpenSubdiv::Osd::MeshBitset;
-using OpenSubdiv::Far::StencilTable;
-using OpenSubdiv::Osd::GLPatchTable;
-
-using OpenSubdiv::Osd::Mesh;
-
-/* CPU backend */
-using OpenSubdiv::Osd::CpuGLVertexBuffer;
-using OpenSubdiv::Osd::CpuEvaluator;
-typedef Mesh<CpuGLVertexBuffer,
- StencilTable,
- CpuEvaluator,
- GLPatchTable> OsdCpuMesh;
-
-#ifdef OPENSUBDIV_HAS_OPENMP
-using OpenSubdiv::Osd::OmpEvaluator;
-typedef Mesh<CpuGLVertexBuffer,
- StencilTable,
- OmpEvaluator,
- GLPatchTable> OsdOmpMesh;
-#endif /* OPENSUBDIV_HAS_OPENMP */
-
-#ifdef OPENSUBDIV_HAS_OPENCL
-using OpenSubdiv::Osd::CLEvaluator;
-using OpenSubdiv::Osd::CLGLVertexBuffer;
-using OpenSubdiv::Osd::CLStencilTable;
-/* TODO(sergey): Use CLDeviceCOntext similar to OSD examples? */
-typedef Mesh<CLGLVertexBuffer,
- CLStencilTable,
- CLEvaluator,
- GLPatchTable,
- CLDeviceContext> OsdCLMesh;
-static CLDeviceContext g_clDeviceContext;
-#endif /* OPENSUBDIV_HAS_OPENCL */
-
-#ifdef OPENSUBDIV_HAS_CUDA
-using OpenSubdiv::Osd::CudaEvaluator;
-using OpenSubdiv::Osd::CudaGLVertexBuffer;
-using OpenSubdiv::Osd::CudaStencilTable;
-typedef Mesh<CudaGLVertexBuffer,
- CudaStencilTable,
- CudaEvaluator,
- GLPatchTable> OsdCudaMesh;
-static CudaDeviceContext g_cudaDeviceContext;
-#endif /* OPENSUBDIV_HAS_CUDA */
-
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
-using OpenSubdiv::Osd::GLXFBEvaluator;
-using OpenSubdiv::Osd::GLStencilTableTBO;
-using OpenSubdiv::Osd::GLVertexBuffer;
-typedef Mesh<GLVertexBuffer,
- GLStencilTableTBO,
- GLXFBEvaluator,
- GLPatchTable> OsdGLSLTransformFeedbackMesh;
-#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
-
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
-using OpenSubdiv::Osd::GLComputeEvaluator;
-using OpenSubdiv::Osd::GLStencilTableSSBO;
-using OpenSubdiv::Osd::GLVertexBuffer;
-typedef Mesh<GLVertexBuffer,
- GLStencilTableSSBO,
- GLComputeEvaluator,
- GLPatchTable> OsdGLSLComputeMesh;
-#endif
-
-namespace {
-
-#if !defined(OPENSUBDIV_VERSION_NUMBER) && !defined(OPENSUBDIV_VERSION_MINOR)
-void stringSplit(vector<string>* tokens,
- const string& str,
- const string& separators,
- bool skip_empty) {
- size_t token_start = 0, token_length = 0;
- for (size_t i = 0; i < str.length(); ++i) {
- const char ch = str[i];
- if (separators.find(ch) == string::npos) {
- /* Append non-separator char to a token. */
- ++token_length;
- } else {
- /* Append current token to the list (if any). */
- if (token_length > 0 || !skip_empty) {
- string token = str.substr(token_start, token_length);
- tokens->push_back(token);
- }
- /* Re-set token pointers, */
- token_start = i + 1;
- token_length = 0;
- }
- }
- /* Append token which might be at the end of the string. */
- if ((token_length != 0) ||
- (!skip_empty && token_start > 0 &&
- separators.find(str[token_start-1]) != string::npos)) {
- string token = str.substr(token_start, token_length);
- tokens->push_back(token);
- }
-}
-#endif
-
-struct FVarVertex {
- float u, v;
- void Clear() {
- u = v = 0.0f;
- }
- void AddWithWeight(FVarVertex const & src, float weight) {
- u += weight * src.u;
- v += weight * src.v;
- }
-};
-
-static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
- const std::vector<float> uvs,
- std::vector<float> &fvar_data) {
- /* TODO(sergey): Make it somehow more generic way. */
- const int fvar_width = 2;
- const int max_level = refiner.GetMaxLevel();
- size_t fvar_data_offset = 0, values_offset = 0;
- for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
- const int num_values = refiner.GetLevel(0).GetNumFVarValues(channel) * 2,
- num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
- num_values_total = refiner.GetNumFVarValuesTotal(channel);
- if (num_values_total <= 0) {
- continue;
- }
- OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
- if (refiner.IsUniform()) {
- /* For uniform we only keep the highest level of refinement. */
- fvar_data.resize(fvar_data.size() + num_values_max * fvar_width);
- std::vector<FVarVertex> buffer(num_values_total - num_values_max);
- FVarVertex *src = &buffer[0];
- memcpy(src, &uvs[values_offset], num_values * sizeof(float));
- /* Defer the last level to treat separately with its alternate
- * destination.
- */
- for (int level = 1; level < max_level; ++level) {
- FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
- primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
- src = dst;
- }
- FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
- primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
- fvar_data_offset += num_values_max * fvar_width;
- } else {
- /* For adaptive we keep all levels. */
- fvar_data.resize(fvar_data.size() + num_values_total * fvar_width);
- FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
- memcpy(src, &uvs[values_offset], num_values * sizeof(float));
- for (int level = 1; level <= max_level; ++level) {
- FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
- primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
- src = dst;
- }
- fvar_data_offset += num_values_total * fvar_width;
- }
- values_offset += num_values;
- }
-}
-
-} // namespace
-
-struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int evaluator_type,
- int level)
-{
- using OpenSubdiv::Far::TopologyRefiner;
-
- MeshBitset bits;
- /* TODO(sergey): Adaptive subdivisions are not currently
- * possible because of the lack of tessellation shader.
- */
- bits.set(OpenSubdiv::Osd::MeshAdaptive, 0);
- bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
- bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
- bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
- bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
-
- const int num_vertex_elements = 3;
- const int num_varying_elements = 3;
-
- GLMeshInterface *mesh = NULL;
- TopologyRefiner *refiner = topology_refiner->osd_refiner;
-
- switch(evaluator_type) {
-#define CHECK_EVALUATOR_TYPE(type, class) \
- case OPENSUBDIV_EVALUATOR_ ## type: \
- mesh = new class(refiner, \
- num_vertex_elements, \
- num_varying_elements, \
- level, \
- bits); \
- break;
-
- CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
-
-#ifdef OPENSUBDIV_HAS_OPENMP
- CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_OPENCL
- CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_CUDA
- CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
- OsdGLSLTransformFeedbackMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
-#endif
-
-#undef CHECK_EVALUATOR_TYPE
- }
-
- if (mesh == NULL) {
- return NULL;
- }
-
- OpenSubdiv_GLMesh *gl_mesh =
- (OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
- gl_mesh->evaluator_type = evaluator_type;
- gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
- gl_mesh->topology_refiner = topology_refiner;
-
- if (refiner->GetNumFVarChannels() > 0) {
- std::vector<float> fvar_data;
- interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
- openSubdiv_osdGLAllocFVar(topology_refiner, gl_mesh, &fvar_data[0]);
- }
- else {
- gl_mesh->fvar_data = NULL;
- }
-
- return gl_mesh;
-}
-
-void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- openSubdiv_osdGLDestroyFVar(gl_mesh);
- switch (gl_mesh->evaluator_type) {
-#define CHECK_EVALUATOR_TYPE(type, class) \
- case OPENSUBDIV_EVALUATOR_ ## type: \
- delete (class *) gl_mesh->descriptor; \
- break;
-
- CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
-
-#ifdef OPENSUBDIV_HAS_OPENMP
- CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_OPENCL
- CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_CUDA
- CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
- OsdGLSLTransformFeedbackMesh)
-#endif
-
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
-#endif
-
-#undef CHECK_EVALUATOR_TYPE
- }
-
- /* NOTE: OSD refiner was owned by gl_mesh, no need to free it here. */
- OBJECT_GUARDED_DELETE(gl_mesh->topology_refiner, OpenSubdiv_TopologyRefinerDescr);
- OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
-}
-
-unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- return ((GLMeshInterface *)gl_mesh->descriptor)->GetPatchTable()->GetPatchIndexBuffer();
-}
-
-unsigned int openSubdiv_getOsdGLMeshVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- return ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
-}
-
-void openSubdiv_osdGLMeshUpdateVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh,
- const float *vertex_data,
- int start_vertex,
- int num_verts)
-{
- ((GLMeshInterface *)gl_mesh->descriptor)->UpdateVertexBuffer(vertex_data,
- start_vertex,
- num_verts);
-}
-
-void openSubdiv_osdGLMeshRefine(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- ((GLMeshInterface *)gl_mesh->descriptor)->Refine();
-}
-
-void openSubdiv_osdGLMeshSynchronize(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- ((GLMeshInterface *)gl_mesh->descriptor)->Synchronize();
-}
-
-void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
-{
- ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
-}
-
-const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner(
- OpenSubdiv_GLMesh *gl_mesh)
-{
- return gl_mesh->topology_refiner;
-}
-
-int openSubdiv_getVersionHex(void)
-{
-#if defined(OPENSUBDIV_VERSION_NUMBER)
- return OPENSUBDIV_VERSION_NUMBER;
-#elif defined(OPENSUBDIV_VERSION_MAJOR)
- return OPENSUBDIV_VERSION_MAJOR * 10000 +
- OPENSUBDIV_VERSION_MINOR * 100 +
- OPENSUBDIV_VERSION_PATCH;
-#elif defined(OPENSUBDIV_VERSION)
- const char* version = STRINGIFY(OPENSUBDIV_VERSION);
- if (version[0] == 'v') {
- version += 1;
- }
- int major = 0, minor = 0, patch = 0;
- vector<string> tokens;
- stringSplit(&tokens, version, "_", true);
- if (tokens.size() == 3) {
- major = atoi(tokens[0].c_str());
- minor = atoi(tokens[1].c_str());
- patch = atoi(tokens[2].c_str());
- }
- return major * 10000 + minor * 100 + patch;
-#else
- return 0;
-#endif
-}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index c29d08a77e1..a26ea36b863 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -1,163 +1,43 @@
-/*
- * ***** 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.
- *
- * Contributor(s): Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __OPENSUBDIV_CAPI_H__
-#define __OPENSUBDIV_CAPI_H__
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CAPI_H_
+#define OPENSUBDIV_CAPI_H_
+
+#include "opensubdiv_capi_type.h"
#ifdef __cplusplus
extern "C" {
#endif
-// Types declaration.
-struct OpenSubdiv_GLMesh;
-struct OpenSubdiv_GLMeshDescr;
-struct OpenSubdiv_GLMeshFVarData;
-struct OpenSubdiv_TopologyRefinerDescr;
-
-typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
-
-// Keep this a bitmask os it's possible to pass available
-// evaluators to Blender.
-enum {
- OPENSUBDIV_EVALUATOR_CPU = (1 << 0),
- OPENSUBDIV_EVALUATOR_OPENMP = (1 << 1),
- OPENSUBDIV_EVALUATOR_OPENCL = (1 << 2),
- OPENSUBDIV_EVALUATOR_CUDA = (1 << 3),
- OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK = (1 << 4),
- OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5),
-};
-
-enum {
- OPENSUBDIV_SCHEME_CATMARK,
- OPENSUBDIV_SCHEME_BILINEAR,
- OPENSUBDIV_SCHEME_LOOP,
-};
-
-/* TODO(sergey): Re-name and avoid bad level data access. */
-OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int evaluator_type,
- int level);
-
-void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
-unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
- OpenSubdiv_GLMesh *gl_mesh);
-unsigned int openSubdiv_getOsdGLMeshVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshUpdateVertexBuffer(OpenSubdiv_GLMesh *gl_mesh,
- const float *vertex_data,
- int start_vertex,
- int num_verts);
-void openSubdiv_osdGLMeshRefine(OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshSynchronize(OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
-
-const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner(
- OpenSubdiv_GLMesh *gl_mesh);
-
-/* ============================= Evaluator API ============================== */
-
-struct OpenSubdiv_EvaluatorDescr;
-typedef struct OpenSubdiv_EvaluatorDescr OpenSubdiv_EvaluatorDescr;
-
-/* TODO(sergey): Avoid bad-level data access, */
-OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(
- struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int subsurf_level);
-
-void openSubdiv_deleteEvaluatorDescr(
- OpenSubdiv_EvaluatorDescr *evaluator_descr);
-
-void openSubdiv_setEvaluatorCoarsePositions(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const float *positions,
- int start_vertex_index,
- int num_vertices);
-void openSubdiv_setEvaluatorVaryingData(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const float *varying_data,
- int start_vertex_index,
- int num_vertices);
-
-void openSubdiv_setEvaluatorCoarsePositionsFromBuffer(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const void *buffer,
- int start_offset,
- int stride,
- int start_vertex_index,
- int num_vertices);
-
-void openSubdiv_refineEvaluator(OpenSubdiv_EvaluatorDescr *evaluator_descr);
-
-void openSubdiv_evaluateLimit(OpenSubdiv_EvaluatorDescr *evaluator_descr,
- int osd_face_index,
- float face_u, float face_v,
- float P[3],
- float dPdu[3],
- float dPdv[3]);
-
-void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
- int osd_face_index,
- float face_u, float face_v,
- float varying[3]);
-
-/* ============================== Mesh drawing =============================== */
-
-/* Initialize/Deinitialize global OpenGL drawing buffers/GLSL programs. */
-bool openSubdiv_osdGLDisplayInit(void);
-void openSubdiv_osdGLDisplayDeinit(void);
-
-/* Initialize all the invariants which stays the same for every single path,
- * for example lighting model stays untouched for the whole mesh.
- *
- * TODO(sergey): Some of the stuff could be initialized once for all meshes.
- */
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl, int active_uv_index);
-
-/* Draw specified patches. */
-void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
- int fill_quads,
- int start_patch,
- int num_patches);
-
-void openSubdiv_osdGLAllocFVar(
- struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- OpenSubdiv_GLMesh *gl_mesh,
- const float *fvar_data);
-
-void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
-
-/* =========================== Utility functions ============================ */
-
-int openSubdiv_getAvailableEvaluators(void);
+// Global initialization/deinitialization.
+//
+// Supposed to be called from main thread.
void openSubdiv_init(void);
void openSubdiv_cleanup(void);
+// Bitmask of eOpenSubdivEvaluator.
+int openSubdiv_getAvailableEvaluators(void);
+
int openSubdiv_getVersionHex(void);
#ifdef __cplusplus
}
#endif
-#endif // __OPENSUBDIV_CAPI_H__
+#endif // OPENSUBDIV_CAPI_H_
diff --git a/intern/opensubdiv/opensubdiv_capi_type.h b/intern/opensubdiv/opensubdiv_capi_type.h
new file mode 100644
index 00000000000..b326e53e168
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_capi_type.h
@@ -0,0 +1,56 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CAPI_TYPES_H_
+#define OPENSUBDIV_CAPI_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Keep this a bitmask os it's possible to pass available
+// evaluators to Blender.
+typedef enum eOpenSubdivEvaluator {
+ OPENSUBDIV_EVALUATOR_CPU = (1 << 0),
+ OPENSUBDIV_EVALUATOR_OPENMP = (1 << 1),
+ OPENSUBDIV_EVALUATOR_OPENCL = (1 << 2),
+ OPENSUBDIV_EVALUATOR_CUDA = (1 << 3),
+ OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK = (1 << 4),
+ OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5),
+} eOpenSubdivEvaluator;
+
+typedef enum OpenSubdiv_SchemeType {
+ OSD_SCHEME_BILINEAR,
+ OSD_SCHEME_CATMARK,
+ OSD_SCHEME_LOOP,
+} OpenSubdiv_SchemeType;
+
+typedef enum OpenSubdiv_FVarLinearInterpolation {
+ OSD_FVAR_LINEAR_INTERPOLATION_NONE,
+ OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
+ OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1,
+ OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2,
+ OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
+ OSD_FVAR_LINEAR_INTERPOLATION_ALL,
+} OpenSubdiv_FVarLinearInterpolation;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // OPENSUBDIV_CAPI_TYPES_H_
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
deleted file mode 100644
index fec15b118ae..00000000000
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ /dev/null
@@ -1,764 +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.
- *
- * The Original Code is Copyright (C) 2015 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <cstdio>
-#include <vector>
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include <opensubdiv/far/topologyRefinerFactory.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "opensubdiv_converter_capi.h"
-#include "opensubdiv_intern.h"
-#include "opensubdiv_topology_refiner.h"
-
-
-#include <stack>
-
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
-namespace {
-
-inline void reverse_face_verts(int *face_verts, int num_verts)
-{
- int last_vert = face_verts[num_verts - 1];
- for (int i = num_verts - 1; i > 0; --i) {
- face_verts[i] = face_verts[i - 1];
- }
- face_verts[0] = last_vert;
-}
-
-struct TopologyRefinerData {
- const OpenSubdiv_Converter& conv;
- std::vector<float> *uvs;
-};
-
-} /* namespace */
-#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
-
-namespace OpenSubdiv {
-namespace OPENSUBDIV_VERSION {
-namespace Far {
-
-namespace {
-
-template <typename T>
-inline int findInArray(T array, int value)
-{
- return (int)(std::find(array.begin(), array.end(), value) - array.begin());
-}
-
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
-inline int get_loop_winding(int vert0_of_face, int vert1_of_face)
-{
- int delta_face = vert1_of_face - vert0_of_face;
- if (abs(delta_face) != 1) {
- if (delta_face > 0) {
- delta_face = -1;
- }
- else {
- delta_face = 1;
- }
- }
- return delta_face;
-}
-
-inline void reverse_face_loops(IndexArray face_verts, IndexArray face_edges)
-{
- for (int i = 0; i < face_verts.size() / 2; ++i) {
- int j = face_verts.size() - i - 1;
- if (i != j) {
- std::swap(face_verts[i], face_verts[j]);
- std::swap(face_edges[i], face_edges[j]);
- }
- }
- reverse_face_verts(&face_verts[0], face_verts.size());
-}
-
-inline void check_oriented_vert_connectivity(const int num_vert_edges,
- const int num_vert_faces,
- const int *vert_edges,
- const int *vert_faces,
- const int *dst_vert_edges,
- const int *dst_vert_faces)
-{
-# ifndef NDEBUG
- for (int i = 0; i < num_vert_faces; ++i) {
- bool found = false;
- for (int j = 0; j < num_vert_faces; ++j) {
- if (vert_faces[i] == dst_vert_faces[j]) {
- found = true;
- break;
- }
- }
- if (!found) {
- assert(!"vert-faces connectivity ruined");
- }
- }
- for (int i = 0; i < num_vert_edges; ++i) {
- bool found = false;
- for (int j = 0; j < num_vert_edges; ++j) {
- if (vert_edges[i] == dst_vert_edges[j]) {
- found = true;
- break;
- }
- }
- if (!found) {
- assert(!"vert-edges connectivity ruined");
- }
- }
-# else
- (void)num_vert_edges;
- (void)num_vert_faces;
- (void)vert_edges;
- (void)vert_faces;
- (void)dst_vert_edges;
- (void)dst_vert_faces;
-# endif
-}
-#endif
-
-} /* namespace */
-
-template <>
-inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
- TopologyRefiner& refiner,
- const TopologyRefinerData& cb_data)
-{
- const OpenSubdiv_Converter& conv = cb_data.conv;
- /* Faces and face-verts */
- const int num_faces = conv.get_num_faces(&conv);
- setNumBaseFaces(refiner, num_faces);
- for (int face = 0; face < num_faces; ++face) {
- const int num_verts = conv.get_num_face_verts(&conv, face);
- setNumBaseFaceVertices(refiner, face, num_verts);
- }
- /* Edges and edge-faces. */
- const int num_edges = conv.get_num_edges(&conv);
- setNumBaseEdges(refiner, num_edges);
- for (int edge = 0; edge < num_edges; ++edge) {
- const int num_edge_faces = conv.get_num_edge_faces(&conv, edge);
- setNumBaseEdgeFaces(refiner, edge, num_edge_faces);
- }
- /* Vertices and vert-faces and vert-edges/ */
- const int num_verts = conv.get_num_verts(&conv);
- setNumBaseVertices(refiner, num_verts);
- for (int vert = 0; vert < num_verts; ++vert) {
- const int num_vert_edges = conv.get_num_vert_edges(&conv, vert),
- num_vert_faces = conv.get_num_vert_faces(&conv, vert);
- setNumBaseVertexEdges(refiner, vert, num_vert_edges);
- setNumBaseVertexFaces(refiner, vert, num_vert_faces);
- }
- return true;
-}
-
-template <>
-inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
- TopologyRefiner& refiner,
- const TopologyRefinerData &cb_data)
-{
- const OpenSubdiv_Converter& conv = cb_data.conv;
- using Far::IndexArray;
- /* Face relations. */
- const int num_faces = conv.get_num_faces(&conv);
- for (int face = 0; face < num_faces; ++face) {
- IndexArray dst_face_verts = getBaseFaceVertices(refiner, face);
- conv.get_face_verts(&conv, face, &dst_face_verts[0]);
- IndexArray dst_face_edges = getBaseFaceEdges(refiner, face);
- conv.get_face_edges(&conv, face, &dst_face_edges[0]);
- }
- /* Edge relations. */
- const int num_edges = conv.get_num_edges(&conv);
- for (int edge = 0; edge < num_edges; ++edge) {
- /* Edge-vertices */
- IndexArray dst_edge_verts = getBaseEdgeVertices(refiner, edge);
- conv.get_edge_verts(&conv, edge, &dst_edge_verts[0]);
- /* Edge-faces */
- IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge);
- conv.get_edge_faces(&conv, edge, &dst_edge_faces[0]);
- }
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
- /* Make face normals consistent. */
- bool *face_used = new bool[num_faces];
- memset(face_used, 0, sizeof(bool) * num_faces);
- std::stack<int> traverse_stack;
- int face_start = 0, num_traversed_faces = 0;
- /* Traverse all islands. */
- while (num_traversed_faces != num_faces) {
- /* Find first face of any untraversed islands. */
- while (face_used[face_start]) {
- ++face_start;
- }
- /* Add first face to the stack. */
- traverse_stack.push(face_start);
- face_used[face_start] = true;
- /* Go over whole connected component. */
- while (!traverse_stack.empty()) {
- int face = traverse_stack.top();
- traverse_stack.pop();
- IndexArray face_edges = getBaseFaceEdges(refiner, face);
- ConstIndexArray face_verts = getBaseFaceVertices(refiner, face);
- for (int edge_index = 0; edge_index < face_edges.size(); ++edge_index) {
- const int edge = face_edges[edge_index];
- ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
- if (edge_faces.size() != 2) {
- /* Can't make consistent normals for non-manifolds. */
- continue;
- }
- ConstIndexArray edge_verts = getBaseEdgeVertices(refiner, edge);
- /* Get winding of the reference face. */
- int vert0_of_face = findInArray(face_verts, edge_verts[0]),
- vert1_of_face = findInArray(face_verts, edge_verts[1]);
- int delta_face = get_loop_winding(vert0_of_face, vert1_of_face);
- for (int edge_face = 0; edge_face < edge_faces.size(); ++edge_face) {
- int other_face = edge_faces[edge_face];
- /* Never re-traverse faces, only move forward. */
- if (face_used[other_face]) {
- continue;
- }
- IndexArray other_face_verts = getBaseFaceVertices(refiner,
- other_face);
- int vert0_of_other_face = findInArray(other_face_verts,
- edge_verts[0]),
- vert1_of_other_face = findInArray(other_face_verts,
- edge_verts[1]);
- int delta_other_face = get_loop_winding(vert0_of_other_face,
- vert1_of_other_face);
- if (delta_face * delta_other_face > 0) {
- IndexArray other_face_verts = getBaseFaceVertices(refiner,
- other_face),
- other_face_edges = getBaseFaceEdges(refiner,
- other_face);
- reverse_face_loops(other_face_verts,
- other_face_edges);
- }
- traverse_stack.push(other_face);
- face_used[other_face] = true;
- }
- }
- ++num_traversed_faces;
- }
- }
-#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
- /* Vertex relations */
- const int num_verts = conv.get_num_verts(&conv);
- for (int vert = 0; vert < num_verts; ++vert) {
-
- /* Vert-Faces */
- IndexArray dst_vert_faces = getBaseVertexFaces(refiner, vert);
- int num_vert_faces = conv.get_num_vert_faces(&conv, vert);
- int *vert_faces = new int[num_vert_faces];
- conv.get_vert_faces(&conv, vert, vert_faces);
- /* Vert-Edges */
- IndexArray dst_vert_edges = getBaseVertexEdges(refiner, vert);
- int num_vert_edges = conv.get_num_vert_edges(&conv, vert);
- int *vert_edges = new int[num_vert_edges];
- conv.get_vert_edges(&conv, vert, vert_edges);
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
- /* ** Order vertex edges and faces in a CCW order. ** */
- memset(face_used, 0, sizeof(bool) * num_faces);
- /* Number of edges and faces added to the ordered array. */
- int edge_count_ordered = 0, face_count_ordered = 0;
- /* Add loose edges straight into the edges array. */
- bool has_fan_connections = false;
- for (int i = 0; i < num_vert_edges; ++i) {
- IndexArray edge_faces = getBaseEdgeFaces(refiner, vert_edges[i]);
- if (edge_faces.size() == 0) {
- dst_vert_edges[edge_count_ordered++] = vert_edges[i];
- }
- else if (edge_faces.size() > 2) {
- has_fan_connections = true;
- }
- }
- if (has_fan_connections) {
- /* OpenSubdiv currently doesn't give us clues how to handle
- * fan face connections. and since handling such connections
- * complicates the loop below we simply don't do special
- * orientation for them.
- */
- memcpy(&dst_vert_edges[0], vert_edges, sizeof(int) * num_vert_edges);
- memcpy(&dst_vert_faces[0], vert_faces, sizeof(int) * num_vert_faces);
- delete [] vert_edges;
- delete [] vert_faces;
- continue;
- }
- /* Perform at max numbder of vert-edges iteration and try to avoid
- * deadlock here for malformed mesh.
- */
- for (int global_iter = 0; global_iter < num_vert_edges; ++global_iter) {
- /* Numbr of edges and faces which are still to be ordered. */
- int num_vert_edges_remained = num_vert_edges - edge_count_ordered,
- num_vert_faces_remained = num_vert_faces - face_count_ordered;
- if (num_vert_edges_remained == 0 && num_vert_faces_remained == 0) {
- /* All done, nothing to do anymore. */
- break;
- }
- /* Face, edge and face-vertex inndex to start traversal from. */
- int face_start = -1, edge_start = -1, face_vert_start = -1;
- if (num_vert_edges_remained == num_vert_faces_remained) {
- /* Vertex is eitehr complete manifold or is connected to seevral
- * manifold islands (hourglass-like configuration), can pick up
- * random edge unused and start from it.
- */
- /* TODO(sergey): Start from previous edge from which traversal
- * began at previous iteration.
- */
- for (int i = 0; i < num_vert_edges; ++i) {
- face_start = vert_faces[i];
- if (!face_used[face_start]) {
- ConstIndexArray
- face_verts = getBaseFaceVertices(refiner, face_start),
- face_edges = getBaseFaceEdges(refiner, face_start);
- face_vert_start = findInArray(face_verts, vert);
- edge_start = face_edges[face_vert_start];
- break;
- }
- }
- }
- else {
- /* Special handle of non-manifold vertex. */
- for (int i = 0; i < num_vert_edges; ++i) {
- edge_start = vert_edges[i];
- IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_start);
- if (edge_faces.size() == 1) {
- face_start = edge_faces[0];
- if (!face_used[face_start]) {
- ConstIndexArray
- face_verts = getBaseFaceVertices(refiner, face_start),
- face_edges = getBaseFaceEdges(refiner, face_start);
- face_vert_start = findInArray(face_verts, vert);
- if (edge_start == face_edges[face_vert_start]) {
- break;
- }
- }
- }
- /* Reset indices for sanity check below. */
- face_start = edge_start = face_vert_start = -1;
- }
- }
- /* Sanity check. */
- assert(face_start != -1 &&
- edge_start != -1 &&
- face_vert_start != -1);
- /* Traverse faces starting from the current one. */
- int edge_first = edge_start;
- dst_vert_faces[face_count_ordered++] = face_start;
- dst_vert_edges[edge_count_ordered++] = edge_start;
- face_used[face_start] = true;
- while (edge_count_ordered < num_vert_edges) {
- IndexArray face_verts = getBaseFaceVertices(refiner, face_start);
- IndexArray face_edges = getBaseFaceEdges(refiner, face_start);
- int face_edge_start = face_vert_start;
- int face_edge_next = (face_edge_start > 0) ? (face_edge_start - 1) : (face_verts.size() - 1);
- Index edge_next = face_edges[face_edge_next];
- if (edge_next == edge_first) {
- /* Multiple manifolds found, stop for now and handle rest
- * in the next iteration.
- */
- break;
- }
- dst_vert_edges[edge_count_ordered++] = edge_next;
- if (face_count_ordered < num_vert_faces) {
- IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_next);
- assert(edge_faces.size() != 0);
- if (edge_faces.size() == 1) {
- assert(edge_faces[0] == face_start);
- break;
- }
- else if (edge_faces.size() != 2) {
- break;
- }
- assert(edge_faces.size() == 2);
- face_start = edge_faces[(edge_faces[0] == face_start) ? 1 : 0];
- face_vert_start = findInArray(getBaseFaceEdges(refiner, face_start), edge_next);
- dst_vert_faces[face_count_ordered++] = face_start;
- face_used[face_start] = true;
- }
- edge_start = edge_next;
- }
- }
- /* Verify ordering doesn't ruin connectivity information. */
- assert(face_count_ordered == num_vert_faces);
- assert(edge_count_ordered == num_vert_edges);
- check_oriented_vert_connectivity(num_vert_edges,
- num_vert_faces,
- vert_edges,
- vert_faces,
- &dst_vert_edges[0],
- &dst_vert_faces[0]);
- /* For the release builds we're failing mesh construction so instead
- * of nasty bugs the unsupported mesh will simply disappear from the
- * viewport.
- */
- if (face_count_ordered != num_vert_faces ||
- edge_count_ordered != num_vert_edges)
- {
- delete [] vert_edges;
- delete [] vert_faces;
- return false;
- }
-#else /* OPENSUBDIV_ORIENT_TOPOLOGY */
- memcpy(&dst_vert_edges[0], vert_edges, sizeof(int) * num_vert_edges);
- memcpy(&dst_vert_faces[0], vert_faces, sizeof(int) * num_vert_faces);
-#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
- delete [] vert_edges;
- delete [] vert_faces;
- }
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
- delete [] face_used;
-#endif
- populateBaseLocalIndices(refiner);
- return true;
-};
-
-template <>
-inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
- TopologyRefiner& refiner,
- const TopologyRefinerData& cb_data)
-{
- const OpenSubdiv_Converter& conv = cb_data.conv;
- typedef OpenSubdiv::Sdc::Crease Crease;
-
- int num_edges = conv.get_num_edges(&conv);
- for (int edge = 0; edge < num_edges; ++edge) {
- float sharpness;
- ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
- if (edge_faces.size() == 2) {
- sharpness = conv.get_edge_sharpness(&conv, edge);
- }
- else {
- /* Non-manifold edges must be sharp. */
- sharpness = Crease::SHARPNESS_INFINITE;
- }
- setBaseEdgeSharpness(refiner, edge, sharpness);
- }
-
- /* OpenSubdiv expects non-manifold vertices to be sharp but at the
- * time it handles correct cases when vertex is a corner of plane.
- * Currently mark verts which are adjacent to a loose edge as sharp,
- * but this decision needs some more investigation.
- */
- int num_vert = conv.get_num_verts(&conv);
- for (int vert = 0; vert < num_vert; ++vert) {
- ConstIndexArray vert_edges = getBaseVertexEdges(refiner, vert);
- for (int edge_index = 0; edge_index < vert_edges.size(); ++edge_index) {
- int edge = vert_edges[edge_index];
- ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge);
- if (edge_faces.size() == 0) {
- setBaseVertexSharpness(refiner, vert, Crease::SHARPNESS_INFINITE);
- break;
- }
- }
- if (vert_edges.size() == 2) {
- int edge0 = vert_edges[0],
- edge1 = vert_edges[1];
- float sharpness0 = conv.get_edge_sharpness(&conv, edge0),
- sharpness1 = conv.get_edge_sharpness(&conv, edge1);
- float sharpness = std::min(sharpness0, sharpness1);
- setBaseVertexSharpness(refiner, vert, sharpness);
- }
- }
-
- return true;
-}
-
-template <>
-inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
- TopologyError /*errCode*/,
- const char *msg,
- const TopologyRefinerData& /*mesh*/)
-{
- printf("OpenSubdiv Error: %s\n", msg);
-}
-
-template <>
-inline bool TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
- TopologyRefiner& refiner,
- const TopologyRefinerData& cb_data)
-{
- const OpenSubdiv_Converter& conv = cb_data.conv;
- const int num_layers = conv.get_num_uv_layers(&conv);
- if (num_layers <= 0) {
- /* No UV maps, we can skip any face-varying data. */
- return true;
- }
- const int num_faces = getNumBaseFaces(refiner);
- size_t uvs_offset = 0;
- for (int layer = 0; layer < num_layers; ++layer) {
- conv.precalc_uv_layer(&conv, layer);
- const int num_uvs = conv.get_num_uvs(&conv);
- /* Fill in UV coordinates. */
- cb_data.uvs->resize(cb_data.uvs->size() + num_uvs * 2);
- conv.get_uvs(&conv, &cb_data.uvs->at(uvs_offset));
- uvs_offset += num_uvs * 2;
- /* Fill in per-corner index of the UV. */
- const int channel = createBaseFVarChannel(refiner, num_uvs);
- for (int face = 0; face < num_faces; ++face) {
- Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
- face,
- channel);
- for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
- const int uv_index = conv.get_face_corner_uv_index(&conv,
- face,
- corner);
- dst_face_uvs[corner] = uv_index;
- }
- }
- conv.finish_uv_layer(&conv);
- }
- return true;
-}
-
-} /* namespace Far */
-} /* namespace OPENSUBDIV_VERSION */
-} /* namespace OpenSubdiv */
-
-namespace {
-
-OpenSubdiv::Sdc::SchemeType get_capi_scheme_type(OpenSubdiv_SchemeType type)
-{
- switch (type) {
- case OSD_SCHEME_BILINEAR:
- return OpenSubdiv::Sdc::SCHEME_BILINEAR;
- case OSD_SCHEME_CATMARK:
- return OpenSubdiv::Sdc::SCHEME_CATMARK;
- case OSD_SCHEME_LOOP:
- return OpenSubdiv::Sdc::SCHEME_LOOP;
- }
- assert(!"Unknown scheme type passed via C-API");
- return OpenSubdiv::Sdc::SCHEME_CATMARK;
-}
-
-OpenSubdiv::Sdc::Options::FVarLinearInterpolation
-get_capi_fvar_linear_interpolation(
- OpenSubdiv_FVarLinearInterpolation linear_interpolation)
-{
- typedef OpenSubdiv::Sdc::Options Options;
- switch (linear_interpolation) {
- case OSD_FVAR_LINEAR_INTERPOLATION_NONE:
- return Options::FVAR_LINEAR_NONE;
- case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY:
- return Options::FVAR_LINEAR_CORNERS_ONLY;
- case OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES:
- return Options::FVAR_LINEAR_BOUNDARIES;
- case OSD_FVAR_LINEAR_INTERPOLATION_ALL:
- return Options::FVAR_LINEAR_ALL;
- }
- assert(!"Unknown fvar linear interpolation passed via C-API");
- return Options::FVAR_LINEAR_NONE;
-}
-
-} /* namespace */
-
-struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
- OpenSubdiv_Converter *converter)
-{
- typedef OpenSubdiv::Sdc::Options Options;
-
- using OpenSubdiv::Far::TopologyRefinerFactory;
- const OpenSubdiv::Sdc::SchemeType scheme_type =
- get_capi_scheme_type(converter->get_scheme_type(converter));
- const Options::FVarLinearInterpolation linear_interpolation =
- get_capi_fvar_linear_interpolation(
- converter->get_fvar_linear_interpolation(converter));
- Options options;
- options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
- options.SetCreasingMethod(Options::CREASE_UNIFORM);
- options.SetFVarLinearInterpolation(linear_interpolation);
-
- TopologyRefinerFactory<TopologyRefinerData>::Options
- topology_options(scheme_type, options);
-#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
- topology_options.validateFullTopology = true;
-#endif
- OpenSubdiv_TopologyRefinerDescr *result = OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefinerDescr);
- TopologyRefinerData cb_data = {*converter, &result->uvs};
- /* We don't use guarded allocation here so we can re-use the refiner
- * for GL mesh creation directly.
- */
- result->osd_refiner =
- TopologyRefinerFactory<TopologyRefinerData>::Create(
- cb_data,
- topology_options);
-
- return result;
-}
-
-void openSubdiv_deleteTopologyRefinerDescr(
- OpenSubdiv_TopologyRefinerDescr *topology_refiner)
-{
- delete topology_refiner->osd_refiner;
- OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefinerDescr);
-}
-
-int openSubdiv_topologyRefinerGetSubdivLevel(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
-{
- using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- return refiner->GetMaxLevel();
-}
-
-int openSubdiv_topologyRefinerGetNumVerts(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
-{
- using OpenSubdiv::Far::TopologyLevel;
- using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- const TopologyLevel &base_level = refiner->GetLevel(0);
- return base_level.GetNumVertices();
-}
-
-int openSubdiv_topologyRefinerGetNumEdges(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
-{
- using OpenSubdiv::Far::TopologyLevel;
- using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- const TopologyLevel &base_level = refiner->GetLevel(0);
- return base_level.GetNumEdges();
-}
-
-int openSubdiv_topologyRefinerGetNumFaces(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
-{
- using OpenSubdiv::Far::TopologyLevel;
- using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- const TopologyLevel &base_level = refiner->GetLevel(0);
- return base_level.GetNumFaces();
-}
-
-int openSubdiv_topologyRefinerGetNumFaceVerts(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int face)
-{
- using OpenSubdiv::Far::TopologyLevel;
- using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- const TopologyLevel &base_level = refiner->GetLevel(0);
- return base_level.GetFaceVertices(face).size();
-}
-
-int openSubdiv_topologyRefnerCompareConverter(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- OpenSubdiv_Converter *converter)
-{
- typedef OpenSubdiv::Sdc::Options Options;
- using OpenSubdiv::Far::ConstIndexArray;
- using OpenSubdiv::Far::TopologyRefiner;
- using OpenSubdiv::Far::TopologyLevel;
- const TopologyRefiner *refiner = topology_refiner->osd_refiner;
- const TopologyLevel &base_level = refiner->GetLevel(0);
- const int num_verts = base_level.GetNumVertices();
- const int num_edges = base_level.GetNumEdges();
- const int num_faces = base_level.GetNumFaces();
- /* Quick preliminary check. */
- OpenSubdiv::Sdc::SchemeType scheme_type =
- get_capi_scheme_type(converter->get_scheme_type(converter));
- if (scheme_type != refiner->GetSchemeType()) {
- return false;
- }
- const Options options = refiner->GetSchemeOptions();
- const Options::FVarLinearInterpolation interp =
- options.GetFVarLinearInterpolation();
- const Options::FVarLinearInterpolation new_interp =
- get_capi_fvar_linear_interpolation(
- converter->get_fvar_linear_interpolation(converter));
- if (new_interp != interp) {
- return false;
- }
- if (converter->get_num_verts(converter) != num_verts ||
- converter->get_num_edges(converter) != num_edges ||
- converter->get_num_faces(converter) != num_faces)
- {
- return false;
- }
- /* Compare all edges. */
- for (int edge = 0; edge < num_edges; ++edge) {
- ConstIndexArray edge_verts = base_level.GetEdgeVertices(edge);
- int conv_edge_verts[2];
- converter->get_edge_verts(converter, edge, conv_edge_verts);
- if (conv_edge_verts[0] != edge_verts[0] ||
- conv_edge_verts[1] != edge_verts[1])
- {
- return false;
- }
- }
- /* Compare all faces. */
- std::vector<int> conv_face_verts;
- for (int face = 0; face < num_faces; ++face) {
- ConstIndexArray face_verts = base_level.GetFaceVertices(face);
- if (face_verts.size() != converter->get_num_face_verts(converter,
- face))
- {
- return false;
- }
- conv_face_verts.resize(face_verts.size());
- converter->get_face_verts(converter, face, &conv_face_verts[0]);
- bool direct_match = true;
- for (int i = 0; i < face_verts.size(); ++i) {
- if (conv_face_verts[i] != face_verts[i]) {
- direct_match = false;
- break;
- }
- }
- if (!direct_match) {
- /* If face didn't match in direct direction we also test if it
- * matches in reversed direction. This is because conversion might
- * reverse loops to make normals consistent.
- */
-#ifdef OPENSUBDIV_ORIENT_TOPOLOGY
- reverse_face_verts(&conv_face_verts[0], conv_face_verts.size());
- for (int i = 0; i < face_verts.size(); ++i) {
- if (conv_face_verts[i] != face_verts[i]) {
- return false;
- }
- }
-#else
- return false;
-#endif
- }
- }
- /* Compare sharpness. */
- for (int edge = 0; edge < num_edges; ++edge) {
- ConstIndexArray edge_faces = base_level.GetEdgeFaces(edge);
- float sharpness = base_level.GetEdgeSharpness(edge);
- float conv_sharpness;
- if (edge_faces.size() == 2) {
- conv_sharpness = converter->get_edge_sharpness(converter, edge);
- }
- else {
- conv_sharpness = OpenSubdiv::Sdc::Crease::SHARPNESS_INFINITE;
- }
- if (sharpness != conv_sharpness) {
- return false;
- }
- }
- return true;
-}
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index ea4f20c5961..9f559ee208b 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -1,149 +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.
- *
- * The Original Code is Copyright (C) 2015 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __OPENSUBDIV_CONVERTER_CAPI_H__
-#define __OPENSUBDIV_CONVERTER_CAPI_H__
+// Copyright 2015 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CONVERTER_CAPI_H_
+#define OPENSUBDIV_CONVERTER_CAPI_H_
+
+#include <stdint.h> // for bool
+
+#include "opensubdiv_capi_type.h"
#ifdef __cplusplus
extern "C" {
#endif
-struct OpenSubdiv_TopologyRefinerDescr;
-typedef struct OpenSubdiv_TopologyRefinerDescr OpenSubdiv_TopologyRefinerDescr;
-
-typedef struct OpenSubdiv_Converter OpenSubdiv_Converter;
-
-typedef enum OpenSubdiv_SchemeType {
- OSD_SCHEME_BILINEAR,
- OSD_SCHEME_CATMARK,
- OSD_SCHEME_LOOP,
-} OpenSubdiv_SchemeType;
-
-typedef enum OpenSubdiv_FVarLinearInterpolation {
- OSD_FVAR_LINEAR_INTERPOLATION_NONE,
- OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
- OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
- OSD_FVAR_LINEAR_INTERPOLATION_ALL,
-} OpenSubdiv_FVarLinearInterpolation;
-
typedef struct OpenSubdiv_Converter {
- /* TODO(sergey): Needs to be implemented. */
- /* OpenSubdiv::Sdc::Options get_options() const; */
-
- OpenSubdiv_SchemeType (*get_scheme_type)(
- const OpenSubdiv_Converter *converter);
-
- OpenSubdiv_FVarLinearInterpolation (*get_fvar_linear_interpolation)(
- const OpenSubdiv_Converter *converter);
-
- int (*get_num_faces)(const OpenSubdiv_Converter *converter);
- int (*get_num_edges)(const OpenSubdiv_Converter *converter);
- int (*get_num_verts)(const OpenSubdiv_Converter *converter);
-
- /* Face relationships. */
- int (*get_num_face_verts)(const OpenSubdiv_Converter *converter,
- int face);
- void (*get_face_verts)(const OpenSubdiv_Converter *converter,
- int face,
- int *face_verts);
- void (*get_face_edges)(const OpenSubdiv_Converter *converter,
- int face,
- int *face_edges);
-
- /* Edge relationships. */
- void (*get_edge_verts)(const OpenSubdiv_Converter *converter,
- int edge,
- int *edge_verts);
- int (*get_num_edge_faces)(const OpenSubdiv_Converter *converter,
- int edge);
- void (*get_edge_faces)(const OpenSubdiv_Converter *converter,
- int edge,
- int *edge_faces);
- float (*get_edge_sharpness)(const OpenSubdiv_Converter *converter,
- int edge);
-
- /* Vertex relationships. */
- int (*get_num_vert_edges)(const OpenSubdiv_Converter *converter, int vert);
- void (*get_vert_edges)(const OpenSubdiv_Converter *converter,
- int vert,
- int *vert_edges);
- int (*get_num_vert_faces)(const OpenSubdiv_Converter *converter, int vert);
- void (*get_vert_faces)(const OpenSubdiv_Converter *converter,
- int vert,
- int *vert_faces);
-
- /* Face-varying data. */
- int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
-
- void (*precalc_uv_layer)(const OpenSubdiv_Converter *converter, int layer);
- void (*finish_uv_layer)(const OpenSubdiv_Converter *converter);
-
- int (*get_num_uvs)(const OpenSubdiv_Converter *converter);
- void (*get_uvs)(const OpenSubdiv_Converter *converter, float *uvs);
-
- int (*get_face_corner_uv_index)(const OpenSubdiv_Converter *converter,
- int face,
- int corner);
-
- /* User data associated with this converter. */
- void (*free_user_data)(const OpenSubdiv_Converter *converter);
- void *user_data;
+ OpenSubdiv_SchemeType (*getSchemeType)(
+ const struct OpenSubdiv_Converter* converter);
+
+ OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
+ const struct OpenSubdiv_Converter* converter);
+
+ // Denotes whether this converter specifies full topology, which includes
+ // vertices, edges, faces, vertices+edges of a face and edges/faces of a
+ // vertex.
+ // Otherwise this converter will only provide number of vertices and faces,
+ // and vertices of faces. The rest of topology will be created by OpenSubdiv.
+ //
+ // NOTE: Even if converter does not provide full topology, it still needs
+ // to provide number of edges and vertices-of-edge. Those are used to assign
+ // topology tags.
+ bool (*specifiesFullTopology)(const struct OpenSubdiv_Converter* converter);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Global geometry counters.
+
+ // Number of faces/edges/vertices in the base mesh.
+ int (*getNumFaces)(const struct OpenSubdiv_Converter* converter);
+ int (*getNumEdges)(const struct OpenSubdiv_Converter* converter);
+ int (*getNumVertices)(const struct OpenSubdiv_Converter* converter);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Face relationships.
+
+ // Number of vertices the face consists of.
+ int (*getNumFaceVertices)(const struct OpenSubdiv_Converter* converter,
+ const int face_index);
+ // Array of vertex indices the face consists of.
+ void (*getFaceVertices)(const struct OpenSubdiv_Converter* converter,
+ const int face_index,
+ int* face_vertices);
+ // Array of edge indices the face consists of.
+ // Aligned with the vertex indices array, edge i connects face vertex i
+ // with face index i+1.
+ void (*getFaceEdges)(const struct OpenSubdiv_Converter *converter,
+ const int face_index,
+ int *face_edges);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Edge relationships.
+
+ // Vertices the edge consists of.
+ void (*getEdgeVertices)(const struct OpenSubdiv_Converter* converter,
+ const int edge_index,
+ int edge_vertices[2]);
+ // Number of faces which are sharing the given edge.
+ int (*getNumEdgeFaces)(const struct OpenSubdiv_Converter* converter,
+ const int edge_index);
+ // Array of face indices which are sharing the given edge.
+ void (*getEdgeFaces)(const struct OpenSubdiv_Converter* converter,
+ const int edge,
+ int* edge_faces);
+ // Edge sharpness (aka crease).
+ float (*getEdgeSharpness)(const struct OpenSubdiv_Converter* converter,
+ const int edge_index);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Vertex relationships.
+
+ // Number of edges which are adjacent to the given vertex.
+ int (*getNumVertexEdges)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index);
+ // Array fo edge indices which are adjacent to the given vertex.
+ void (*getVertexEdges)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index,
+ int* vertex_edges);
+ // Number of faces which are adjacent to the given vertex.
+ int (*getNumVertexFaces)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index);
+ // Array fo face indices which are adjacent to the given vertex.
+ void (*getVertexFaces)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index,
+ int* vertex_faces);
+
+ // Check whether vertex is to be marked as an infinite sharp.
+ // This is a way to make sharp vertices which are adjacent to a loose edges.
+ bool (*isInfiniteSharpVertex)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index);
+
+ // If vertex is not infinitely sharp, this is it's actual sharpness.
+ float (*getVertexSharpness)(const struct OpenSubdiv_Converter* converter,
+ const int vertex_index);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Face-varying data.
+
+ /////////////////////////////////////
+ // UV coordinates.
+
+ // Number of UV layers.
+ int (*getNumUVLayers)(const struct OpenSubdiv_Converter* converter);
+
+ // We need some corner connectivity information, which might not be trivial
+ // to be gathered (might require multiple matching calculations per corver
+ // query).
+ // precalc() is called before any corner connectivity or UV coordinate is
+ // queried from the given layer, allowing converter to calculate and cache
+ // complex complex-to-calculate information.
+ // finish() is called after converter is done porting UV layer to OpenSubdiv,
+ // allowing to free cached data.
+ void (*precalcUVLayer)(const struct OpenSubdiv_Converter* converter,
+ const int layer_index);
+ void (*finishUVLayer)(const struct OpenSubdiv_Converter* converter);
+
+ // Get number of UV coordinates in the current layer (layer which was
+ // specified in precalcUVLayer().
+ int (*getNumUVCoordinates)(const struct OpenSubdiv_Converter* converter);
+ // For the given face index and its corner (known as loop in Blender)
+ // get corrsponding UV coordinate index.
+ int (*getFaceCornerUVIndex)(const struct OpenSubdiv_Converter* converter,
+ const int face_index,
+ const int corner_index);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // User data associated with this converter.
+
+ void (*freeUserData)(const struct OpenSubdiv_Converter* converter);
+ void* user_data;
} OpenSubdiv_Converter;
-OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
- OpenSubdiv_Converter *converter);
-
-void openSubdiv_deleteTopologyRefinerDescr(
- OpenSubdiv_TopologyRefinerDescr *topology_refiner);
-
-/* TODO(sergey): Those calls are not strictly related to conversion.
- * needs some dedicated file perhaps.
- */
-
-int openSubdiv_topologyRefinerGetSubdivLevel(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
-
-int openSubdiv_topologyRefinerGetNumVerts(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
-
-int openSubdiv_topologyRefinerGetNumEdges(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
-
-int openSubdiv_topologyRefinerGetNumFaces(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
-
-int openSubdiv_topologyRefinerGetNumFaceVerts(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int face);
-
-int openSubdiv_topologyRefnerCompareConverter(
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- OpenSubdiv_Converter *converter);
-
#ifdef __cplusplus
}
#endif
-#endif /* __OPENSUBDIV_CONVERTER_CAPI_H__ */
+#endif /* OPENSUBDIV_CONVERTER_CAPI_H_ */
diff --git a/intern/opensubdiv/opensubdiv_device_context_cuda.cc b/intern/opensubdiv/opensubdiv_device_context_cuda.cc
deleted file mode 100644
index 46b66a6b35e..00000000000
--- a/intern/opensubdiv/opensubdiv_device_context_cuda.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Adopted from OpenSubdiv with the following license:
- *
- * Copyright 2015 Pixar
- *
- * Licensed under the Apache License, Version 2.0 (the "Apache License")
- * with the following modification; you may not use this file except in
- * compliance with the Apache License and the following modification to it:
- * Section 6. Trademarks. is deleted and replaced with:
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor
- * and its affiliates, except as required to comply with Section 4(c) of
- * the License and to reproduce the content of the NOTICE file.
- *
- * You may obtain a copy of the Apache License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Apache License with the above modification is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the Apache License for the specific
- * language governing permissions and limitations under the Apache License.
- */
-
-#ifdef OPENSUBDIV_HAS_CUDA
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include "opensubdiv_device_context_cuda.h"
-
-#if defined(_WIN32)
-# include <windows.h>
-#elif defined(__APPLE__)
-# include <OpenGL/OpenGL.h>
-#else
-# include <X11/Xlib.h>
-# include <GL/glx.h>
-#endif
-
-#include <cstdio>
-#include <algorithm>
-#include <cuda.h>
-#include <cuda_runtime_api.h>
-#include <cuda_gl_interop.h>
-
-#define message(fmt, ...)
-//#define message(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
-#define error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
-
-static int _GetCudaDeviceForCurrentGLContext()
-{
- // Find and use the CUDA device for the current GL context
- unsigned int interopDeviceCount = 0;
- int interopDevices[1];
- cudaError_t status = cudaGLGetDevices(&interopDeviceCount, interopDevices,
- 1, cudaGLDeviceListCurrentFrame);
- if (status == cudaErrorNoDevice or interopDeviceCount != 1) {
- message("CUDA no interop devices found.\n");
- return 0;
- }
- int device = interopDevices[0];
-
-#if defined(_WIN32)
- return device;
-
-#elif defined(__APPLE__)
- return device;
-
-#else // X11
- Display * display = glXGetCurrentDisplay();
- int screen = DefaultScreen(display);
- if (device != screen) {
- error("The CUDA interop device (%d) does not match "
- "the screen used by the current GL context (%d), "
- "which may cause slow performance on systems "
- "with multiple GPU devices.", device, screen);
- }
- message("CUDA init using device for current GL context: %d\n", device);
- return device;
-#endif
-}
-
-/* From "NVIDIA GPU Computing SDK 4.2/C/common/inc/cutil_inline_runtime.h": */
-
-/* Beginning of GPU Architecture definitions */
-inline int _ConvertSMVer2Cores_local(int major, int minor)
-{
- /* Defines for GPU Architecture types (using the SM version to determine
- * the # of cores per SM
- */
- typedef struct {
- int SM; /* 0xMm (hexidecimal notation),
- * M = SM Major version,
- * and m = SM minor version
- */
- int Cores;
- } sSMtoCores;
-
- sSMtoCores nGpuArchCoresPerSM[] =
- { { 0x10, 8 }, /* Tesla Generation (SM 1.0) G80 class */
- { 0x11, 8 }, /* Tesla Generation (SM 1.1) G8x class */
- { 0x12, 8 }, /* Tesla Generation (SM 1.2) G9x class */
- { 0x13, 8 }, /* Tesla Generation (SM 1.3) GT200 class */
- { 0x20, 32 }, /* Fermi Generation (SM 2.0) GF100 class */
- { 0x21, 48 }, /* Fermi Generation (SM 2.1) GF10x class */
- { 0x30, 192}, /* Fermi Generation (SM 3.0) GK10x class */
- { -1, -1 }
- };
-
- int index = 0;
- while (nGpuArchCoresPerSM[index].SM != -1) {
- if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor)) {
- return nGpuArchCoresPerSM[index].Cores;
- }
- index++;
- }
- printf("MapSMtoCores undefined SMversion %d.%d!\n", major, minor);
- return -1;
-}
-/* End of GPU Architecture definitions. */
-
-/* This function returns the best GPU (with maximum GFLOPS) */
-inline int cutGetMaxGflopsDeviceId()
-{
- int current_device = 0, sm_per_multiproc = 0;
- int max_compute_perf = 0, max_perf_device = -1;
- int device_count = 0, best_SM_arch = 0;
- int compat_major, compat_minor;
-
- cuDeviceGetCount(&device_count);
- /* Find the best major SM Architecture GPU device. */
- while (current_device < device_count) {
- cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
- if (compat_major > 0 && compat_major < 9999) {
- best_SM_arch = std::max(best_SM_arch, compat_major);
- }
- current_device++;
- }
-
- /* Find the best CUDA capable GPU device. */
- current_device = 0;
- while (current_device < device_count) {
- cuDeviceComputeCapability(&compat_major, &compat_minor, current_device);
- if (compat_major == 9999 && compat_minor == 9999) {
- sm_per_multiproc = 1;
- } else {
- sm_per_multiproc = _ConvertSMVer2Cores_local(compat_major,
- compat_minor);
- }
- int multi_processor_count;
- cuDeviceGetAttribute(&multi_processor_count,
- CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
- current_device);
- int clock_rate;
- cuDeviceGetAttribute(&clock_rate,
- CU_DEVICE_ATTRIBUTE_CLOCK_RATE,
- current_device);
- int compute_perf = multi_processor_count * sm_per_multiproc * clock_rate;
- if (compute_perf > max_compute_perf) {
- /* If we find GPU with SM major > 2, search only these */
- if (best_SM_arch > 2) {
- /* If our device==dest_SM_arch, choose this, or else pass. */
- if (compat_major == best_SM_arch) {
- max_compute_perf = compute_perf;
- max_perf_device = current_device;
- }
- } else {
- max_compute_perf = compute_perf;
- max_perf_device = current_device;
- }
- }
- ++current_device;
- }
- return max_perf_device;
-}
-
-bool CudaDeviceContext::HAS_CUDA_VERSION_4_0()
-{
-#ifdef OPENSUBDIV_HAS_CUDA
- static bool cudaInitialized = false;
- static bool cudaLoadSuccess = true;
- if (!cudaInitialized) {
- cudaInitialized = true;
-
-# ifdef OPENSUBDIV_HAS_CUEW
- cudaLoadSuccess = cuewInit(CUEW_INIT_CUDA) == CUEW_SUCCESS;
- if (!cudaLoadSuccess) {
- fprintf(stderr, "Loading CUDA failed.\n");
- }
-# endif
- // Need to initialize CUDA here so getting device
- // with the maximum FPLOS works fine.
- if (cuInit(0) == CUDA_SUCCESS) {
- // This is to deal with cases like NVidia Optimus,
- // when there might be CUDA library installed but
- // NVidia card is not being active.
- if (cutGetMaxGflopsDeviceId() < 0) {
- cudaLoadSuccess = false;
- }
- }
- else {
- cudaLoadSuccess = false;
- }
- }
- return cudaLoadSuccess;
-#else
- return false;
-#endif
-}
-
-CudaDeviceContext::CudaDeviceContext()
- : _initialized(false) {
-}
-
-CudaDeviceContext::~CudaDeviceContext() {
- cudaDeviceReset();
-}
-
-bool CudaDeviceContext::Initialize()
-{
- /* See if any cuda device is available. */
- int deviceCount = 0;
- cudaGetDeviceCount(&deviceCount);
- message("CUDA device count: %d\n", deviceCount);
- if (deviceCount <= 0) {
- return false;
- }
- cudaGLSetGLDevice(_GetCudaDeviceForCurrentGLContext());
- _initialized = true;
- return true;
-}
-
-#endif /* OPENSUBDIV_HAS_CUDA */
diff --git a/intern/opensubdiv/opensubdiv_device_context_cuda.h b/intern/opensubdiv/opensubdiv_device_context_cuda.h
deleted file mode 100644
index eb30b76f507..00000000000
--- a/intern/opensubdiv/opensubdiv_device_context_cuda.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Adopted from OpenSubdiv with the following license:
- *
- * Copyright 2013 Pixar
- *
- * Licensed under the Apache License, Version 2.0 (the "Apache License")
- * with the following modification; you may not use this file except in
- * compliance with the Apache License and the following modification to it:
- * Section 6. Trademarks. is deleted and replaced with:
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor
- * and its affiliates, except as required to comply with Section 4(c) of
- * the License and to reproduce the content of the NOTICE file.
- *
- * You may obtain a copy of the Apache License at
- *
- * http: //www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Apache License with the above modification is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the Apache License for the specific
- * language governing permissions and limitations under the Apache License.
- *
- */
-
-#ifndef __OPENSUBDIV_DEV_CE_CONTEXT_CUDA_H__
-#define __OPENSUBDIV_DEV_CE_CONTEXT_CUDA_H__
-
-struct ID3D11Device;
-
-class CudaDeviceContext {
-public:
- CudaDeviceContext();
- ~CudaDeviceContext();
-
- static bool HAS_CUDA_VERSION_4_0();
-
- /* Initialze cuda device from the current GL context. */
- bool Initialize();
-
- /* Initialze cuda device from the ID3D11Device/ */
- bool Initialize(ID3D11Device *device);
-
- /* Returns true if the cuda device has already been initialized. */
- bool IsInitialized() const {
- return _initialized;
- }
-private:
- bool _initialized;
-};
-
-#endif /* __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__ */
diff --git a/intern/opensubdiv/opensubdiv_device_context_opencl.cc b/intern/opensubdiv/opensubdiv_device_context_opencl.cc
deleted file mode 100644
index 4cacdc9e845..00000000000
--- a/intern/opensubdiv/opensubdiv_device_context_opencl.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Adopted from OpenSubdiv with the following license:
- *
- * Copyright 2015 Pixar
- *
- * Licensed under the Apache License, Version 2.0 (the "Apache License")
- * with the following modification; you may not use this file except in
- * compliance with the Apache License and the following modification to it:
- * Section 6. Trademarks. is deleted and replaced with:
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor
- * and its affiliates, except as required to comply with Section 4(c) of
- * the License and to reproduce the content of the NOTICE file.
- *
- * You may obtain a copy of the Apache License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Apache License with the above modification is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the Apache License for the specific
- * language governing permissions and limitations under the Apache License.
- *
- */
-
-#ifdef OPENSUBDIV_HAS_OPENCL
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include "opensubdiv_device_context_opencl.h"
-
-#if defined(_WIN32)
-# include <windows.h>
-#elif defined(__APPLE__)
-# include <OpenGL/OpenGL.h>
-#else
-# include <GL/glx.h>
-#endif
-
-#include <cstdio>
-#include <cstring>
-#include <string>
-
-#define message(...) // fprintf(stderr, __VA_ARGS__)
-#define error(...) fprintf(stderr, __VA_ARGS__)
-
-/* Returns the first found platform. */
-static cl_platform_id findPlatform() {
- cl_uint numPlatforms;
- cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clGetPlatformIDs call.\n", ciErrNum);
- return NULL;
- }
- if (numPlatforms == 0) {
- error("No OpenCL platform found.\n");
- return NULL;
- }
- cl_platform_id *clPlatformIDs = new cl_platform_id[numPlatforms];
- ciErrNum = clGetPlatformIDs(numPlatforms, clPlatformIDs, NULL);
- char chBuffer[1024];
- for (cl_uint i = 0; i < numPlatforms; ++i) {
- ciErrNum = clGetPlatformInfo(clPlatformIDs[i], CL_PLATFORM_NAME,
- 1024, chBuffer,NULL);
- if (ciErrNum == CL_SUCCESS) {
- cl_platform_id platformId = clPlatformIDs[i];
- delete[] clPlatformIDs;
- return platformId;
- }
- }
- delete[] clPlatformIDs;
- return NULL;
-}
-
-/* Return. the device in clDevices which supports the extension. */
-static int findExtensionSupportedDevice(cl_device_id *clDevices,
- int numDevices,
- const char *extensionName) {
- /* Find a device that supports sharing with GL/D3D11
- * (SLI / X-fire configurations)
- */
- cl_int ciErrNum;
- for (int i = 0; i < numDevices; ++i) {
- /* Get extensions string size. */
- size_t extensionSize;
- ciErrNum = clGetDeviceInfo(clDevices[i],
- CL_DEVICE_EXTENSIONS, 0, NULL,
- &extensionSize);
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clGetDeviceInfo\n", ciErrNum);
- return -1;
- }
- if (extensionSize > 0) {
- /* Get extensions string. */
- char *extensions = new char[extensionSize];
- ciErrNum = clGetDeviceInfo(clDevices[i], CL_DEVICE_EXTENSIONS,
- extensionSize, extensions,
- &extensionSize);
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clGetDeviceInfo\n", ciErrNum);
- delete[] extensions;
- continue;
- }
- std::string extString(extensions);
- delete[] extensions;
- /* Parse string. This is bit deficient since the extentions
- * is space separated.
- *
- * The actual string would be "cl_khr_d3d11_sharing"
- * or "cl_nv_d3d11_sharing"
- */
- if (extString.find(extensionName) != std::string::npos) {
- return i;
- }
- }
- }
- return -1;
-}
-
-CLDeviceContext::CLDeviceContext()
- : _clContext(NULL),
- _clCommandQueue(NULL) {
-}
-
-CLDeviceContext::~CLDeviceContext() {
- if (_clCommandQueue)
- clReleaseCommandQueue(_clCommandQueue);
- if (_clContext)
- clReleaseContext(_clContext);
-}
-
-bool CLDeviceContext::HAS_CL_VERSION_1_1()
-{
-#ifdef OPENSUBDIV_HAS_CLEW
- static bool clewInitialized = false;
- static bool clewLoadSuccess;
- if (not clewInitialized) {
- clewInitialized = true;
- clewLoadSuccess = clewInit() == CLEW_SUCCESS;
- if (!clewLoadSuccess) {
- error("Loading OpenCL failed.\n");
- }
- }
- return clewLoadSuccess;
-#endif
- return true;
-}
-
-bool CLDeviceContext::Initialize()
-{
-#ifdef OPENSUBDIV_HAS_CLEW
- if (!clGetPlatformIDs) {
- error("Error clGetPlatformIDs function not bound.\n");
- return false;
- }
-#endif
- cl_int ciErrNum;
- cl_platform_id cpPlatform = findPlatform();
-
-#if defined(_WIN32)
- cl_context_properties props[] = {
- CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
- CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
- CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
- 0
- };
-#elif defined(__APPLE__)
- CGLContextObj kCGLContext = CGLGetCurrentContext();
- CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
- cl_context_properties props[] = {
- CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
- 0
- };
-#else
- cl_context_properties props[] = {
- CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
- CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
- CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
- 0
- };
-#endif
-
-#if defined(__APPLE__)
- _clContext = clCreateContext(props, 0, NULL, clLogMessagesToStdoutAPPLE,
- NULL, &ciErrNum);
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clCreateContext\n", ciErrNum);
- return false;
- }
-
- size_t devicesSize = 0;
- clGetGLContextInfoAPPLE(_clContext, kCGLContext,
- CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
- 0, NULL, &devicesSize);
- int numDevices = int(devicesSize / sizeof(cl_device_id));
- if (numDevices == 0) {
- error("No sharable devices.\n");
- return false;
- }
- cl_device_id *clDevices = new cl_device_id[numDevices];
- clGetGLContextInfoAPPLE(_clContext, kCGLContext,
- CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
- numDevices * sizeof(cl_device_id), clDevices, NULL);
- int clDeviceUsed = 0;
-
-#else // not __APPLE__
- /* Get the number of GPU devices available to the platform. */
- cl_uint numDevices = 0;
- clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
- if (numDevices == 0) {
- error("No CL GPU device found.\n");
- return false;
- }
-
- /* Create the device list. */
- cl_device_id *clDevices = new cl_device_id[numDevices];
- clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);
-
- const char *extension = "cl_khr_gl_sharing";
- int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
- extension);
-
- if (clDeviceUsed < 0) {
- error("No device found that supports CL/GL context sharing\n");
- delete[] clDevices;
- return false;
- }
-
- _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
- NULL, NULL, &ciErrNum);
-#endif // not __APPLE__
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clCreateContext\n", ciErrNum);
- delete[] clDevices;
- return false;
- }
- _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
- 0, &ciErrNum);
- delete[] clDevices;
- if (ciErrNum != CL_SUCCESS) {
- error("Error %d in clCreateCommandQueue\n", ciErrNum);
- return false;
- }
- return true;
-}
-
-#endif /* OPENSUBDIV_HAS_OPENCL */
diff --git a/intern/opensubdiv/opensubdiv_device_context_opencl.h b/intern/opensubdiv/opensubdiv_device_context_opencl.h
deleted file mode 100644
index a640dce1f07..00000000000
--- a/intern/opensubdiv/opensubdiv_device_context_opencl.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Adopted from OpenSubdiv with the following license:
- *
- * Copyright 2015 Pixar
- *
- * Licensed under the Apache License, Version 2.0 (the "Apache License")
- * with the following modification; you may not use this file except in
- * compliance with the Apache License and the following modification to it:
- * Section 6. Trademarks. is deleted and replaced with:
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor
- * and its affiliates, except as required to comply with Section 4(c) of
- * the License and to reproduce the content of the NOTICE file.
- *
- * You may obtain a copy of the Apache License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Apache License with the above modification is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the Apache License for the specific
- * language governing permissions and limitations under the Apache License.
- *
- */
-
-#ifndef __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__
-#define __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__
-
-#include <opensubdiv/osd/opencl.h>
-
-class CLDeviceContext {
-public:
- CLDeviceContext();
- ~CLDeviceContext();
-
- static bool HAS_CL_VERSION_1_1 ();
-
- bool Initialize();
-
- bool IsInitialized() const {
- return (_clContext != NULL);
- }
-
- cl_context GetContext() const {
- return _clContext;
- }
- cl_command_queue GetCommandQueue() const {
- return _clCommandQueue;
- }
-
-protected:
- cl_context _clContext;
- cl_command_queue _clCommandQueue;
-};
-
-#endif /* __OPENSUBDIV_DEV_CE_CONTEXT_OPENCL_H__ */
diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.cc b/intern/opensubdiv/opensubdiv_evaluator_capi.cc
deleted file mode 100644
index fb5313b8501..00000000000
--- a/intern/opensubdiv/opensubdiv_evaluator_capi.cc
+++ /dev/null
@@ -1,516 +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.
- *
- * The Original Code is Copyright (C) 2015 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "opensubdiv_capi.h"
-
-#include <cstdio>
-#include <vector>
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include <opensubdiv/far/patchMap.h>
-#include <opensubdiv/far/patchTable.h>
-#include <opensubdiv/far/patchTableFactory.h>
-#include <opensubdiv/osd/cpuEvaluator.h>
-#include <opensubdiv/osd/cpuPatchTable.h>
-#include <opensubdiv/osd/cpuVertexBuffer.h>
-#include <opensubdiv/osd/mesh.h>
-#include <opensubdiv/osd/types.h>
-
-#include "opensubdiv_intern.h"
-#include "opensubdiv_topology_refiner.h"
-
-#include "MEM_guardedalloc.h"
-
-using OpenSubdiv::Osd::BufferDescriptor;
-using OpenSubdiv::Osd::PatchCoord;
-using OpenSubdiv::Far::PatchMap;
-using OpenSubdiv::Far::PatchTable;
-using OpenSubdiv::Far::PatchTableFactory;
-using OpenSubdiv::Far::StencilTable;
-using OpenSubdiv::Far::StencilTableFactory;
-using OpenSubdiv::Far::TopologyRefiner;
-
-namespace {
-
-/* Helper class to wrap numerous of patch coords into a buffer.
- * Used to pass coordinates to the CPU evaluator. Other evaluators
- * are not supported.
- */
-class PatchCoordBuffer : public std::vector<PatchCoord> {
-public:
- static PatchCoordBuffer *Create(int size)
- {
- PatchCoordBuffer *buffer = new PatchCoordBuffer();
- buffer->resize(size);
- return buffer;
- }
- PatchCoord *BindCpuBuffer() {
- return (PatchCoord*)&(*this)[0];
- }
- int GetNumVertices() {
- return size();
- }
- void UpdateData(const PatchCoord *patch_coords,
- int num_patch_coords)
- {
- memcpy(&(*this)[0],
- (void*)patch_coords,
- num_patch_coords * sizeof(PatchCoord));
- }
-};
-
-/* Helper class to wrap single of patch coord into a buffer.
- * Used to pass coordinates to the CPU evaluator. Other evaluators
- * are not supported.
- */
-class SinglePatchCoordBuffer {
-public:
- SinglePatchCoordBuffer() {
- }
- SinglePatchCoordBuffer(const PatchCoord& patch_coord)
- : patch_coord_(patch_coord){
- }
- static SinglePatchCoordBuffer *Create()
- {
- SinglePatchCoordBuffer *buffer = new SinglePatchCoordBuffer();
- return buffer;
- }
- PatchCoord *BindCpuBuffer() {
- return (PatchCoord*)&patch_coord_;
- }
- int GetNumVertices() {
- return 1;
- }
- void UpdateData(const PatchCoord& patch_coord)
- {
- patch_coord_ = patch_coord;
- }
-protected:
- PatchCoord patch_coord_;
-};
-
-/* Helper class which is aimed to be used in cases when buffer
- * is small enough and better to be allocated in stack rather
- * than in heap.
- *
- * TODO(sergey): Check if bare arrays could be used by CPU evaluator.
- */
-template <int element_size, int num_verts>
-class StackAllocatedBuffer {
-public:
- static PatchCoordBuffer *Create(int /*size*/)
- {
- StackAllocatedBuffer<element_size, num_verts> *buffer =
- new StackAllocatedBuffer<element_size, num_verts>();
- return buffer;
- }
- float *BindCpuBuffer() {
- return &data_[0];
- }
- int GetNumVertices() {
- return num_verts;
- }
- /* TODO(sergey): Support UpdateData(). */
-protected:
- float data_[element_size * num_verts];
-};
-
-/* Volatile evaluator which can be used from threads.
- *
- * TODO(sergey): Make it possible to evaluate coordinates in chunks.
- */
-template<typename SRC_VERTEX_BUFFER,
- typename EVAL_VERTEX_BUFFER,
- typename STENCIL_TABLE,
- typename PATCH_TABLE,
- typename EVALUATOR,
- typename DEVICE_CONTEXT = void>
-class VolatileEvalOutput {
-public:
- typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
-
- VolatileEvalOutput(const StencilTable *vertex_stencils,
- const StencilTable *varying_stencils,
- int num_coarse_verts,
- int num_total_verts,
- const PatchTable *patch_table,
- EvaluatorCache *evaluator_cache = NULL,
- DEVICE_CONTEXT *device_context = NULL)
- : src_desc_( /*offset*/ 0, /*length*/ 3, /*stride*/ 3),
- src_varying_desc_(/*offset*/ 0, /*length*/ 3, /*stride*/ 3),
- num_coarse_verts_(num_coarse_verts),
- evaluator_cache_ (evaluator_cache),
- device_context_(device_context)
- {
- using OpenSubdiv::Osd::convertToCompatibleStencilTable;
- src_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_verts, device_context_);
- src_varying_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_verts, device_context_);
- patch_table_ = PATCH_TABLE::Create(patch_table, device_context_);
- patch_coords_ = NULL;
- vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(vertex_stencils,
- device_context_);
- varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
- device_context_);
- }
-
- ~VolatileEvalOutput()
- {
- delete src_data_;
- delete src_varying_data_;
- delete patch_table_;
- delete vertex_stencils_;
- delete varying_stencils_;
- }
-
- void UpdateData(const float *src, int start_vertex, int num_vertices)
- {
- src_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
- }
-
- void UpdateVaryingData(const float *src, int start_vertex, int num_vertices)
- {
- src_varying_data_->UpdateData(src,
- start_vertex,
- num_vertices,
- device_context_);
- }
-
- void Refine()
- {
- BufferDescriptor dst_desc = src_desc_;
- dst_desc.offset += num_coarse_verts_ * src_desc_.stride;
-
- const EVALUATOR *eval_instance =
- OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
- src_desc_,
- dst_desc,
- device_context_);
-
- EVALUATOR::EvalStencils(src_data_, src_desc_,
- src_data_, dst_desc,
- vertex_stencils_,
- eval_instance,
- device_context_);
-
- dst_desc = src_varying_desc_;
- dst_desc.offset += num_coarse_verts_ * src_varying_desc_.stride;
- eval_instance =
- OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
- src_varying_desc_,
- dst_desc,
- device_context_);
-
- EVALUATOR::EvalStencils(src_varying_data_, src_varying_desc_,
- src_varying_data_, dst_desc,
- varying_stencils_,
- eval_instance,
- device_context_);
- }
-
- void EvalPatchCoord(PatchCoord& patch_coord, float P[3])
- {
- StackAllocatedBuffer<6, 1> vertex_data;
- BufferDescriptor vertex_desc(0, 3, 6);
- SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
- const EVALUATOR *eval_instance =
- OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
- src_desc_,
- vertex_desc,
- device_context_);
- EVALUATOR::EvalPatches(src_data_, src_desc_,
- &vertex_data, vertex_desc,
- patch_coord_buffer.GetNumVertices(),
- &patch_coord_buffer,
- patch_table_, eval_instance, device_context_);
- float *refined_verts = vertex_data.BindCpuBuffer();
- memcpy(P, refined_verts, sizeof(float) * 3);
- }
-
- void EvalPatchesWithDerivatives(PatchCoord& patch_coord,
- float P[3],
- float dPdu[3],
- float dPdv[3])
- {
- StackAllocatedBuffer<6, 1> vertex_data, derivatives;
- BufferDescriptor vertex_desc(0, 3, 6),
- du_desc(0, 3, 6),
- dv_desc(3, 3, 6);
- SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
- const EVALUATOR *eval_instance =
- OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
- src_desc_,
- vertex_desc,
- du_desc,
- dv_desc,
- device_context_);
- EVALUATOR::EvalPatches(src_data_, src_desc_,
- &vertex_data, vertex_desc,
- &derivatives, du_desc,
- &derivatives, dv_desc,
- patch_coord_buffer.GetNumVertices(),
- &patch_coord_buffer,
- patch_table_, eval_instance, device_context_);
- float *refined_verts = vertex_data.BindCpuBuffer();
- memcpy(P, refined_verts, sizeof(float) * 3);
- if (dPdu != NULL || dPdv != NULL) {
- float *refined_drivatives = derivatives.BindCpuBuffer();
- if (dPdu) {
- memcpy(dPdu, refined_drivatives, sizeof(float) * 3);
- }
- if (dPdv) {
- memcpy(dPdv, refined_drivatives + 3, sizeof(float) * 3);
- }
- }
- }
-
- void EvalPatchVarying(PatchCoord& patch_coord,
- float varying[3]) {
- StackAllocatedBuffer<3, 1> varying_data;
- BufferDescriptor varying_desc(0, 3, 3);
- SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
- EVALUATOR const *eval_instance =
- OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
- src_varying_desc_,
- varying_desc,
- device_context_);
-
- EVALUATOR::EvalPatches(src_varying_data_, src_varying_desc_,
- &varying_data, varying_desc,
- patch_coord_buffer.GetNumVertices(),
- &patch_coord_buffer,
- patch_table_, eval_instance, device_context_);
- float *refined_varying = varying_data.BindCpuBuffer();
- memcpy(varying, refined_varying, sizeof(float) * 3);
- }
-private:
- SRC_VERTEX_BUFFER *src_data_;
- SRC_VERTEX_BUFFER *src_varying_data_;
- PatchCoordBuffer *patch_coords_;
- PATCH_TABLE *patch_table_;
- BufferDescriptor src_desc_;
- BufferDescriptor src_varying_desc_;
- int num_coarse_verts_;
-
- const STENCIL_TABLE *vertex_stencils_;
- const STENCIL_TABLE *varying_stencils_;
-
- EvaluatorCache *evaluator_cache_;
- DEVICE_CONTEXT *device_context_;
-};
-
-} /* namespace */
-
-typedef VolatileEvalOutput<OpenSubdiv::Osd::CpuVertexBuffer,
- OpenSubdiv::Osd::CpuVertexBuffer,
- OpenSubdiv::Far::StencilTable,
- OpenSubdiv::Osd::CpuPatchTable,
- OpenSubdiv::Osd::CpuEvaluator> CpuEvalOutput;
-
-typedef struct OpenSubdiv_EvaluatorDescr {
- CpuEvalOutput *eval_output;
- const PatchMap *patch_map;
- const PatchTable *patch_table;
-} OpenSubdiv_EvaluatorDescr;
-
-OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(
- OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- int subsurf_level)
-{
- /* TODO(sergey): Look into re-using refiner with GLMesh. */
- TopologyRefiner *refiner = topology_refiner->osd_refiner;
- if(refiner == NULL) {
- /* Happens on bad topology. */
- return NULL;
- }
- /* Apply uniform refinement to the mesh so that we can use the
- * limit evaluation API features.
- */
- TopologyRefiner::UniformOptions options(subsurf_level);
- refiner->RefineUniform(options);
- /* Generate stencil table to update the bi-cubic patches control
- * vertices after they have been re-posed (both for vertex & varying
- * interpolation).
- */
- StencilTableFactory::Options vertex_stencil_options;
- vertex_stencil_options.generateOffsets = true;
- vertex_stencil_options.generateIntermediateLevels = false;
- const StencilTable *vertex_stencils =
- StencilTableFactory::Create(*refiner, vertex_stencil_options);
- StencilTableFactory::Options varying_stencil_options;
- varying_stencil_options.generateOffsets = true;
- varying_stencil_options.generateIntermediateLevels = false;
- varying_stencil_options.interpolationMode =
- StencilTableFactory::INTERPOLATE_VARYING;
- const StencilTable *varying_stencils =
- StencilTableFactory::Create(*refiner, varying_stencil_options);
- /* Generate bi-cubic patch table for the limit surface. */
- PatchTableFactory::Options poptions;
- poptions.SetEndCapType(PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
- const PatchTable *patch_table =
- PatchTableFactory::Create(*refiner, poptions);
- /* Append local points stencils. */
- const StencilTable *local_point_stencil_table =
- patch_table->GetLocalPointStencilTable();
- if (local_point_stencil_table != NULL) {
- const StencilTable *table =
- StencilTableFactory::AppendLocalPointStencilTable(
- *refiner,
- vertex_stencils,
- local_point_stencil_table);
- delete vertex_stencils;
- vertex_stencils = table;
- }
- const StencilTable *local_point_varying_stencil_table =
- patch_table->GetLocalPointVaryingStencilTable();
- if (local_point_varying_stencil_table != NULL) {
- const StencilTable *table =
- StencilTableFactory::AppendLocalPointStencilTable(
- *refiner,
- varying_stencils,
- local_point_varying_stencil_table);
- delete varying_stencils;
- varying_stencils = table;
- }
-
- /* Total number of vertices = coarse verts + refined verts + gregory
- * basis verts.
- */
- const int num_total_verts = vertex_stencils->GetNumControlVertices() +
- vertex_stencils->GetNumStencils();
- const int num_coarse_verts = refiner->GetLevel(0).GetNumVertices();
- /* Create OpenSubdiv's CPU side evaluator. */
- CpuEvalOutput *eval_output = new CpuEvalOutput(vertex_stencils,
- varying_stencils,
- num_coarse_verts,
- num_total_verts,
- patch_table);
- OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
- /* Wrap everything we need into an object which we control from our
- * side.
- */
- OpenSubdiv_EvaluatorDescr *evaluator_descr;
- evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorDescr);
- evaluator_descr->eval_output = eval_output;
- evaluator_descr->patch_map = patch_map;
- evaluator_descr->patch_table = patch_table;
- /* TOOD(sergey): Look into whether we've got duplicated stencils arrays. */
- delete varying_stencils;
- delete vertex_stencils;
- return evaluator_descr;
-}
-
-void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr)
-{
- delete evaluator_descr->eval_output;
- delete evaluator_descr->patch_map;
- delete evaluator_descr->patch_table;
- OBJECT_GUARDED_DELETE(evaluator_descr, OpenSubdiv_EvaluatorDescr);
-}
-
-void openSubdiv_setEvaluatorCoarsePositions(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const float *positions,
- int start_vertex_index,
- int num_vertices)
-{
- /* TODO(sergey): Add sanity check on indices. */
- evaluator_descr->eval_output->UpdateData(positions,
- start_vertex_index,
- num_vertices);
-}
-
-void openSubdiv_setEvaluatorVaryingData(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const float *varying_data,
- int start_vertex_index,
- int num_vertices)
-{
- /* TODO(sergey): Add sanity check on indices. */
- evaluator_descr->eval_output->UpdateVaryingData(varying_data,
- start_vertex_index,
- num_vertices);
-}
-
-void openSubdiv_setEvaluatorCoarsePositionsFromBuffer(
- OpenSubdiv_EvaluatorDescr *evaluator_descr,
- const void *buffer,
- int start_offset,
- int stride,
- int start_vertex_index,
- int num_vertices)
-{
- const unsigned char *current_buffer = (unsigned char *)buffer;
- current_buffer += start_offset;
- /* TODO(sergey): Add sanity check on indices. */
- for (int i = 0; i < num_vertices; ++i) {
- const int current_vertex_index = start_vertex_index + i;
- evaluator_descr->eval_output->UpdateData((float *)current_buffer,
- current_vertex_index,
- 1);
- current_buffer += stride;
- }
-}
-
-void openSubdiv_refineEvaluator(OpenSubdiv_EvaluatorDescr *evaluator_descr)
-{
- evaluator_descr->eval_output->Refine();
-}
-
-void openSubdiv_evaluateLimit(OpenSubdiv_EvaluatorDescr *evaluator_descr,
- int osd_face_index,
- float face_u, float face_v,
- float P[3],
- float dPdu[3],
- float dPdv[3])
-{
- assert((face_u >= 0.0f) && (face_u <= 1.0f) && (face_v >= 0.0f) && (face_v <= 1.0f));
- const PatchTable::PatchHandle *handle =
- evaluator_descr->patch_map->FindPatch(osd_face_index, face_u, face_v);
- PatchCoord patch_coord(*handle, face_u, face_v);
- if (dPdu != NULL || dPdv != NULL) {
- evaluator_descr->eval_output->EvalPatchesWithDerivatives(patch_coord,
- P,
- dPdu,
- dPdv);
- }
- else {
- evaluator_descr->eval_output->EvalPatchCoord(patch_coord, P);
- }
-}
-
-void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
- int osd_face_index,
- float face_u, float face_v,
- float varying[3])
-{
- assert((face_u >= 0.0f) && (face_u <= 1.0f) && (face_v >= 0.0f) && (face_v <= 1.0f));
- const PatchTable::PatchHandle *handle =
- evaluator_descr->patch_map->FindPatch(osd_face_index, face_u, face_v);
- PatchCoord patch_coord(*handle, face_u, face_v);
- evaluator_descr->eval_output->EvalPatchVarying(patch_coord, varying);
-}
diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.h b/intern/opensubdiv/opensubdiv_evaluator_capi.h
new file mode 100644
index 00000000000..eda5d614635
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_evaluator_capi.h
@@ -0,0 +1,120 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_EVALUATOR_CAPI_H_
+#define OPENSUBDIV_EVALUATOR_CAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct OpenSubdiv_EvaluatorInternal;
+struct OpenSubdiv_TopologyRefiner;
+
+typedef struct OpenSubdiv_Evaluator {
+ // Set coarse positions from a continuous array of coordinates.
+ void (*setCoarsePositions)(struct OpenSubdiv_Evaluator* evaluator,
+ const float* positions,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set varying data from a continuous array of data.
+ void (*setVaryingData)(struct OpenSubdiv_Evaluator* evaluator,
+ const float* varying_data,
+ const int start_vertex_index, const int num_vertices);
+ // Set face varying data from a continuous array of data.
+ //
+ // TODO(sergey): Find a better name for vertex here. It is not the vertex of
+ // geometry, but a vertex of UV map.
+ void (*setFaceVaryingData)(struct OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const float* face_varying_data,
+ const int start_vertex_index,
+ const int num_vertices);
+
+ // Set coarse vertex position from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ void (*setCoarsePositionsFromBuffer)(struct OpenSubdiv_Evaluator* evaluator,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set varying data from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ void (*setVaryingDataFromBuffer)(struct OpenSubdiv_Evaluator* evaluator,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+ // Set face varying data from a continuous memory buffer where
+ // first coordinate starts at offset of `start_offset` and there is `stride`
+ // bytes between adjacent vertex coordinates.
+ //
+ // TODO(sergey): Find a better name for vertex here. It is not the vertex of
+ // geometry, but a vertex of UV map.
+ void (*setFaceVaryingDataFromBuffer)(struct OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const void* buffer,
+ const int start_offset,
+ const int stride,
+ const int start_vertex_index,
+ const int num_vertices);
+
+ // Refine after coarse positions update.
+ void (*refine)(struct OpenSubdiv_Evaluator* evaluator);
+
+ // Evaluate given ptex face at given bilinear coordinate.
+ // If derivatives are NULL, they will not be evaluated.
+ void (*evaluateLimit)(struct OpenSubdiv_Evaluator* evaluator,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float P[3], float dPdu[3], float dPdv[3]);
+
+ // Evaluate varying data at a given bilinear coordinate of given ptex face.
+ void (*evaluateVarying)(struct OpenSubdiv_Evaluator* evaluator,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float varying[3]);
+
+ // Evaluate face-varying data at a given bilinear coordinate of given
+ // ptex face.
+ void (*evaluateFaceVarying)(struct OpenSubdiv_Evaluator* evaluator,
+ const int face_varying_channel,
+ const int ptex_face_index,
+ float face_u, float face_v,
+ float face_varying[2]);
+
+ // Internal storage for the use in this module only.
+ //
+ // This is where actual OpenSubdiv's evaluator is living.
+ struct OpenSubdiv_EvaluatorInternal* internal;
+} OpenSubdiv_Evaluator;
+
+OpenSubdiv_Evaluator* openSubdiv_createEvaluatorFromTopologyRefiner(
+ struct OpenSubdiv_TopologyRefiner* topology_refiner);
+
+void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator* evaluator);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // OPENSUBDIV_EVALUATOR_CAPI_H_
diff --git a/intern/opensubdiv/opensubdiv_gl_mesh_capi.h b/intern/opensubdiv/opensubdiv_gl_mesh_capi.h
new file mode 100644
index 00000000000..971f6b9dcd3
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_gl_mesh_capi.h
@@ -0,0 +1,92 @@
+// Copyright 2013 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
+#define OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
+
+#include <stdint.h> // for bool
+
+#include "opensubdiv_capi_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct OpenSubdiv_GLMeshInternal;
+
+// Mesh which is displayable in OpenGL context.
+typedef struct OpenSubdiv_GLMesh {
+ //////////////////////////////////////////////////////////////////////////////
+ // Subdivision/topology part.
+
+ // Returns the GL index buffer containing the patch control vertices.
+ unsigned int (*getPatchIndexBuffer)(struct OpenSubdiv_GLMesh* gl_mesh);
+
+ // Bind GL buffer which contains vertices (VBO).
+ // TODO(sergey): Is this a coarse vertices?
+ void (*bindVertexBuffer)(struct OpenSubdiv_GLMesh* gl_mesh);
+
+ // Set coarse positions from a continuous array of coordinates.
+ void (*setCoarsePositions)(struct OpenSubdiv_GLMesh* gl_mesh,
+ const float* positions,
+ const int start_vertex,
+ const int num_vertices);
+ // TODO(sergey): setCoarsePositionsFromBuffer().
+
+ // Refine after coarse positions update.
+ void (*refine)(struct OpenSubdiv_GLMesh* gl_mesh);
+
+ // Synchronize after coarse positions update and refine.
+ void (*synchronize)(struct OpenSubdiv_GLMesh* gl_mesh);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Drawing part.
+
+ // Prepare mesh for display.
+ void (*prepareDraw)(struct OpenSubdiv_GLMesh* gl_mesh,
+ const bool use_osd_glsl,
+ const int active_uv_index);
+
+ // Draw given range of patches.
+ //
+ // If fill_quads is false, then patches are drawn in wireframe.
+ void (*drawPatches)(struct OpenSubdiv_GLMesh *gl_mesh,
+ const bool fill_quads,
+ const int start_patch, const int num_patches);
+
+ // Internal storage for the use in this module only.
+ //
+ // Tease: This contains an actual OpenSubdiv's Mesh object.
+ struct OpenSubdiv_GLMeshInternal* internal;
+} OpenSubdiv_GLMesh;
+
+OpenSubdiv_GLMesh* openSubdiv_createOsdGLMeshFromTopologyRefiner(
+ struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ eOpenSubdivEvaluator evaluator_type);
+
+void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
+
+// Global resources needed for GL mesh drawing.
+bool openSubdiv_initGLMeshDrawingResources(void);
+void openSubdiv_deinitGLMeshDrawingResources(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
deleted file mode 100644
index d28b48ddd18..00000000000
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ /dev/null
@@ -1,788 +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.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "opensubdiv_capi.h"
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#include <cstdio>
-#include <cmath>
-#include <GL/glew.h>
-
-#include <opensubdiv/osd/glMesh.h>
-
-#ifdef OPENSUBDIV_HAS_CUDA
-# include <opensubdiv/osd/cudaGLVertexBuffer.h>
-#endif /* OPENSUBDIV_HAS_CUDA */
-
-#include <opensubdiv/osd/cpuGLVertexBuffer.h>
-#include <opensubdiv/osd/cpuEvaluator.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "opensubdiv_capi.h"
-#include "opensubdiv_gl_mesh.h"
-#include "opensubdiv_topology_refiner.h"
-
-using OpenSubdiv::Osd::GLMeshInterface;
-
-extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
-extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
-extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
-
-/* TODO(sergey): This is bit of bad level calls :S */
-extern "C" {
-void copy_m3_m3(float m1[3][3], float m2[3][3]);
-void copy_m3_m4(float m1[3][3], float m2[4][4]);
-void adjoint_m3_m3(float m1[3][3], float m[3][3]);
-float determinant_m3_array(float m[3][3]);
-bool invert_m3_m3(float m1[3][3], float m2[3][3]);
-bool invert_m3(float m[3][3]);
-void transpose_m3(float mat[3][3]);
-}
-
-#define MAX_LIGHTS 8
-#define SUPPORT_COLOR_MATERIAL
-
-typedef struct Light {
- float position[4];
- float ambient[4];
- float diffuse[4];
- float specular[4];
- float spot_direction[4];
-#ifdef SUPPORT_COLOR_MATERIAL
- float constant_attenuation;
- float linear_attenuation;
- float quadratic_attenuation;
- float spot_cutoff;
- float spot_exponent;
- float spot_cos_cutoff;
- float pad, pad2;
-#endif
-} Light;
-
-typedef struct Lighting {
- Light lights[MAX_LIGHTS];
- int num_enabled;
-} Lighting;
-
-typedef struct Transform {
- float projection_matrix[16];
- float model_view_matrix[16];
- float normal_matrix[9];
-} Transform;
-
-static bool g_use_osd_glsl = false;
-static int g_active_uv_index = 0;
-
-static GLuint g_flat_fill_solid_program = 0;
-static GLuint g_flat_fill_texture2d_program = 0;
-static GLuint g_smooth_fill_solid_program = 0;
-static GLuint g_smooth_fill_texture2d_program = 0;
-
-static GLuint g_flat_fill_solid_shadeless_program = 0;
-static GLuint g_flat_fill_texture2d_shadeless_program = 0;
-static GLuint g_smooth_fill_solid_shadeless_program = 0;
-static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
-
-static GLuint g_wireframe_program = 0;
-
-static GLuint g_lighting_ub = 0;
-static Lighting g_lighting_data;
-static Transform g_transform;
-
-struct OpenSubdiv_GLMeshFVarData
-{
- OpenSubdiv_GLMeshFVarData() :
- texture_buffer(0), offset_buffer(0) {
- }
-
- ~OpenSubdiv_GLMeshFVarData()
- {
- Release();
- }
-
- void Release()
- {
- if (texture_buffer) {
- glDeleteTextures(1, &texture_buffer);
- }
- if (offset_buffer) {
- glDeleteTextures(1, &offset_buffer);
- }
- texture_buffer = 0;
- offset_buffer = 0;
- fvar_width = 0;
- channel_offsets.clear();
- }
-
- void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
- const OpenSubdiv::Far::PatchTable *patch_table,
- int fvar_width,
- const float *fvar_src_data)
- {
- Release();
-
- this->fvar_width = fvar_width;
-
- /* Expand fvar data to per-patch array */
- const int max_level = refiner->GetMaxLevel();
- const int num_channels = patch_table->GetNumFVarChannels();
- std::vector<float> data;
- int fvar_data_offset = 0;
- channel_offsets.resize(num_channels);
- for (int channel = 0; channel < num_channels; ++channel) {
- OpenSubdiv::Far::ConstIndexArray indices =
- patch_table->GetFVarValues(channel);
-
- channel_offsets[channel] = data.size();
- data.reserve(data.size() + indices.size() * fvar_width);
-
- for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
- int index = indices[fvert] * fvar_width;
- for (int i = 0; i < fvar_width; ++i) {
- data.push_back(fvar_src_data[fvar_data_offset + index++]);
- }
- }
- if (refiner->IsUniform()) {
- const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
- fvar_data_offset += num_values_max * fvar_width;
- } else {
- const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
- fvar_data_offset += num_values_total * fvar_width;
- }
- }
-
- GLuint buffer;
- glGenBuffers(1, &buffer);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
- &data[0], GL_STATIC_DRAW);
-
- glGenTextures(1, &texture_buffer);
- glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
-
- glDeleteBuffers(1, &buffer);
-
- glGenBuffers(1, &buffer);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
- &channel_offsets[0], GL_STATIC_DRAW);
-
- glGenTextures(1, &offset_buffer);
- glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
- glBindTexture(GL_TEXTURE_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
- GLuint texture_buffer;
- GLuint offset_buffer;
- std::vector<int> channel_offsets;
- int fvar_width;
-};
-
-namespace {
-
-GLuint compileShader(GLenum shaderType,
- const char *version,
- const char *define,
- const char *source)
-{
- const char *sources[] = {
- version,
- define,
-#ifdef SUPPORT_COLOR_MATERIAL
- "#define SUPPORT_COLOR_MATERIAL\n",
-#else
- "",
-#endif
- source,
- };
-
- GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 4, sources, NULL);
- glCompileShader(shader);
-
- GLint status;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- GLchar emsg[1024];
- glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
- fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
- fprintf(stderr, "Version: %s\n", version);
- fprintf(stderr, "Defines: %s\n", define);
- fprintf(stderr, "Source: %s\n", source);
- return 0;
- }
-
- return shader;
-}
-
-GLuint linkProgram(const char *version, const char *define)
-{
- GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
- version,
- define,
- datatoc_gpu_shader_opensubdiv_vertex_glsl);
- if (vertexShader == 0) {
- return 0;
- }
- GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
- version,
- define,
- datatoc_gpu_shader_opensubdiv_geometry_glsl);
- if (geometryShader == 0) {
- return 0;
- }
- GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
- version,
- define,
- datatoc_gpu_shader_opensubdiv_fragment_glsl );
- if (fragmentShader == 0) {
- return 0;
- }
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, vertexShader);
- glAttachShader(program, geometryShader);
- glAttachShader(program, fragmentShader);
-
- glBindAttribLocation(program, 0, "position");
- glBindAttribLocation(program, 1, "normal");
-
- glLinkProgram(program);
-
- glDeleteShader(vertexShader);
- glDeleteShader(geometryShader);
- glDeleteShader(fragmentShader);
-
- GLint status;
- glGetProgramiv(program, GL_LINK_STATUS, &status);
- if (status == GL_FALSE) {
- GLchar emsg[1024];
- glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
- fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
- fprintf(stderr, "Defines: %s\n", define);
- glDeleteProgram(program);
- return 0;
- }
-
- glUniformBlockBinding(program,
- glGetUniformBlockIndex(program, "Lighting"),
- 0);
-
- if (GLEW_VERSION_4_1) {
- glProgramUniform1i(program,
- glGetUniformLocation(program, "texture_buffer"),
- 0); /* GL_TEXTURE0 */
-
- glProgramUniform1i(program,
- glGetUniformLocation(program, "FVarDataOffsetBuffer"),
- 30); /* GL_TEXTURE30 */
-
- glProgramUniform1i(program,
- glGetUniformLocation(program, "FVarDataBuffer"),
- 31); /* GL_TEXTURE31 */
- }
- else {
- glUseProgram(program);
- glUniform1i(glGetUniformLocation(program, "texture_buffer"), 0); /* GL_TEXTURE0 */
- glUniform1i(glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30); /* GL_TEXTURE30 */
- glUniform1i(glGetUniformLocation(program, "FVarDataBuffer"), 31); /* GL_TEXTURE31 */
- glUseProgram(0);
- }
-
- return program;
-}
-
-void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
-{
- glUseProgram(program);
-
- /* Matrices */
- glUniformMatrix4fv(glGetUniformLocation(program, "modelViewMatrix"),
- 1, false,
- g_transform.model_view_matrix);
- glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"),
- 1, false,
- g_transform.projection_matrix);
- glUniformMatrix3fv(glGetUniformLocation(program, "normalMatrix"),
- 1, false,
- g_transform.normal_matrix);
-
- /* Lighting */
- glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
- glBufferSubData(GL_UNIFORM_BUFFER,
- 0, sizeof(g_lighting_data), &g_lighting_data);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
-
- /* Color */
- {
- /* TODO: stop using glGetMaterial */
- float color[4];
- glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
- glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
-
- glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
- glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
-
- glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
- glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
- }
-
- /* Face-vertex data */
- if (gl_mesh->fvar_data != NULL) {
- if (gl_mesh->fvar_data->texture_buffer) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (gl_mesh->fvar_data->offset_buffer) {
- glActiveTexture(GL_TEXTURE30);
- glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
-
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
- gl_mesh->fvar_data->fvar_width);
- if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
- g_active_uv_index >= 0)
- {
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
- } else {
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
- } else {
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
-}
-
-} /* namespace */
-
-bool openSubdiv_osdGLDisplayInit(void)
-{
- static bool need_init = true;
- static bool init_success = false;
-
- if (need_init) {
- /* TODO: update OSD drawing to OpenGL 3.3 core, then remove following line */
- return false;
-
- const char *version = "";
- if (GLEW_VERSION_3_2) {
- version = "#version 150 compatibility\n";
- }
- else if (GLEW_VERSION_3_1) {
- version = "#version 140\n"
- "#extension GL_ARB_compatibility: enable\n";
- }
- else {
- version = "#version 130\n";
- /* minimum supported for OpenSubdiv */
- }
-
- g_flat_fill_solid_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define USE_TEXTURE_2D\n"
- "#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define USE_TEXTURE_2D\n"
- "#define SMOOTH_SHADING\n");
-
- g_flat_fill_solid_shadeless_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_shadeless_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_TEXTURE_2D\n"
- "#define FLAT_SHADING\n");
- g_smooth_fill_solid_shadeless_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_shadeless_program = linkProgram(
- version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_TEXTURE_2D\n"
- "#define SMOOTH_SHADING\n");
-
- g_wireframe_program = linkProgram(
- version,
- "#define WIREFRAME\n");
-
- glGenBuffers(1, &g_lighting_ub);
- glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
- glBufferData(GL_UNIFORM_BUFFER,
- sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
-
- need_init = false;
- init_success = g_flat_fill_solid_program != 0 &&
- g_flat_fill_texture2d_program != 0 &&
- g_smooth_fill_solid_program != 0 &&
- g_smooth_fill_texture2d_program != 0 &&
- g_wireframe_program;
- }
- return init_success;
-}
-
-void openSubdiv_osdGLDisplayDeinit(void)
-{
- if (g_lighting_ub != 0) {
- glDeleteBuffers(1, &g_lighting_ub);
- }
-#define SAFE_DELETE_PROGRAM(program) \
- do { \
- if (program) { \
- glDeleteProgram(program); \
- } \
- } while (false)
-
- SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
- SAFE_DELETE_PROGRAM(g_wireframe_program);
-
-#undef SAFE_DELETE_PROGRAM
-}
-
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
- int active_uv_index)
-{
- g_active_uv_index = active_uv_index;
- g_use_osd_glsl = (use_osd_glsl != 0);
-
- /* Update transformation matrices. */
- glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
- glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
-
- copy_m3_m4((float (*)[3])g_transform.normal_matrix,
- (float (*)[4])g_transform.model_view_matrix);
- invert_m3((float (*)[3])g_transform.normal_matrix);
- transpose_m3((float (*)[3])g_transform.normal_matrix);
-
- /* Update OpenGL lights positions, colors etc. */
- g_lighting_data.num_enabled = 0;
- for (int i = 0; i < MAX_LIGHTS; ++i) {
- GLboolean enabled;
- glGetBooleanv(GL_LIGHT0 + i, &enabled);
- if (enabled) {
- g_lighting_data.num_enabled++;
- }
-
- /* TODO: stop using glGetLight */
- glGetLightfv(GL_LIGHT0 + i,
- GL_POSITION,
- g_lighting_data.lights[i].position);
- glGetLightfv(GL_LIGHT0 + i,
- GL_AMBIENT,
- g_lighting_data.lights[i].ambient);
- glGetLightfv(GL_LIGHT0 + i,
- GL_DIFFUSE,
- g_lighting_data.lights[i].diffuse);
- glGetLightfv(GL_LIGHT0 + i,
- GL_SPECULAR,
- g_lighting_data.lights[i].specular);
- glGetLightfv(GL_LIGHT0 + i,
- GL_SPOT_DIRECTION,
- g_lighting_data.lights[i].spot_direction);
-#ifdef SUPPORT_COLOR_MATERIAL
- glGetLightfv(GL_LIGHT0 + i,
- GL_CONSTANT_ATTENUATION,
- &g_lighting_data.lights[i].constant_attenuation);
- glGetLightfv(GL_LIGHT0 + i,
- GL_LINEAR_ATTENUATION,
- &g_lighting_data.lights[i].linear_attenuation);
- glGetLightfv(GL_LIGHT0 + i,
- GL_QUADRATIC_ATTENUATION,
- &g_lighting_data.lights[i].quadratic_attenuation);
- glGetLightfv(GL_LIGHT0 + i,
- GL_SPOT_CUTOFF,
- &g_lighting_data.lights[i].spot_cutoff);
- glGetLightfv(GL_LIGHT0 + i,
- GL_SPOT_EXPONENT,
- &g_lighting_data.lights[i].spot_exponent);
- g_lighting_data.lights[i].spot_cos_cutoff =
- cos(g_lighting_data.lights[i].spot_cutoff);
-#endif
- }
-}
-
-static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
- bool fill_quads)
-{
- GLint program = 0;
- if (!g_use_osd_glsl) {
- glGetIntegerv(GL_CURRENT_PROGRAM, &program);
- if (program) {
- GLint model;
- glGetIntegerv(GL_SHADE_MODEL, &model);
-
- GLint location = glGetUniformLocation(program, "osd_flat_shading");
- if (location != -1) {
- glUniform1i(location, model == GL_FLAT);
- }
-
- /* Face-vertex data */
- if (gl_mesh->fvar_data != NULL) {
- if (gl_mesh->fvar_data->texture_buffer) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- gl_mesh->fvar_data->texture_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (gl_mesh->fvar_data->offset_buffer) {
- glActiveTexture(GL_TEXTURE30);
- glBindTexture(GL_TEXTURE_BUFFER,
- gl_mesh->fvar_data->offset_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
-
- GLint location = glGetUniformLocation(program, "osd_fvar_count");
- if (location != -1) {
- glUniform1i(location, gl_mesh->fvar_data->fvar_width);
- }
-
- location = glGetUniformLocation(program, "osd_active_uv_offset");
- if (location != -1) {
- if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
- g_active_uv_index >= 0)
- {
- glUniform1i(location,
- gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
- } else {
- glUniform1i(location, 0);
- }
- }
- } else {
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
- }
- return program;
- }
-
- if (fill_quads) {
- int model;
- GLboolean use_texture_2d;
- glGetIntegerv(GL_SHADE_MODEL, &model);
- glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
-
- if (model == GL_FLAT) {
- if (use_texture_2d) {
- program = g_flat_fill_texture2d_program;
- }
- else {
- program = g_flat_fill_solid_program;
- }
- }
- else {
- if (use_texture_2d) {
- program = g_smooth_fill_texture2d_program;
- }
- else {
- program = g_smooth_fill_solid_program;
- }
- }
-
- }
- else {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- program = g_wireframe_program;
- }
-
- bindProgram(gl_mesh, program);
-
- return program;
-}
-
-static void perform_drawElements(GLuint program,
- int patch_index,
- int num_elements,
- int start_element)
-{
- if (program) {
- glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"),
- patch_index);
- }
- glDrawElements(GL_LINES_ADJACENCY,
- num_elements,
- GL_UNSIGNED_INT,
- (void *)(start_element * sizeof(unsigned int)));
-}
-
-static void finish_patchDraw(bool fill_quads)
-{
- /* TODO(sergey): Some of the stuff could be done once after the whole
- * mesh is displayed.
- */
-
- /* Restore state. */
- if (!fill_quads) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- glBindVertexArray(0);
-
- if (g_use_osd_glsl) {
- /* TODO(sergey): Store previously used program and roll back to it? */
- glUseProgram(0);
- }
-}
-
-static void draw_partition_patches_range(GLMeshInterface *mesh,
- GLuint program,
- int start_patch,
- int num_patches)
-{
- int traversed_patches = 0, num_remained_patches = num_patches;
- const OpenSubdiv::Osd::PatchArrayVector& patches =
- mesh->GetPatchTable()->GetPatchArrays();
- for (int i = 0; i < (int)patches.size(); ++i) {
- const OpenSubdiv::Osd::PatchArray& patch = patches[i];
- OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
- OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
-
- if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
- const int num_block_patches = patch.GetNumPatches();
- if (start_patch >= traversed_patches &&
- start_patch < traversed_patches + num_block_patches)
- {
- const int num_control_verts = desc.GetNumControlVertices();
- const int start_draw_patch = start_patch - traversed_patches;
- const int num_draw_patches = std::min(num_remained_patches,
- num_block_patches - start_draw_patch);
- perform_drawElements(program,
- i + start_draw_patch,
- num_draw_patches * num_control_verts,
- patch.GetIndexBase() + start_draw_patch * num_control_verts);
- num_remained_patches -= num_draw_patches;
- }
- if (num_remained_patches == 0) {
- break;
- }
- traversed_patches += num_block_patches;
- }
- }
-}
-
-static void draw_all_patches(GLMeshInterface *mesh,
- GLuint program)
-{
- const OpenSubdiv::Osd::PatchArrayVector& patches =
- mesh->GetPatchTable()->GetPatchArrays();
- for (int i = 0; i < (int)patches.size(); ++i) {
- const OpenSubdiv::Osd::PatchArray& patch = patches[i];
- OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
- OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
-
- if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
- perform_drawElements(program,
- i,
- patch.GetNumPatches() * desc.GetNumControlVertices(),
- patch.GetIndexBase());
- }
- }
-}
-
-void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
- int fill_quads,
- int start_patch,
- int num_patches)
-{
- GLMeshInterface *mesh =
- (GLMeshInterface *)(gl_mesh->descriptor);
-
- /* Make sure all global invariants are initialized. */
- if (!openSubdiv_osdGLDisplayInit()) {
- return;
- }
-
- /* Setup GLSL/OpenGL to draw patches in current context. */
- GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
-
- if (start_patch != -1) {
- draw_partition_patches_range(mesh,
- program,
- start_patch,
- num_patches);
- }
- else {
- draw_all_patches(mesh, program);
- }
-
- /* Finish patch drawing by restoring all changes to the OpenGL context. */
- finish_patchDraw(fill_quads != 0);
-}
-
-void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
- OpenSubdiv_GLMesh *gl_mesh,
- const float *fvar_data)
-{
- GLMeshInterface *mesh =
- (GLMeshInterface *)(gl_mesh->descriptor);
- gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
- gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
- mesh->GetFarPatchTable(),
- 2,
- fvar_data);
-}
-
-void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
-{
- if (gl_mesh->fvar_data != NULL) {
- OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
- }
-}
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner_capi.h b/intern/opensubdiv/opensubdiv_topology_refiner_capi.h
new file mode 100644
index 00000000000..fe4db0ca67c
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_topology_refiner_capi.h
@@ -0,0 +1,151 @@
+// Copyright 2018 Blender Foundation. All rights reserved.
+//
+// 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.
+//
+// Author: Sergey Sharybin
+
+#ifndef OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
+#define OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
+
+#include <stdint.h> // for bool
+
+#include "opensubdiv_capi_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct OpenSubdiv_Converter;
+struct OpenSubdiv_TopologyRefinerInternal;
+
+// Those settings don't really belong to OpenSubdiv's topology refiner, but
+// we are keeping track of them on our side of topology refiner. This is to
+// make it possible to ensure we are not trying to abuse same OpenSubdiv's
+// topology refiner with different subdivision levels or with different
+// adaptive settings.
+typedef struct OpenSubdiv_TopologyRefinerSettings {
+ bool is_adaptive;
+ int level;
+} OpenSubdiv_TopologyRefinerSettings;
+
+typedef struct OpenSubdiv_TopologyRefiner {
+ // Query subdivision level the refiner is created for.
+ int (*getSubdivisionLevel)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ bool (*getIsAdaptive)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+
+ // NOTE: All queries are querying base level.
+ //
+ // TODO(sergey): Consider making it more obvious in function naming,
+ // but since it's unlikely (or at least, will be uncommon use) for API
+ // which queries final geometry, we should be fine with this name for
+ // now.
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Query basic topology information from base level.
+
+ int (*getNumVertices)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ int (*getNumEdges)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ int (*getNumFaces)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ int (*getNumFaceVertices)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // PTex face geometry queries.
+
+ // Ptex face corresponds to OpenSubdiv's internal "patch" and to Blender's
+ // subdivision grid. The rule commes as:
+ // - Triangle face consist of 3 ptex faces, ordered in the order of
+ // face-vertices.
+ // - Quad face consists of a single ptex face.
+ // - N-gons (similar to triangle) consists of N ptex faces, ordered same
+ // way as for triangle.
+ int (*getNumFacePtexFaces)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index);
+ int (*getNumPtexFaces)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+
+ // Initialize a per-base-face offset measured in ptex face indices.
+ //
+ // Basically, face_ptex_offset[base_face_index] is a total number of ptex
+ // faces created for bases faces [0 .. base_face_index - 1].
+ //
+ // The array must contain at least total number of ptex faces elements.
+ void (*fillFacePtexIndexOffset)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ int* face_ptex_index_offset);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Face-varying data.
+
+ // Number of face-varying channels (or how they are called in Blender layers).
+ int (*getNumFVarChannels)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ // Get face-varying interpolation type.
+ OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner);
+ // Get total number of face-varying values in a particular channel.
+ int (*getNumFVarValues)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int channel);
+ // Get face-varying value indices associated with a particular face.
+ //
+ // This is an array of indices inside of face-varying array, array elements
+ // are aligned with face corners (or loops in Blender terminology).
+ const int* (*getFaceFVarValueIndices)(
+ const struct OpenSubdiv_TopologyRefiner* topology_refiner,
+ const int face_index,
+ const int channel);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Internal use.
+
+ // Internal storage for the use in this module only.
+ //
+ // Tease: Contains actual OpenSubdiv's refiner and (optionally) some other
+ // data and state needed for an internbal use.
+ struct OpenSubdiv_TopologyRefinerInternal* internal;
+} OpenSubdiv_TopologyRefiner;
+
+// NOTE: Will return NULL in cases of bad topology.
+// NOTE: Mesh without faces is considered a bad topology.
+OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
+ struct OpenSubdiv_Converter* converter,
+ const OpenSubdiv_TopologyRefinerSettings* settings);
+
+void openSubdiv_deleteTopologyRefiner(
+ OpenSubdiv_TopologyRefiner* topology_refiner);
+
+// Compare given topology refiner with converter. Returns truth if topology
+// refiner matches given converter, false otherwise.
+//
+// This allows users to construct converter (which is supposed to be cheap)
+// and compare with existing refiner before going into more computationally
+// complicated parts of subdivision process.
+bool openSubdiv_topologyRefinerCompareWithConverter(
+ const OpenSubdiv_TopologyRefiner* topology_refiner,
+ const struct OpenSubdiv_Converter* converter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
diff --git a/intern/opensubdiv/opensubdiv_utils_capi.cc b/intern/opensubdiv/opensubdiv_utils_capi.cc
deleted file mode 100644
index 72e3751e6b3..00000000000
--- a/intern/opensubdiv/opensubdiv_utils_capi.cc
+++ /dev/null
@@ -1,88 +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.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- * Brecht van Lommel
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "opensubdiv_capi.h"
-
-#include <cstring>
-#include <GL/glew.h>
-
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
-
-#ifdef OPENSUBDIV_HAS_OPENCL
-# include "opensubdiv_device_context_opencl.h"
-#endif /* OPENSUBDIV_HAS_OPENCL */
-
-#ifdef OPENSUBDIV_HAS_CUDA
-# include "opensubdiv_device_context_cuda.h"
-#endif /* OPENSUBDIV_HAS_CUDA */
-
-int openSubdiv_getAvailableEvaluators(void)
-{
- int flags = OPENSUBDIV_EVALUATOR_CPU;
-
-#ifdef OPENSUBDIV_HAS_OPENMP
- flags |= OPENSUBDIV_EVALUATOR_OPENMP;
-#endif /* OPENSUBDIV_HAS_OPENMP */
-
-#ifdef OPENSUBDIV_HAS_OPENCL
- if (CLDeviceContext::HAS_CL_VERSION_1_1()) {
- flags |= OPENSUBDIV_EVALUATOR_OPENCL;
- }
-#endif /* OPENSUBDIV_HAS_OPENCL */
-
-#ifdef OPENSUBDIV_HAS_CUDA
- if (CudaDeviceContext::HAS_CUDA_VERSION_4_0()) {
- flags |= OPENSUBDIV_EVALUATOR_CUDA;
- }
-#endif /* OPENSUBDIV_HAS_OPENCL */
-
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- if (GLEW_VERSION_4_1) {
- flags |= OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK;
- }
-#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
-
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- if (GLEW_VERSION_4_3 || GLEW_ARB_compute_shader) {
- flags |= OPENSUBDIV_EVALUATOR_GLSL_COMPUTE;
- }
-#endif /* OPENSUBDIV_HAS_GLSL_COMPUTE */
-
- return flags;
-}
-
-void openSubdiv_init(void)
-{
- /* Ensure all OpenGL strings are cached. */
- (void)openSubdiv_getAvailableEvaluators();
-}
-
-void openSubdiv_cleanup(void)
-{
- openSubdiv_osdGLDisplayDeinit();
-}
diff --git a/intern/opensubdiv/gpu_shader_opensubdiv_fragment.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl
index 1e36d549360..1e36d549360 100644
--- a/intern/opensubdiv/gpu_shader_opensubdiv_fragment.glsl
+++ b/intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl
diff --git a/intern/opensubdiv/gpu_shader_opensubdiv_geometry.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl
index b16a5cca733..b16a5cca733 100644
--- a/intern/opensubdiv/gpu_shader_opensubdiv_geometry.glsl
+++ b/intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl
diff --git a/intern/opensubdiv/gpu_shader_opensubdiv_vertex.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl
index 6fcf5ad20cd..6fcf5ad20cd 100644
--- a/intern/opensubdiv/gpu_shader_opensubdiv_vertex.glsl
+++ b/intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl
diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h
index 556ca959e64..eec94bcea50 100644
--- a/intern/rigidbody/RBI_api.h
+++ b/intern/rigidbody/RBI_api.h
@@ -268,6 +268,7 @@ rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody
rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
/* ............ */
@@ -299,12 +300,18 @@ void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float l
void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper);
/* 6dof spring specific */
-void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper);
void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness);
void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping);
void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable);
void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con);
+/* 6dof spring 2 specific */
+void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper);
+void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness);
+void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping);
+void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable);
+void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con);
+
/* motors */
void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang);
void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang);
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index a9fbcb28529..6a50c5c93ee 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -954,11 +954,25 @@ rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigi
make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
- btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2);
+ btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true);
return (rbConstraint *)con;
}
+rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2);
+
+ return (rbConstraint *)con;
+}
+
rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
{
btRigidBody *body1 = rb1->body;
@@ -1034,7 +1048,7 @@ void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, flo
constraint->setLimit(axis, lower, upper);
}
-void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper)
+void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper)
{
btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
@@ -1043,27 +1057,58 @@ void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float low
void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness)
{
- btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
constraint->setStiffness(axis, stiffness);
}
void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping)
{
- btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ // invert damping range so that 0 = no damping
+ damping = (damping > 1.0f) ? 0.0f : 1.0f - damping;
constraint->setDamping(axis, damping);
}
void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable)
{
- btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
constraint->enableSpring(axis, enable);
}
void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con)
{
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ constraint->setEquilibriumPoint();
+}
+
+void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness)
+{
+ btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+
+ constraint->setStiffness(axis, stiffness);
+}
+
+void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping)
+{
+ btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+
+ constraint->setDamping(axis, damping);
+}
+
+void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable)
+{
+ btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
+
+ constraint->enableSpring(axis, enable);
+}
+
+void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con)
+{
btGeneric6DofSpring2Constraint *constraint = reinterpret_cast<btGeneric6DofSpring2Constraint*>(con);
constraint->setEquilibriumPoint();
diff --git a/release/datafiles/brushicons/gp_brush_block.png b/release/datafiles/brushicons/gp_brush_block.png
new file mode 100644
index 00000000000..2db3964e573
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_block.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_clone.png b/release/datafiles/brushicons/gp_brush_clone.png
new file mode 100644
index 00000000000..8358ace23b3
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_clone.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_erase_hard.png b/release/datafiles/brushicons/gp_brush_erase_hard.png
new file mode 100644
index 00000000000..2ac52840678
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_erase_hard.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_erase_soft.png b/release/datafiles/brushicons/gp_brush_erase_soft.png
new file mode 100644
index 00000000000..416923004dd
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_erase_soft.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_erase_stroke.png b/release/datafiles/brushicons/gp_brush_erase_stroke.png
new file mode 100644
index 00000000000..cd6d21532cf
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_erase_stroke.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_fill.png b/release/datafiles/brushicons/gp_brush_fill.png
new file mode 100644
index 00000000000..9dac633139c
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_fill.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_grab.png b/release/datafiles/brushicons/gp_brush_grab.png
new file mode 100644
index 00000000000..2123ac69aef
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_grab.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_ink.png b/release/datafiles/brushicons/gp_brush_ink.png
new file mode 100644
index 00000000000..410a77f6117
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_ink.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_inknoise.png b/release/datafiles/brushicons/gp_brush_inknoise.png
new file mode 100644
index 00000000000..5356f697e01
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_inknoise.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_marker.png b/release/datafiles/brushicons/gp_brush_marker.png
new file mode 100644
index 00000000000..c7a62b78ca7
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_marker.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_pen.png b/release/datafiles/brushicons/gp_brush_pen.png
new file mode 100644
index 00000000000..9aaaa861f49
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_pen.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_pencil.png b/release/datafiles/brushicons/gp_brush_pencil.png
new file mode 100644
index 00000000000..2d1fbdfd916
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_pencil.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_pinch.png b/release/datafiles/brushicons/gp_brush_pinch.png
new file mode 100644
index 00000000000..e38236d1be0
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_pinch.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_push.png b/release/datafiles/brushicons/gp_brush_push.png
new file mode 100644
index 00000000000..542764309cc
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_push.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_randomize.png b/release/datafiles/brushicons/gp_brush_randomize.png
new file mode 100644
index 00000000000..0dd1a131d86
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_randomize.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_smooth.png b/release/datafiles/brushicons/gp_brush_smooth.png
new file mode 100644
index 00000000000..7518a358219
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_smooth.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_strength.png b/release/datafiles/brushicons/gp_brush_strength.png
new file mode 100644
index 00000000000..a0513119f29
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_strength.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_thickness.png b/release/datafiles/brushicons/gp_brush_thickness.png
new file mode 100644
index 00000000000..6026716f026
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_thickness.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_twist.png b/release/datafiles/brushicons/gp_brush_twist.png
new file mode 100644
index 00000000000..84b9a90e9d6
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_twist.png
Binary files differ
diff --git a/release/datafiles/brushicons/gp_brush_weight.png b/release/datafiles/brushicons/gp_brush_weight.png
new file mode 100644
index 00000000000..171e9221e92
--- /dev/null
+++ b/release/datafiles/brushicons/gp_brush_weight.png
Binary files differ
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index ce79dfeb540..c8466ab99fc 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -70,7 +70,7 @@ displays:
- !<View> {name: Default, colorspace: Raw}
active_displays: [sRGB, DCIP3, Rec709, XYZ, None]
-active_views: [Default, RRT, Raw, Log]
+active_views: [Filmic, Default, RRT, Raw, Log]
colorspaces:
- !<ColorSpace>
diff --git a/release/datafiles/icons/brush.gpencil.draw.eraser_hard.dat b/release/datafiles/icons/brush.gpencil.draw.eraser_hard.dat
new file mode 100644
index 00000000000..1e909ca8ac9
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw.eraser_hard.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw.eraser_soft.dat b/release/datafiles/icons/brush.gpencil.draw.eraser_soft.dat
new file mode 100644
index 00000000000..7242f76a0f9
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw.eraser_soft.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw.eraser_stroke.dat b/release/datafiles/icons/brush.gpencil.draw.eraser_stroke.dat
new file mode 100644
index 00000000000..6bf620bf3c2
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw.eraser_stroke.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_block.dat b/release/datafiles/icons/brush.gpencil.draw_block.dat
new file mode 100644
index 00000000000..7a7402ef673
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_block.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_fill.dat b/release/datafiles/icons/brush.gpencil.draw_fill.dat
new file mode 100644
index 00000000000..809aed7f3cf
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_fill.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_ink.dat b/release/datafiles/icons/brush.gpencil.draw_ink.dat
new file mode 100644
index 00000000000..3c654712783
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_ink.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_marker.dat b/release/datafiles/icons/brush.gpencil.draw_marker.dat
new file mode 100644
index 00000000000..77a52dd83d4
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_marker.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_noise.dat b/release/datafiles/icons/brush.gpencil.draw_noise.dat
new file mode 100644
index 00000000000..127f469b9fb
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_noise.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_pen.dat b/release/datafiles/icons/brush.gpencil.draw_pen.dat
new file mode 100644
index 00000000000..cb6fb77924a
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_pen.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.gpencil.draw_pencil.dat b/release/datafiles/icons/brush.gpencil.draw_pencil.dat
new file mode 100644
index 00000000000..a8898a94917
--- /dev/null
+++ b/release/datafiles/icons/brush.gpencil.draw_pencil.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.add.dat b/release/datafiles/icons/brush.particle.add.dat
new file mode 100644
index 00000000000..e78bf251371
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.add.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.comb.dat b/release/datafiles/icons/brush.particle.comb.dat
new file mode 100644
index 00000000000..5ece6bf754d
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.comb.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.cut.dat b/release/datafiles/icons/brush.particle.cut.dat
new file mode 100644
index 00000000000..79306d5d7e9
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.cut.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.length.dat b/release/datafiles/icons/brush.particle.length.dat
new file mode 100644
index 00000000000..4c9da271316
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.length.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.puff.dat b/release/datafiles/icons/brush.particle.puff.dat
new file mode 100644
index 00000000000..b0e797853c3
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.puff.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.smooth.dat b/release/datafiles/icons/brush.particle.smooth.dat
new file mode 100644
index 00000000000..a3cbe3cf657
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.smooth.dat
Binary files differ
diff --git a/release/datafiles/icons/brush.particle.weight.dat b/release/datafiles/icons/brush.particle.weight.dat
new file mode 100644
index 00000000000..309ee157a19
--- /dev/null
+++ b/release/datafiles/icons/brush.particle.weight.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.draw.dat b/release/datafiles/icons/ops.gpencil.draw.dat
new file mode 100644
index 00000000000..3adc50ab17d
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.draw.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.draw.eraser.dat b/release/datafiles/icons/ops.gpencil.draw.eraser.dat
new file mode 100644
index 00000000000..323d8c23245
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.draw.eraser.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.draw.line.dat b/release/datafiles/icons/ops.gpencil.draw.line.dat
new file mode 100644
index 00000000000..238db63807a
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.draw.line.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.draw.poly.dat b/release/datafiles/icons/ops.gpencil.draw.poly.dat
new file mode 100644
index 00000000000..8351e48fec1
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.draw.poly.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.edit_bend.dat b/release/datafiles/icons/ops.gpencil.edit_bend.dat
new file mode 100644
index 00000000000..32f7b2e9631
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.edit_bend.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.edit_mirror.dat b/release/datafiles/icons/ops.gpencil.edit_mirror.dat
new file mode 100644
index 00000000000..ee073664f78
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.edit_mirror.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.edit_shear.dat b/release/datafiles/icons/ops.gpencil.edit_shear.dat
new file mode 100644
index 00000000000..e6b51f988f8
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.edit_shear.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.edit_to_sphere.dat b/release/datafiles/icons/ops.gpencil.edit_to_sphere.dat
new file mode 100644
index 00000000000..bf1181cd500
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.edit_to_sphere.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_clone.dat b/release/datafiles/icons/ops.gpencil.sculpt_clone.dat
new file mode 100644
index 00000000000..dbae6a68159
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_clone.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_grab.dat b/release/datafiles/icons/ops.gpencil.sculpt_grab.dat
new file mode 100644
index 00000000000..291b4fd12dc
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_grab.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_pinch.dat b/release/datafiles/icons/ops.gpencil.sculpt_pinch.dat
new file mode 100644
index 00000000000..cb2b43f5597
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_pinch.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_push.dat b/release/datafiles/icons/ops.gpencil.sculpt_push.dat
new file mode 100644
index 00000000000..e1c4961ff86
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_push.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_randomize.dat b/release/datafiles/icons/ops.gpencil.sculpt_randomize.dat
new file mode 100644
index 00000000000..35042936757
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_randomize.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_smooth.dat b/release/datafiles/icons/ops.gpencil.sculpt_smooth.dat
new file mode 100644
index 00000000000..3a132ed4049
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_smooth.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_strength.dat b/release/datafiles/icons/ops.gpencil.sculpt_strength.dat
new file mode 100644
index 00000000000..7e52b0d7648
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_strength.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_thickness.dat b/release/datafiles/icons/ops.gpencil.sculpt_thickness.dat
new file mode 100644
index 00000000000..1e558806888
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_thickness.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_twist.dat b/release/datafiles/icons/ops.gpencil.sculpt_twist.dat
new file mode 100644
index 00000000000..4ce958cb7ec
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_twist.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.gpencil.sculpt_weight.dat b/release/datafiles/icons/ops.gpencil.sculpt_weight.dat
new file mode 100644
index 00000000000..41b58abfda7
--- /dev/null
+++ b/release/datafiles/icons/ops.gpencil.sculpt_weight.dat
Binary files differ
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject d3349b42856d00c278f72f2a5909a6c96b9cdb5
+Subproject 59495b4b59077aa1cc68fffbdae1463af980f08
diff --git a/release/datafiles/preview_grease_pencil.blend b/release/datafiles/preview_grease_pencil.blend
new file mode 100644
index 00000000000..82661d80029
--- /dev/null
+++ b/release/datafiles/preview_grease_pencil.blend
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/basic_1.exr b/release/datafiles/studiolights/matcap/basic_1.exr
new file mode 100644
index 00000000000..bb2e09abbd2
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/basic_1.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/basic_2.exr b/release/datafiles/studiolights/matcap/basic_2.exr
new file mode 100644
index 00000000000..d97f7630d63
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/basic_2.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/basic_dark.exr b/release/datafiles/studiolights/matcap/basic_dark.exr
new file mode 100644
index 00000000000..b623c8030f8
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/basic_dark.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/basic_side.exr b/release/datafiles/studiolights/matcap/basic_side.exr
new file mode 100644
index 00000000000..6e4452e7511
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/basic_side.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/ceramic_dark.exr b/release/datafiles/studiolights/matcap/ceramic_dark.exr
new file mode 100644
index 00000000000..837b020c96d
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/ceramic_dark.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/ceramic_lightbulb.exr b/release/datafiles/studiolights/matcap/ceramic_lightbulb.exr
new file mode 100644
index 00000000000..e05b6612e46
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/ceramic_lightbulb.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/check_normal+y.exr b/release/datafiles/studiolights/matcap/check_normal+y.exr
new file mode 100644
index 00000000000..4e2a97ac3b9
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/check_normal+y.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/check_reflection.exr b/release/datafiles/studiolights/matcap/check_reflection.exr
new file mode 100644
index 00000000000..245d6059241
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/check_reflection.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/check_rim_dark.exr b/release/datafiles/studiolights/matcap/check_rim_dark.exr
new file mode 100644
index 00000000000..e6a32004ea1
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/check_rim_dark.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/check_rim_light.exr b/release/datafiles/studiolights/matcap/check_rim_light.exr
new file mode 100644
index 00000000000..6318c0f9346
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/check_rim_light.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/clay_brown.exr b/release/datafiles/studiolights/matcap/clay_brown.exr
new file mode 100644
index 00000000000..fe1e0305383
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/clay_brown.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/clay_muddy.exr b/release/datafiles/studiolights/matcap/clay_muddy.exr
new file mode 100644
index 00000000000..d219578c62b
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/clay_muddy.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/clay_studio.exr b/release/datafiles/studiolights/matcap/clay_studio.exr
new file mode 100644
index 00000000000..7746e6d0e35
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/clay_studio.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/jade.exr b/release/datafiles/studiolights/matcap/jade.exr
new file mode 100644
index 00000000000..fe1211f1b65
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/jade.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/license.txt b/release/datafiles/studiolights/matcap/license.txt
index 358c8dcd832..09a0f7a439e 100644
--- a/release/datafiles/studiolights/matcap/license.txt
+++ b/release/datafiles/studiolights/matcap/license.txt
@@ -1,3 +1,3 @@
-These matcap images are licensed as GNU GPL 2 or later, like the rest of Blender's code.
+These matcap images are licensed as CC0 or public domain.
-Thanks to Kent Trammell, Aidy Burrows, John Herreno , Terry Wallwork and David Silverman for making the pictures.
+Thanks to the Blender community for contributing these matcaps.
diff --git a/release/datafiles/studiolights/matcap/mc01.jpg b/release/datafiles/studiolights/matcap/mc01.jpg
deleted file mode 100644
index 8c7aef287ee..00000000000
--- a/release/datafiles/studiolights/matcap/mc01.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc02.jpg b/release/datafiles/studiolights/matcap/mc02.jpg
deleted file mode 100644
index 11deddfeaed..00000000000
--- a/release/datafiles/studiolights/matcap/mc02.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc03.jpg b/release/datafiles/studiolights/matcap/mc03.jpg
deleted file mode 100644
index 64d992fb61a..00000000000
--- a/release/datafiles/studiolights/matcap/mc03.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc04.jpg b/release/datafiles/studiolights/matcap/mc04.jpg
deleted file mode 100644
index 42be580ee93..00000000000
--- a/release/datafiles/studiolights/matcap/mc04.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc05.jpg b/release/datafiles/studiolights/matcap/mc05.jpg
deleted file mode 100644
index 586d233ef31..00000000000
--- a/release/datafiles/studiolights/matcap/mc05.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc06.jpg b/release/datafiles/studiolights/matcap/mc06.jpg
deleted file mode 100644
index 657883d0866..00000000000
--- a/release/datafiles/studiolights/matcap/mc06.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc07.jpg b/release/datafiles/studiolights/matcap/mc07.jpg
deleted file mode 100644
index 372caf7e87c..00000000000
--- a/release/datafiles/studiolights/matcap/mc07.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc08.jpg b/release/datafiles/studiolights/matcap/mc08.jpg
deleted file mode 100644
index 50eec402812..00000000000
--- a/release/datafiles/studiolights/matcap/mc08.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc09.jpg b/release/datafiles/studiolights/matcap/mc09.jpg
deleted file mode 100644
index e05d441aaf9..00000000000
--- a/release/datafiles/studiolights/matcap/mc09.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc10.jpg b/release/datafiles/studiolights/matcap/mc10.jpg
deleted file mode 100644
index ab82f17bb93..00000000000
--- a/release/datafiles/studiolights/matcap/mc10.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc11.jpg b/release/datafiles/studiolights/matcap/mc11.jpg
deleted file mode 100644
index 053550f082c..00000000000
--- a/release/datafiles/studiolights/matcap/mc11.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc12.jpg b/release/datafiles/studiolights/matcap/mc12.jpg
deleted file mode 100644
index beb16f3742e..00000000000
--- a/release/datafiles/studiolights/matcap/mc12.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc13.jpg b/release/datafiles/studiolights/matcap/mc13.jpg
deleted file mode 100644
index 7fb8fa58e8f..00000000000
--- a/release/datafiles/studiolights/matcap/mc13.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc14.jpg b/release/datafiles/studiolights/matcap/mc14.jpg
deleted file mode 100644
index ba868d2f95a..00000000000
--- a/release/datafiles/studiolights/matcap/mc14.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc15.jpg b/release/datafiles/studiolights/matcap/mc15.jpg
deleted file mode 100644
index b10ea326a42..00000000000
--- a/release/datafiles/studiolights/matcap/mc15.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc16.jpg b/release/datafiles/studiolights/matcap/mc16.jpg
deleted file mode 100644
index c6ce02d59df..00000000000
--- a/release/datafiles/studiolights/matcap/mc16.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc17.jpg b/release/datafiles/studiolights/matcap/mc17.jpg
deleted file mode 100644
index 14f15f70460..00000000000
--- a/release/datafiles/studiolights/matcap/mc17.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc18.jpg b/release/datafiles/studiolights/matcap/mc18.jpg
deleted file mode 100644
index db572856b07..00000000000
--- a/release/datafiles/studiolights/matcap/mc18.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc19.jpg b/release/datafiles/studiolights/matcap/mc19.jpg
deleted file mode 100644
index 56d2efb1734..00000000000
--- a/release/datafiles/studiolights/matcap/mc19.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc20.jpg b/release/datafiles/studiolights/matcap/mc20.jpg
deleted file mode 100644
index 002a0910dd9..00000000000
--- a/release/datafiles/studiolights/matcap/mc20.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc21.jpg b/release/datafiles/studiolights/matcap/mc21.jpg
deleted file mode 100644
index cb2fea573b8..00000000000
--- a/release/datafiles/studiolights/matcap/mc21.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc22.jpg b/release/datafiles/studiolights/matcap/mc22.jpg
deleted file mode 100644
index 2fc71b98c5a..00000000000
--- a/release/datafiles/studiolights/matcap/mc22.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc23.jpg b/release/datafiles/studiolights/matcap/mc23.jpg
deleted file mode 100644
index 3793c0fcaa5..00000000000
--- a/release/datafiles/studiolights/matcap/mc23.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/mc24.jpg b/release/datafiles/studiolights/matcap/mc24.jpg
deleted file mode 100644
index 2a9618d8fe1..00000000000
--- a/release/datafiles/studiolights/matcap/mc24.jpg
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/metal_anisotropic.exr b/release/datafiles/studiolights/matcap/metal_anisotropic.exr
new file mode 100644
index 00000000000..38ea94ac676
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/metal_anisotropic.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/metal_carpaint.exr b/release/datafiles/studiolights/matcap/metal_carpaint.exr
new file mode 100644
index 00000000000..c5bcdf67abf
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/metal_carpaint.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/metal_lead.exr b/release/datafiles/studiolights/matcap/metal_lead.exr
new file mode 100644
index 00000000000..4d6b2954ccd
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/metal_lead.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/metal_shiny.exr b/release/datafiles/studiolights/matcap/metal_shiny.exr
new file mode 100644
index 00000000000..3b5d20ffda2
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/metal_shiny.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/pearl.exr b/release/datafiles/studiolights/matcap/pearl.exr
new file mode 100644
index 00000000000..e657c67936e
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/pearl.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/resin.exr b/release/datafiles/studiolights/matcap/resin.exr
new file mode 100644
index 00000000000..80e405aaa67
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/resin.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/skin.exr b/release/datafiles/studiolights/matcap/skin.exr
new file mode 100644
index 00000000000..ffc3213dad9
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/skin.exr
Binary files differ
diff --git a/release/datafiles/studiolights/matcap/toon.exr b/release/datafiles/studiolights/matcap/toon.exr
new file mode 100644
index 00000000000..242f5055e2b
--- /dev/null
+++ b/release/datafiles/studiolights/matcap/toon.exr
Binary files differ
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 11a9fbaca00..69ad58ea1c5 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -1,8 +1,8 @@
/*
- * Generated by 'source/tools/utils/blender_theme_as_c.py'
- *
- * Do not hand edit this file!
- */
+* Generated by 'source/tools/utils/blender_theme_as_c.py'
+*
+* Do not hand edit this file!
+*/
#include "DNA_userdef_types.h"
@@ -1040,5 +1040,5 @@ const bTheme U_theme_default = {
.select = RGBA(0x000000ff),
.active = RGBA(0x000000ff),
},
- },
+},
};
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject ebd058d7a6438d137522063bb3286c8acc325ca
+Subproject 371960484a38fc64e0a2635170a41a0d8ab2f6b
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 86185b96e9d..f73d23c150b 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -367,14 +367,14 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
# Silent default, we know these need updating.
if module_name in {
- "io_anim_bvh",
- "io_mesh_ply",
- "io_mesh_stl",
- "io_mesh_uv_layout",
- "io_scene_3ds",
- "io_scene_fbx",
- "io_scene_obj",
- "io_scene_x3d",
+ "io_anim_bvh",
+ "io_mesh_ply",
+ "io_mesh_stl",
+ "io_mesh_uv_layout",
+ "io_scene_3ds",
+ "io_scene_fbx",
+ "io_scene_obj",
+ "io_scene_x3d",
}:
return None
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index 6859e327b66..ec4db69986c 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -56,6 +56,7 @@ KM_HIERARCHY = [
('Particle', 'EMPTY', 'WINDOW', []),
('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []),
+ ('Custom Normals Modal Map', 'EMPTY', 'WINDOW', []),
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
('Paint Curve', 'EMPTY', 'WINDOW', []),
@@ -121,6 +122,12 @@ KM_HIERARCHY = [
('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Paint (Draw brush)', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Paint (Fill)', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Paint (Erase)', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Paint Mode', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Sculpt Mode', 'EMPTY', 'WINDOW', []),
+ ('Grease Pencil Stroke Weight Mode', 'EMPTY', 'WINDOW', []),
]),
('Mask Editing', 'EMPTY', 'WINDOW', []),
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 7719e2f6e30..c9ea684862d 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -100,7 +100,7 @@ def add_object_align_init(context, operator):
if operator:
properties.rotation = rotation.to_euler()
- return location * rotation
+ return location @ rotation
def object_data_add(context, obdata, operator=None, name=None):
@@ -166,7 +166,7 @@ def object_data_add(context, obdata, operator=None, name=None):
obj_act.select_set(action='SELECT')
scene.update() # apply location
- # scene.objects.active = obj_new
+ # layer.objects.active = obj_new
# Match up UV layers, this is needed so adding an object with UV's
# doesn't create new layers when there happens to be a naming mis-match.
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index a4834a4531c..a2e394b270f 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -54,7 +54,7 @@ def region_2d_to_vector_3d(region, rv3d, coord):
w = out.dot(persinv[3].xyz) + persinv[3][3]
- view_vector = ((persinv * out) / w) - viewinv.translation
+ view_vector = ((persinv @ out) / w) - viewinv.translation
else:
view_vector = -viewinv.col[2].xyz
@@ -179,7 +179,7 @@ def location_3d_to_region_2d(region, rv3d, coord, default=None):
"""
from mathutils import Vector
- prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0))
+ prj = rv3d.perspective_matrix @ Vector((coord[0], coord[1], coord[2], 1.0))
if prj.w > 0.0:
width_half = region.width / 2.0
height_half = region.height / 2.0
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index f4fd188c641..96193b047c6 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -205,21 +205,21 @@ class _GenericBone:
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
- return self.matrix.to_3x3() * Vector((1.0, 0.0, 0.0))
+ return self.matrix.to_3x3() @ Vector((1.0, 0.0, 0.0))
@property
def y_axis(self):
""" Vector pointing down the y-axis of the bone.
"""
from mathutils import Vector
- return self.matrix.to_3x3() * Vector((0.0, 1.0, 0.0))
+ return self.matrix.to_3x3() @ Vector((0.0, 1.0, 0.0))
@property
def z_axis(self):
""" Vector pointing down the z-axis of the bone.
"""
from mathutils import Vector
- return self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
+ return self.matrix.to_3x3() @ Vector((0.0, 0.0, 1.0))
@property
def basename(self):
@@ -378,9 +378,9 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
:type roll: bool
"""
from mathutils import Vector
- z_vec = self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
- self.tail = matrix * self.tail
- self.head = matrix * self.head
+ z_vec = self.matrix.to_3x3() @ Vector((0.0, 0.0, 1.0))
+ self.tail = matrix @ self.tail
+ self.head = matrix @ self.head
if scale:
scalar = matrix.median_scale
@@ -388,7 +388,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
self.tail_radius *= scalar
if roll:
- self.align_roll(matrix * z_vec)
+ self.align_roll(matrix @ z_vec)
def ord_ind(i1, i2):
@@ -587,7 +587,7 @@ class Gizmo(StructRNA):
_rna_gizmo_target_get_range as target_get_range,
)
- # Convenience wrappers around private `_gawain` module.
+ # Convenience wrappers around private `_gpu` module.
def draw_custom_shape(self, shape, *, matrix=None, select_id=None):
"""
Draw a shape created form :class:`bpy.types.Gizmo.draw_custom_shape`.
@@ -638,19 +638,19 @@ class Gizmo(StructRNA):
:return: The newly created shape.
:rtype: Undefined (it may change).
"""
- from _gawain.types import (
- Gwn_Batch,
- Gwn_VertBuf,
- Gwn_VertFormat,
+ from _gpu.types import (
+ GPUBatch,
+ GPUVertBuf,
+ GPUVertFormat,
)
dims = len(verts[0])
if dims not in {2, 3}:
raise ValueError("Expected 2D or 3D vertex")
- fmt = Gwn_VertFormat()
+ fmt = GPUVertFormat()
pos_id = fmt.attr_add(id="pos", comp_type='F32', len=dims, fetch_mode='FLOAT')
- vbo = Gwn_VertBuf(len=len(verts), format=fmt)
+ vbo = GPUVertBuf(len=len(verts), format=fmt)
vbo.fill(id=pos_id, data=verts)
- batch = Gwn_Batch(type=type, buf=vbo)
+ batch = GPUBatch(type=type, buf=vbo)
return (batch, dims)
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index bdb0751c973..0d17c11456e 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -132,6 +132,11 @@ def draw(layout, context, context_member, property_type, use_edit=True):
show_developer_ui = context.user_preferences.view.show_developer_ui
rna_properties = {prop.identifier for prop in rna_item.bl_rna.properties if prop.is_runtime} if items else None
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+
for key, val in items:
if key == '_RNA_UI':
@@ -143,7 +148,6 @@ def draw(layout, context, context_member, property_type, use_edit=True):
if is_rna and not show_developer_ui:
continue
- row = layout.row()
to_dict = getattr(val, "to_dict", None)
to_list = getattr(val, "to_list", None)
@@ -157,17 +161,20 @@ def draw(layout, context, context_member, property_type, use_edit=True):
else:
val_draw = val
+ row = flow.row(align=True)
box = row.box()
if use_edit:
split = box.split(percentage=0.75)
- row = split.row()
+ row = split.row(align=True)
else:
- row = box.row()
+ row = box.row(align=True)
+
+ row.alignment = 'RIGHT'
row.label(text=key, translate=False)
- # explicit exception for arrays
+ # explicit exception for arrays.
if to_dict or to_list:
row.label(text=val_draw, translate=False)
else:
@@ -186,6 +193,8 @@ def draw(layout, context, context_member, property_type, use_edit=True):
else:
row.label(text="API Defined")
+ del flow
+
class PropertyPanel:
"""
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 4460af173ff..68f49acc186 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -46,10 +46,11 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
for minor_index in range(minor_seg):
angle = pi_2 * minor_index / minor_seg
- vec = matrix * Vector((major_rad + (cos(angle) * minor_rad),
- 0.0,
- sin(angle) * minor_rad,
- ))
+ vec = matrix @ Vector((
+ major_rad + (cos(angle) * minor_rad),
+ 0.0,
+ sin(angle) * minor_rad,
+ ))
verts.extend(vec[:])
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index 2717a4f62a3..d05082b0dd8 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -238,7 +238,7 @@ class CLIP_OT_track_to_empty(Operator):
ob = bpy.data.objects.new(name=track.name, object_data=None)
ob.select_set(action='SELECT')
context.scene.objects.link(ob)
- context.scene.objects.active = ob
+ context.view_layer.objects.active = ob
for con in ob.constraints:
if con.type == 'FOLLOW_TRACK':
@@ -300,7 +300,7 @@ class CLIP_OT_bundles_to_mesh(Operator):
reconstruction = tracking_object.reconstruction
framenr = scene.frame_current - clip.frame_start + 1
reconstructed_matrix = reconstruction.cameras.matrix_from_frame(framenr)
- matrix = camera.matrix_world * reconstructed_matrix.inverted()
+ matrix = camera.matrix_world @ reconstructed_matrix.inverted()
for track in tracking_object.tracks:
if track.has_bundle and track.select:
@@ -314,7 +314,7 @@ class CLIP_OT_bundles_to_mesh(Operator):
ob.matrix_world = matrix
context.scene.objects.link(ob)
ob.select = True
- context.scene.objects.active = ob
+ context.view_layer.objects.active = ob
else:
self.report({'WARNING'}, "No usable tracks selected")
@@ -580,10 +580,12 @@ class CLIP_OT_setup_tracking_scene(Operator):
scene.camera = camob
- camob.matrix_local = (Matrix.Translation((7.481, -6.508, 5.344)) *
- Matrix.Rotation(0.815, 4, 'Z') *
- Matrix.Rotation(0.011, 4, 'Y') *
- Matrix.Rotation(1.109, 4, 'X'))
+ camob.matrix_local = (
+ Matrix.Translation((7.481, -6.508, 5.344)) @
+ Matrix.Rotation(0.815, 4, 'Z') @
+ Matrix.Rotation(0.011, 4, 'Y') @
+ Matrix.Rotation(1.109, 4, 'X')
+ )
return camob
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index a7475dcc6ef..1149d7a0dfb 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -205,57 +205,7 @@ class MeshSelectPrev(Operator):
return {'FINISHED'}
-# XXX This is hackish (going forth and back from Object mode...), to be redone once we have proper support of
-# custom normals in BMesh/edit mode.
-class MehsSetNormalsFromFaces(Operator):
- """Set the custom vertex normals from the selected faces ones"""
- bl_idname = "mesh.set_normals_from_faces"
- bl_label = "Set Normals From Faces"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (context.mode == 'EDIT_MESH' and context.edit_object.data.polygons)
-
- def execute(self, context):
- import mathutils
-
- bpy.ops.object.mode_set(mode='OBJECT')
- obj = context.active_object
- me = obj.data
-
- v2nors = {}
- for p in me.polygons:
- if not p.select:
- continue
- for lidx, vidx in zip(p.loop_indices, p.vertices):
- assert(me.loops[lidx].vertex_index == vidx)
- v2nors.setdefault(vidx, []).append(p.normal)
-
- for nors in v2nors.values():
- nors[:] = [sum(nors, mathutils.Vector((0, 0, 0))).normalized()]
-
- if not me.has_custom_normals:
- me.create_normals_split()
- me.calc_normals_split()
-
- normals = []
- for l in me.loops:
- nor = v2nors.get(l.vertex_index, [None])[0]
- if nor is None:
- nor = l.normal
- normals.append(nor.to_tuple())
-
- me.normals_split_custom_set(normals)
-
- me.free_normals_split()
- bpy.ops.object.mode_set(mode='EDIT')
-
- return {'FINISHED'}
-
-
classes = (
- MehsSetNormalsFromFaces,
MeshMirrorUV,
MeshSelectNext,
MeshSelectPrev,
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index be379ec6089..c49591ff300 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -599,7 +599,7 @@ class MakeDupliFace(Operator):
trans = matrix.to_translation()
rot = matrix.to_3x3() # also contains scale
- return [(rot * b) + trans for b in base_tri]
+ return [(rot @ b) + trans for b in base_tri]
scene = context.scene
linked = {}
for obj in context.selected_objects:
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index f627fd30162..60fb360480f 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -75,7 +75,7 @@ def worldspace_bounds_from_object_data(scene, obj):
me = obj.to_mesh(scene=scene, apply_modifiers=True, settings='PREVIEW')
verts = me.vertices
- val = matrix_world * (verts[-1].co if verts else Vector((0.0, 0.0, 0.0)))
+ val = matrix_world @ (verts[-1].co if verts else Vector((0.0, 0.0, 0.0)))
left, right, front, back, down, up = (
val[0],
@@ -88,7 +88,7 @@ def worldspace_bounds_from_object_data(scene, obj):
# Test against all other verts
for v in verts:
- vco = matrix_world * v.co
+ vco = matrix_world @ v.co
# X Range
val = vco[0]
@@ -146,7 +146,7 @@ def align_objects(context,
for obj in context.selected_objects:
matrix_world = obj.matrix_world.copy()
- bb_world = [matrix_world * Vector(v) for v in obj.bound_box]
+ bb_world = [matrix_world @ Vector(v) for v in obj.bound_box]
objects.append((obj, bb_world))
if not objects:
@@ -216,7 +216,7 @@ def align_objects(context,
for obj, bb_world in objects:
matrix_world = obj.matrix_world.copy()
- bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
+ bb_world = [matrix_world @ Vector(v[:]) for v in obj.bound_box]
if bb_quality and obj.type == 'MESH':
GBB = worldspace_bounds_from_object_data(scene, obj)
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 530194e5bb7..0fe45f8fee3 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -257,7 +257,7 @@ class PresetMenu(Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'HEADER'
bl_label = "Presets"
- path_menu: Menu.path_menu
+ path_menu = Menu.path_menu
@classmethod
def draw_panel_header(cls, layout):
@@ -670,6 +670,42 @@ class AddPresetUnitsLength(AddPresetBase, Operator):
preset_subdir = "units_length"
+class AddPresetGpencilBrush(AddPresetBase, Operator):
+ """Add or remove grease pencil brush preset"""
+ bl_idname = "scene.gpencil_brush_preset_add"
+ bl_label = "Add Grease Pencil Brush Preset"
+ preset_menu = "VIEW3D_PT_gpencil_brush_presets"
+
+ preset_defines = [
+ "brush = bpy.context.active_gpencil_brush",
+ "settings = brush.gpencil_settings"
+ ]
+
+ preset_values = [
+ "settings.input_samples",
+ "settings.active_smooth_factor",
+ "settings.angle",
+ "settings.angle_factor",
+ "settings.use_stabilizer",
+ "brush.smooth_stroke_radius",
+ "brush.smooth_stroke_factor",
+ "settings.pen_smooth_factor",
+ "settings.pen_smooth_steps",
+ "settings.pen_thick_smooth_factor",
+ "settings.pen_thick_smooth_steps",
+ "settings.pen_subdivision_steps",
+ "settings.random_subdiv",
+ "settings.enable_random",
+ "settings.random_pressure",
+ "settings.random_strength",
+ "settings.uv_random",
+ "settings.pen_jitter",
+ "settings.use_jitter_pressure",
+ ]
+
+ preset_subdir = "gpencil_brush"
+
+
classes = (
AddPresetCamera,
AddPresetCloth,
@@ -686,6 +722,7 @@ classes = (
AddPresetTrackingSettings,
AddPresetTrackingTrackColor,
AddPresetUnitsLength,
+ AddPresetGpencilBrush,
ExecutePreset,
WM_MT_operator_presets,
)
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index 36150a63895..46f3d0a1436 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -60,7 +60,7 @@ class CopyRigidbodySettings(Operator):
def execute(self, context):
obj_act = context.object
- scene = context.scene
+ view_layer = context.view_layer
# deselect all but mesh objects
for o in context.selected_objects:
@@ -68,9 +68,9 @@ class CopyRigidbodySettings(Operator):
o.select_set(action='DESELECT')
elif o.rigid_body is None:
# Add rigidbody to object!
- scene.objects.active = o
+ view_layer.objects.active = o
bpy.ops.rigidbody.object_add()
- scene.objects.active = obj_act
+ view_layer.objects.active = obj_act
objects = context.selected_objects
if objects:
@@ -149,7 +149,7 @@ class BakeToKeyframes(Operator):
mat = bake[i][j]
# convert world space transform to parent space, so parented objects don't get offset after baking
if (obj.parent):
- mat = obj.matrix_parent_inverse.inverted() * obj.parent.matrix_world.inverted() * mat
+ mat = obj.matrix_parent_inverse.inverted() @ obj.parent.matrix_world.inverted() @ mat
obj.location = mat.to_translation()
@@ -265,7 +265,7 @@ class ConnectRigidBodies(Operator):
ob = bpy.data.objects.new("Constraint", object_data=None)
ob.location = loc
context.scene.objects.link(ob)
- context.scene.objects.active = ob
+ context.view_layer.objects.active = ob
ob.select_set(action='SELECT')
bpy.ops.rigidbody.constraint_add()
@@ -278,7 +278,7 @@ class ConnectRigidBodies(Operator):
con.object2 = object2
def execute(self, context):
- scene = context.scene
+ view_layer = context.view_layer
objects = context.selected_objects
obj_act = context.active_object
change = False
@@ -312,7 +312,7 @@ class ConnectRigidBodies(Operator):
bpy.ops.object.select_all(action='DESELECT')
for obj in objects:
obj.select_set(action='SELECT')
- scene.objects.active = obj_act
+ view_layer.objects.active = obj_act
return {'FINISHED'}
else:
self.report({'WARNING'}, "No other objects selected")
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 95a3d18304b..b866fb1ce40 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -579,7 +579,7 @@ def unwrap(operator, context, **kwargs):
# define list of meshes
meshes = []
if PREF_ACT_ONLY:
- obj = context.scene.objects.active
+ obj = context.view_layer.objects.active
if obj and obj.type == 'MESH':
meshes = [obj.data]
else:
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index fe15b9fa345..b01a50d5d6a 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -89,7 +89,7 @@ def pointInTri2D(v, v1, v2, v3):
dict_matrix[key] = mtx
- uvw = (v - v1) * mtx
+ uvw = (v - v1) @ mtx
return 0 <= uvw[0] and 0 <= uvw[1] and uvw[0] + uvw[1] <= 1
@@ -258,7 +258,7 @@ def rotate_uvs(uv_points, angle):
if angle != 0.0:
mat = Matrix.Rotation(angle, 2)
for uv in uv_points:
- uv[:] = mat * uv
+ uv[:] = mat @ uv
def optiRotateUvIsland(faces):
@@ -858,7 +858,7 @@ def main(context,
# Initialize projectVecs
if USER_VIEW_INIT:
# Generate Projection
- projectVecs = [Vector(Window.GetViewVector()) * ob.matrix_world.inverted().to_3x3()] # We add to this along the way
+ projectVecs = [Vector(Window.GetViewVector()) @ ob.matrix_world.inverted().to_3x3()] # We add to this along the way
else:
projectVecs = []
@@ -975,7 +975,7 @@ def main(context,
f_uv = f.uv
for j, v in enumerate(f.v):
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
- f_uv[j][:] = (MatQuat * v.co).xy
+ f_uv[j][:] = (MatQuat @ v.co).xy
if USER_SHARE_SPACE:
# Should we collect and pack later?
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index cfbc96696d6..0ccdd3cf5c6 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -2440,9 +2440,9 @@ class WM_OT_studiolight_install(Operator):
)
orientation: EnumProperty(
items=(
- ("MATCAP", "MatCap", ""),
- ("WORLD", "World", ""),
- ("CAMERA", "Camera", ""),
+ ('MATCAP', "MatCap", ""),
+ ('WORLD', "World", ""),
+ ('CAMERA', "Camera", ""),
)
)
@@ -2499,9 +2499,12 @@ class WM_OT_studiolight_uninstall(Operator):
userpref = context.user_preferences
for studio_light in userpref.studio_lights:
if studio_light.index == self.index:
- self._remove_path(pathlib.Path(studio_light.path))
- self._remove_path(pathlib.Path(studio_light.path_irr_cache))
- self._remove_path(pathlib.Path(studio_light.path_sh_cache))
+ if len(studio_light.path) > 0:
+ self._remove_path(pathlib.Path(studio_light.path))
+ if len(studio_light.path_irr_cache) > 0:
+ self._remove_path(pathlib.Path(studio_light.path_irr_cache))
+ if len(studio_light.path_sh_cache) > 0:
+ self._remove_path(pathlib.Path(studio_light.path_sh_cache))
userpref.studio_lights.remove(studio_light)
return {'FINISHED'}
return {'CANCELLED'}
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index e91f3727f20..3b0cc2527a8 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -34,17 +34,20 @@ _modules = [
"properties_data_camera",
"properties_data_curve",
"properties_data_empty",
+ "properties_data_gpencil",
"properties_data_light",
"properties_data_lattice",
"properties_data_mesh",
"properties_data_metaball",
"properties_data_modifier",
+ "properties_data_shaderfx",
"properties_data_lightprobe",
"properties_data_speaker",
"properties_data_workspace",
"properties_hair_common",
"properties_mask_common",
"properties_material",
+ "properties_material_gpencil",
"properties_object",
"properties_paint_common",
"properties_grease_pencil_common",
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 901e15c181a..4033d5c2448 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -29,7 +29,7 @@ class MotionPathButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = "Motion Paths"
- bl_options = {'DEFAULT_CLOSED'}
+ # bl_options = {'DEFAULT_CLOSED'}
def draw_settings(self, context, avs, mpath, bones=False):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 6cfc4b6ea3f..8ea20ada390 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -211,6 +211,7 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
# TODO: this panel will soon be deprecated too
class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
bl_label = "Ghost"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
@@ -328,7 +329,7 @@ class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit from
class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Armature
@@ -340,9 +341,9 @@ classes = (
DATA_MT_bone_group_specials,
DATA_PT_bone_groups,
DATA_PT_pose_library,
+ DATA_PT_motion_paths,
DATA_PT_ghost,
DATA_PT_iksolver_itasc,
- DATA_PT_motion_paths,
DATA_PT_custom_props_arm,
)
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index cc593fbb0a2..6d364ee6539 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -402,7 +402,7 @@ class BONE_PT_deform(BoneButtonsPanel, Panel):
class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_property_type = bpy.types.Bone, bpy.types.EditBone, bpy.types.PoseBone
@property
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 4730fc56602..cc0bde46189 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -39,7 +39,7 @@ class CAMERA_PT_presets(PresetMenu):
preset_subdir = "camera"
preset_operator = "script.execute_preset"
preset_add_operator = "camera.preset_add"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
class SAFE_AREAS_PT_presets(PresetMenu):
@@ -47,13 +47,13 @@ class SAFE_AREAS_PT_presets(PresetMenu):
preset_subdir = "safe_areas"
preset_operator = "script.execute_preset"
preset_add_operator = "safe_areas.preset_add"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -70,7 +70,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
class DATA_PT_lens(CameraButtonsPanel, Panel):
bl_label = "Lens"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -88,7 +88,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
if cam.lens_unit == 'MILLIMETERS':
col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
- row.prop(cam, "angle")
+ col.prop(cam, "angle")
col.prop(cam, "lens_unit")
elif cam.type == 'ORTHO':
@@ -111,7 +111,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
sub = col.column(align=True)
sub.prop(ccam, "longitude_min", text="Longiture Min")
sub.prop(ccam, "longitude_max", text="Max")
- elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE'}:
+ elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}:
if cam.lens_unit == 'MILLIMETERS':
col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
@@ -133,7 +133,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
bl_label = "Stereoscopy"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -181,7 +181,7 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Camera"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header_preset(self, context):
CAMERA_PT_presets.draw_panel_header(self.layout)
@@ -250,21 +250,16 @@ class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
col.prop(dof_options, "rotation")
col.prop(dof_options, "ratio")
else:
- hq_support = dof_options.is_hq_supported
col = flow.column()
col.label("Viewport")
- sub = col.column()
- sub.active = hq_support
- sub.prop(dof_options, "use_high_quality")
col.prop(dof_options, "fstop")
- if dof_options.use_high_quality and hq_support:
- col.prop(dof_options, "blades")
+ col.prop(dof_options, "blades")
class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
bl_label = "Background Images"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
cam = context.camera
@@ -365,7 +360,7 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -398,7 +393,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_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
cam = context.camera
@@ -417,7 +412,7 @@ class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Camera
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index c0ab9da949f..4002568fb7d 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -135,7 +135,7 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -459,7 +459,7 @@ class DATA_PT_text_boxes(CurveButtonsPanelText, Panel):
class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Curve
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
new file mode 100644
index 00000000000..90dc86a20bb
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -0,0 +1,404 @@
+# ##### 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 Menu, Panel, UIList
+from rna_prop_ui import PropertyPanel
+from .properties_grease_pencil_common import (
+ GreasePencilDataPanel,
+ GreasePencilOnionPanel,
+)
+
+###############################
+# Base-Classes (for shared stuff - e.g. poll, attributes, etc.)
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ return context.object and context.object.type == 'GPENCIL'
+
+
+class LayerDataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ return (context.object and
+ context.object.type == 'GPENCIL' and
+ context.active_gpencil_layer)
+
+
+###############################
+# GP Object Properties Panels and Helper Classes
+
+class DATA_PT_gpencil(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ # Grease Pencil data selector
+ gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ layout.template_ID(gpd_owner, "data")
+
+
+class GPENCIL_UL_layer(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.GPencilLayer)
+ gpl = item
+ gpd = context.gpencil_data
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpl.lock:
+ layout.active = False
+
+ row = layout.row(align=True)
+ if gpl.is_parented:
+ icon = 'BONE_DATA'
+ else:
+ icon = 'BLANK1'
+
+ row.label(text="", icon=icon)
+ row.prop(gpl, "info", text="", emboss=False)
+
+ row = layout.row(align=True)
+ row.prop(gpl, "lock", text="", emboss=False)
+ row.prop(gpl, "hide", text="", emboss=False)
+ row.prop(gpl, "unlock_color", text="", emboss=False)
+ if gpl.use_onion_skinning is False:
+ icon = 'GHOST_DISABLED'
+ else:
+ icon = 'GHOST_ENABLED'
+ subrow = row.row(align=True)
+ subrow.prop(gpl, "use_onion_skinning", text="", icon=icon, emboss=False)
+ subrow.active = gpd.use_onion_skinning
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GPENCIL_MT_layer_specials(Menu):
+ bl_label = "Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
+
+ layout.separator()
+
+ layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
+ layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+
+ layout.separator()
+
+ layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
+ layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
+
+ layout.separator()
+
+ layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
+
+
+class DATA_PT_gpencil_datapanel(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Layers"
+
+ @classmethod
+ def poll(cls, context):
+ if context.gpencil_data is None:
+ return False
+
+ ob = context.object
+ if ob is not None and ob.type == 'GPENCIL':
+ return True
+
+ return False
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ #layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ gpd = context.gpencil_data
+
+ # Grease Pencil data...
+ if (gpd is None) or (not gpd.layers):
+ layout.operator("gpencil.layer_add", text="New Layer")
+ else:
+ self.draw_layers(context, layout, gpd)
+
+ def draw_layers(self, context, layout, gpd):
+ row = layout.row()
+
+ col = row.column()
+ if len(gpd.layers) >= 2:
+ layer_rows = 5
+ else:
+ layer_rows = 2
+ col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
+
+ col = row.column()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_add", icon='ZOOMIN', text="")
+ sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="")
+
+ gpl = context.active_gpencil_layer
+ if gpl:
+ sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
+
+ if len(gpd.layers) > 1:
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
+ sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
+ sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
+
+ row = layout.row(align=True)
+ if gpl:
+ row.prop(gpl, "opacity", text="Opacity", slider=True)
+
+
+class DATA_PT_gpencil_layer_optionpanel(LayerDataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Adjustments"
+ bl_parent_id = 'DATA_PT_gpencil_datapanel'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ gpl = context.active_gpencil_layer
+ layout.active = not gpl.lock
+
+ # Layer options
+ # Offsets - Color Tint
+ layout.enabled = not gpl.lock
+ col = layout.column(align=True)
+ col.prop(gpl, "tint_color")
+ col.prop(gpl, "tint_factor", text="Factor", slider=True)
+
+ # Offsets - Thickness
+ col = layout.row(align=True)
+ col.prop(gpl, "line_change", text="Stroke Thickness")
+
+
+class DATA_PT_gpencil_parentpanel(LayerDataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Relations"
+ bl_parent_id = 'DATA_PT_gpencil_datapanel'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ gpl = context.active_gpencil_layer
+ col = layout.column()
+ col.active = not gpl.lock
+ col.prop(gpl, "parent")
+ col.prop(gpl, "parent_type", text="Type")
+ parent = gpl.parent
+
+ if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
+ col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone")
+
+
+class DATA_PT_gpencil_onionpanel(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Onion Skinning"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.active_gpencil_layer)
+
+ @staticmethod
+ def draw_header(self, context):
+ self.layout.prop(context.gpencil_data, "use_onion_skinning", text="")
+
+ def draw(self, context):
+ gpd = context.gpencil_data
+
+ layout = self.layout
+ layout.use_property_split = True
+ layout.enabled = gpd.use_onion_skinning
+
+ GreasePencilOnionPanel.draw_settings(layout, gpd)
+
+
+class GPENCIL_MT_gpencil_vertex_group(Menu):
+ bl_label = "GP Vertex Groups"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'EXEC_AREA'
+ layout.operator("object.vertex_group_add")
+
+ ob = context.active_object
+ if ob.vertex_groups.active:
+ layout.separator()
+
+ layout.operator("gpencil.vertex_group_assign", text="Assign to Active Group")
+ layout.operator("gpencil.vertex_group_remove_from", text="Remove from Active Group")
+
+ layout.separator()
+ layout.operator_menu_enum("object.vertex_group_set_active", "group", text="Set Active Group")
+ layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
+ layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
+
+ layout.separator()
+ layout.operator("gpencil.vertex_group_select", text="Select Points")
+ layout.operator("gpencil.vertex_group_deselect", text="Deselect Points")
+
+
+class GPENCIL_UL_vgroups(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ vgroup = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
+ # icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
+ # layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class DATA_PT_gpencil_vertexpanel(DataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Vertex Groups"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ group = ob.vertex_groups.active
+
+ rows = 2
+ if group:
+ rows = 4
+
+ row = layout.row()
+ row.template_list("GPENCIL_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
+ col.operator("object.vertex_group_remove", icon='ZOOMOUT', text="").all = False
+
+ if ob.vertex_groups:
+ row = layout.row()
+
+ sub = row.row(align=True)
+ sub.operator("gpencil.vertex_group_assign", text="Assign")
+ sub.operator("gpencil.vertex_group_remove_from", text="Remove")
+
+ sub = row.row(align=True)
+ sub.operator("gpencil.vertex_group_select", text="Select")
+ sub.operator("gpencil.vertex_group_deselect", text="Deselect")
+
+ layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
+
+
+class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+
+ gpd = context.gpencil_data
+ gpl = context.active_gpencil_layer
+
+ layout.prop(gpd, "xray_mode", text="Depth Ordering")
+ layout.prop(gpd, "edit_line_color", text="Edit Line Color")
+ layout.prop(ob, "empty_draw_size", text="Marker Size")
+
+ col = layout.column(align=True)
+ col.prop(gpd, "show_constant_thickness")
+ sub = col.column()
+ sub.active = not gpd.show_constant_thickness
+ sub.prop(gpd, "pixfactor", text="Thickness Scale")
+
+ if gpl:
+ layout.prop(gpd, "show_stroke_direction", text="Show Stroke Directions")
+
+
+class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel):
+ _context_path = "object.data"
+ _property_type = bpy.types.GreasePencil
+
+###############################
+
+
+classes = (
+ DATA_PT_gpencil,
+ DATA_PT_gpencil_datapanel,
+ DATA_PT_gpencil_onionpanel,
+ DATA_PT_gpencil_layer_optionpanel,
+ DATA_PT_gpencil_parentpanel,
+ DATA_PT_gpencil_vertexpanel,
+ DATA_PT_gpencil_display,
+ DATA_PT_custom_props_gpencil,
+
+ GPENCIL_UL_layer,
+ GPENCIL_UL_vgroups,
+
+ GPENCIL_MT_layer_specials,
+ GPENCIL_MT_gpencil_vertex_group,
+)
+
+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_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index 40e82bc0a52..9aa8a4dee64 100644
--- a/release/scripts/startup/bl_ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -85,7 +85,7 @@ class DATA_PT_lattice(DataButtonsPanel, Panel):
class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Lattice
diff --git a/release/scripts/startup/bl_ui/properties_data_light.py b/release/scripts/startup/bl_ui/properties_data_light.py
index a92414c0e7c..f5c985f2abe 100644
--- a/release/scripts/startup/bl_ui/properties_data_light.py
+++ b/release/scripts/startup/bl_ui/properties_data_light.py
@@ -36,7 +36,7 @@ class DataButtonsPanel:
class DATA_PT_context_light(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -62,7 +62,7 @@ class DATA_PT_preview(DataButtonsPanel, Panel):
class DATA_PT_light(DataButtonsPanel, Panel):
bl_label = "Light"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -71,38 +71,6 @@ class DATA_PT_light(DataButtonsPanel, Panel):
layout.row().prop(light, "type", expand=True)
- layout.use_property_split = True
-
- col = col.column()
- col.prop(light, "color")
- col.prop(light, "energy")
-
- if light.type in {'POINT', 'SPOT'}:
-
- col = col.column()
- col.label(text="Falloff")
- col.prop(light, "falloff_type")
- col.prop(light, "distance")
- col.prop(light, "shadow_soft_size")
-
- if light.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
- sub = col.column(align=True)
- sub.prop(light, "linear_attenuation", slider=True, text="Linear")
- sub.prop(light, "quadratic_attenuation", slider=True, text="Quadratic")
-
- elif light.falloff_type == 'INVERSE_COEFFICIENTS':
- col.label(text="Inverse Coefficients")
- sub = col.column(align=True)
- sub.prop(light, "constant_coefficient", text="Constant")
- sub.prop(light, "linear_coefficient", text="Linear")
- sub.prop(light, "quadratic_coefficient", text="Quadratic")
-
- if light.type == 'AREA':
- col.prop(light, "distance")
-
- col = split.column()
- col.label()
-
class DATA_PT_EEVEE_light(DataButtonsPanel, Panel):
bl_label = "Light"
@@ -234,7 +202,7 @@ class DATA_PT_EEVEE_shadow_contact(DataButtonsPanel, Panel):
class DATA_PT_area(DataButtonsPanel, Panel):
bl_label = "Area Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -260,43 +228,8 @@ class DATA_PT_area(DataButtonsPanel, Panel):
class DATA_PT_spot(DataButtonsPanel, Panel):
bl_label = "Spot Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- light = context.light
- engine = context.engine
- return (light and light.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- light = context.light
-
- split = layout.split()
-
- col = split.column()
- sub = col.column()
- sub.prop(light, "spot_size", text="Size")
- sub.prop(light, "spot_blend", text="Blend", slider=True)
- col.prop(light, "use_square")
- col.prop(light, "show_cone")
-
- col = split.column()
-
- col.active = (light.shadow_method != 'BUFFER_SHADOW' or light.shadow_buffer_type != 'DEEP')
- col.prop(light, "use_halo")
- sub = col.column(align=True)
- sub.active = light.use_halo
- sub.prop(light, "halo_intensity", text="Intensity")
- if light.shadow_method == 'BUFFER_SHADOW':
- sub.prop(light, "halo_step", text="Step")
-
-
-class DATA_PT_spot(DataButtonsPanel, Panel):
- bl_label = "Spot Shape"
bl_parent_id = "DATA_PT_EEVEE_light"
- COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -337,7 +270,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
class DATA_PT_custom_props_light(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Light
diff --git a/release/scripts/startup/bl_ui/properties_data_lightprobe.py b/release/scripts/startup/bl_ui/properties_data_lightprobe.py
index 10b66dd0033..5924a796b65 100644
--- a/release/scripts/startup/bl_ui/properties_data_lightprobe.py
+++ b/release/scripts/startup/bl_ui/properties_data_lightprobe.py
@@ -155,12 +155,9 @@ class DATA_PT_lightprobe_display(DataButtonsPanel, Panel):
col = layout.column()
- if probe.type != 'PLANAR':
- col.prop(probe, "data_draw_size", text="Size")
- else:
+ if probe.type == 'PLANAR':
col.prop(ob, "empty_draw_size", text="Arrow Size")
-
- col.prop(probe, "show_data")
+ col.prop(probe, "show_data")
if probe.type in {'GRID', 'CUBEMAP'}:
col.prop(probe, "show_influence")
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index e8015327c1d..f096ff83957 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -24,7 +24,6 @@ from rna_prop_ui import PropertyPanel
class MESH_MT_vertex_group_specials(Menu):
bl_label = "Vertex Group Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -48,7 +47,6 @@ class MESH_MT_vertex_group_specials(Menu):
class MESH_MT_shape_key_specials(Menu):
bl_label = "Shape Key Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -137,7 +135,7 @@ class MeshButtonsPanel:
class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -154,7 +152,8 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
class DATA_PT_normals(MeshButtonsPanel, Panel):
bl_label = "Normals"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -174,7 +173,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_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -194,7 +193,7 @@ class DATA_PT_texture_space(MeshButtonsPanel, Panel):
class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
bl_label = "Vertex Groups"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -241,7 +240,8 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
bl_label = "Face Maps"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -283,7 +283,7 @@ class DATA_PT_face_maps(MeshButtonsPanel, Panel):
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -373,7 +373,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
bl_label = "UV Maps"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -392,7 +392,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -412,7 +412,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_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -439,7 +439,7 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
@@ -452,13 +452,13 @@ classes = (
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_face_maps,
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
+ DATA_PT_face_maps,
+ DATA_PT_normals,
+ DATA_PT_texture_space,
DATA_PT_customdata,
DATA_PT_custom_props_mesh,
)
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index 2a61e6cda79..75015a57f5f 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -71,7 +71,7 @@ class DATA_PT_metaball(DataButtonsPanel, Panel):
class DATA_PT_mball_texture_space(DataButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -125,7 +125,7 @@ class DATA_PT_metaball_element(DataButtonsPanel, Panel):
class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.MetaBall
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index cd0617d8f26..e2a537acadd 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -32,6 +32,11 @@ class ModifierButtonsPanel:
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type != 'GPENCIL'
+
def draw(self, context):
layout = self.layout
@@ -140,6 +145,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_only_vertices")
col.prop(md, "use_clamp_overlap")
col.prop(md, "loop_slide")
+ col.prop(md, "mark_seam")
+ col.prop(md, "mark_sharp")
layout.label(text="Limit Method:")
layout.row().prop(md, "limit_method", expand=True)
@@ -152,6 +159,12 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.label(text="Width Method:")
layout.row().prop(md, "offset_type", expand=True)
+ layout.label(text="Normal Mode")
+ layout.row().prop(md, "hnmode", expand=True)
+ layout.prop(md, "hn_strength")
+ layout.prop(md, "set_wn_strength")
+
+
def BOOLEAN(self, layout, ob, md):
split = layout.split()
@@ -736,23 +749,25 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "particle_amount", text="Amount")
row.prop(md, "particle_offset", text="Offset")
+ row = layout.row(align=True)
+ row.prop(md, "axis", expand=True)
+
layout.separator()
layout.prop(md, "use_path", text="Create Along Paths")
- split = layout.split()
- split.active = md.use_path
- col = split.column()
- col.row().prop(md, "axis", expand=True)
+ col = layout.column()
+ col.active = md.use_path
col.prop(md, "use_preserve_shape")
- col = split.column()
- col2 = col.column(align=True)
- col2.prop(md, "position", slider=True)
- col2.prop(md, "random_position", text="Random", slider=True)
- col2 = col.column(align=True)
- col2.prop(md, "rotation", slider=True)
- col2.prop(md, "random_rotation", text="Random", slider=True)
+ row = col.row(align=True)
+ row.prop(md, "position", slider=True)
+ row.prop(md, "random_position", text="Random", slider=True)
+ row = col.row(align=True)
+ row.prop(md, "rotation", slider=True)
+ row.prop(md, "random_rotation", text="Random", slider=True)
+
+ layout.separator()
col = layout.column()
col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer")
@@ -1583,9 +1598,468 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label("Display Settings:")
draw_hair_display_settings(col, md.draw_settings)
+ def WEIGHTED_NORMAL(self, layout, ob, md):
+ layout.label("Weighting Mode:")
+ split = layout.split(align=True)
+ col = split.column(align=True)
+ col.prop(md, "mode", text="")
+ col.prop(md, "weight", text="Weight")
+ col.prop(md, "keep_sharp")
+
+ col = split.column(align=True)
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.active = bool(md.vertex_group)
+ row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+ col.prop(md, "thresh", text="Threshold")
+ col.prop(md, "face_influence")
+
+
+class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
+ bl_label = "Modifiers"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+
+ layout.operator_menu_enum("object.gpencil_modifier_add", "type")
+
+ for md in ob.grease_pencil_modifiers:
+ box = layout.template_greasepencil_modifier(md)
+ if box:
+ # match enum type to our functions, avoids a lookup table.
+ getattr(self, md.type)(box, ob, md)
+
+ # the mt.type enum is (ab)used for a lookup on function names
+ # ...to avoid lengthy if statements
+ # so each type must have a function here.
+
+ def GP_NOISE(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "factor")
+ row.prop(md, "random", text="", icon="TIME", toggle=True)
+ row = col.row()
+ row.enabled = md.random
+ row.prop(md, "step")
+ col.prop(md, "full_stroke")
+ col.prop(md, "move_extreme")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.label("Affect:")
+ row = layout.row(align=True)
+ row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
+ row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
+ row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
+ row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
+
+ def GP_SMOOTH(self, layout, ob, md):
+ gpd = ob.data
+ row = layout.row(align=False)
+ row.prop(md, "factor")
+ row.prop(md, "step")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col = split.column()
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.label("Affect:")
+ row = layout.row(align=True)
+ row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
+ row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
+ row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
+ row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
+
+ def GP_SUBDIV(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "level")
+ row.prop(md, "simple", text="", icon="PARTICLE_POINT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_SIMPLIFY(self, layout, ob, md):
+ gpd = ob.data
+
+ row = layout.row()
+ row.prop(md, "mode")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label("Settings:")
+ row = col.row(align=True)
+ row.enabled = md.mode == 'FIXED'
+ row.prop(md, "step")
+
+ row = col.row(align=True)
+ row.enabled = not md.mode == 'FIXED'
+ row.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_THICK(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "thickness")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ col.prop(md, "normalize_thickness")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ if not md.normalize_thickness:
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "use_custom_curve")
+
+ if md.use_custom_curve:
+ col.template_curve_mapping(md, "curve")
+
+ def GP_TINT(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "color")
+ col.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row()
+ row.prop(md, "create_materials")
+ row.prop(md, "modify_color")
+
+
+ def GP_COLOR(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label("Color:")
+ col.prop(md, "hue", text="H")
+ col.prop(md, "saturation", text="S")
+ col.prop(md, "value", text="V")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row()
+ row.prop(md, "create_materials")
+ row.prop(md, "modify_color")
+
+ def GP_OPACITY(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label("Opacity:")
+ col.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row()
+ row.prop(md, "create_materials")
+ row.prop(md, "modify_color")
+
+ def GP_INSTANCE(self, layout, ob, md):
+ gpd = ob.data
+
+ col = layout.column()
+ col.prop(md, "count")
+ col.prop(md, "use_make_objects")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Offset:")
+ col.prop(md, "offset", text="")
+
+ col = split.column()
+ col.label("Shift:")
+ col.prop(md, "shift", text="")
+ row = col.row(align=True)
+ row.prop(md, "lock_axis", expand=True)
+
+ split = layout.split()
+ col = split.column()
+ col.label("Rotation:")
+ col.prop(md, "rotation", text="")
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "random_rot", text="", icon="TIME", toggle=True)
+ row.prop(md, "rot_factor", text="")
+
+ col = split.column()
+ col.label("Scale:")
+ col.prop(md, "scale", text="")
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "random_scale", text="", icon="TIME", toggle=True)
+ row.prop(md, "scale_factor", text="")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_BUILD(self, layout, ob, md):
+ gpd = ob.data
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "mode")
+ if md.mode == 'CONCURRENT':
+ col.prop(md, "concurrent_time_alignment")
+ else:
+ col.separator() # For spacing
+ col.separator()
+ col.separator()
+
+ col.prop(md, "transition")
+ sub = col.column(align=True)
+ sub.prop(md, "start_delay")
+ sub.prop(md, "length")
+
+ col = split.column(align=True)
+ col.prop(md, "use_restrict_frame_range")
+ sub = col.column(align=True)
+ sub.active = md.use_restrict_frame_range
+ sub.prop(md, "frame_start", text="Start")
+ sub.prop(md, "frame_end", text="End")
+ col.separator()
+
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_LATTICE(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ layout.separator()
+ layout.prop(md, "strength", slider=True)
+
+ def GP_MIRROR(self, layout, ob, md):
+ gpd = ob.data
+
+ row = layout.row(align=True)
+ row.prop(md, "x_axis")
+ row.prop(md, "y_axis")
+ row.prop(md, "z_axis")
+
+ # GPXX: Not implemented yet
+ # layout.separator()
+ # layout.prop(md, "clip")
+
+ layout.label("Layer:")
+ row = layout.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ layout.label(text="Object:")
+ layout.prop(md, "object", text="")
+
+ def GP_HOOK(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+ if md.object and md.object.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "subtarget", md.object.data, "bones", text="")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ use_falloff = (md.falloff_type != 'NONE')
+ split = layout.split()
+
+ layout.separator()
+
+ row = layout.row(align=True)
+ if use_falloff:
+ row.prop(md, "falloff_radius")
+ row.prop(md, "strength", slider=True)
+ layout.prop(md, "falloff_type")
+
+ col = layout.column()
+ if use_falloff:
+ if md.falloff_type == 'CURVE':
+ col.template_curve_mapping(md, "falloff_curve")
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "use_falloff_uniform")
+
+ def GP_OFFSET(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "location")
+ col.prop(md, "scale")
+
+ col = split.column()
+ col.prop(md, "rotation")
+
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
classes = (
DATA_PT_modifiers,
+ DATA_PT_gpencil_modifiers,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
new file mode 100644
index 00000000000..3798a273e09
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
@@ -0,0 +1,135 @@
+# ##### 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 Panel
+from bpy.app.translations import pgettext_iface as iface_
+
+
+class ShaderFxButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "shaderfx"
+ bl_options = {'HIDE_HEADER'}
+
+
+class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
+ bl_label = "Effects"
+
+ @classmethod
+ def poll(cls, context):
+ return True
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+
+ layout.operator_menu_enum("object.shaderfx_add", "type")
+
+ for fx in ob.shader_effects:
+ box = layout.template_shaderfx(fx)
+ if box:
+ # match enum type to our functions, avoids a lookup table.
+ getattr(self, fx.type)(box, fx)
+
+ # the mt.type enum is (ab)used for a lookup on function names
+ # ...to avoid lengthy if statements
+ # so each type must have a function here.
+
+ def FX_BLUR(self, layout, fx):
+
+ layout.prop(fx, "factor", text="Factor")
+ layout.prop(fx, "samples", text="Samples")
+
+ layout.separator()
+ layout.prop(fx, "use_dof_mode")
+ if fx.use_dof_mode:
+ layout.prop(fx, "coc")
+
+ def FX_COLORIZE(self, layout, fx):
+ layout.prop(fx, "mode", text="Mode")
+
+ if fx.mode == 'BITONE':
+ layout.prop(fx, "low_color", text="Low Color")
+ if fx.mode == 'CUSTOM':
+ layout.prop(fx, "low_color", text="Color")
+
+ if fx.mode == 'BITONE':
+ layout.prop(fx, "high_color", text="High Color")
+
+ if fx.mode in {'BITONE', 'CUSTOM', 'TRANSPARENT'}:
+ layout.prop(fx, "factor")
+
+ def FX_WAVE(self, layout, fx):
+ layout.prop(fx, "orientation", expand=True)
+
+ layout.separator()
+ layout.prop(fx, "amplitude")
+ layout.prop(fx, "period")
+ layout.prop(fx, "phase")
+
+ def FX_PIXEL(self, layout, fx):
+ layout.prop(fx, "size", text="Size")
+
+ layout.prop(fx, "use_lines", text="Display Lines")
+
+ col = layout.column()
+ col.enabled = fx.use_lines
+ col.prop(fx, "color")
+
+ def FX_RIM(self, layout, fx):
+ layout.prop(fx, "offset", text="Offset")
+
+ layout.prop(fx, "rim_color")
+ layout.prop(fx, "mask_color")
+ layout.prop(fx, "mode")
+ layout.prop(fx, "blur")
+ layout.prop(fx, "samples")
+
+ def FX_SWIRL(self, layout, fx):
+ layout.prop(fx, "object", text="Object")
+
+ layout.prop(fx, "radius")
+ layout.prop(fx, "angle")
+
+ layout.prop(fx, "transparent")
+
+ def FX_FLIP(self, layout, fx):
+ layout.prop(fx, "flip_horizontal")
+ layout.prop(fx, "flip_vertical")
+
+ def FX_LIGHT(self, layout, fx):
+ layout.prop(fx, "object", text="Object")
+
+ layout.prop(fx, "energy")
+ layout.prop(fx, "ambient")
+
+
+classes = (
+ DATA_PT_shader_fx,
+)
+
+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_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py
index 2a3dc4d02c1..d7c93095489 100644
--- a/release/scripts/startup/bl_ui/properties_data_speaker.py
+++ b/release/scripts/startup/bl_ui/properties_data_speaker.py
@@ -36,7 +36,7 @@ class DataButtonsPanel:
class DATA_PT_context_speaker(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -55,7 +55,7 @@ class DATA_PT_context_speaker(DataButtonsPanel, Panel):
class DATA_PT_speaker(DataButtonsPanel, Panel):
bl_label = "Sound"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -76,7 +76,7 @@ class DATA_PT_speaker(DataButtonsPanel, Panel):
class DATA_PT_distance(DataButtonsPanel, Panel):
bl_label = "Distance"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -99,7 +99,7 @@ class DATA_PT_distance(DataButtonsPanel, Panel):
class DATA_PT_cone(DataButtonsPanel, Panel):
bl_label = "Cone"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -121,7 +121,7 @@ class DATA_PT_cone(DataButtonsPanel, Panel):
class DATA_PT_custom_props_speaker(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object.data"
_property_type = bpy.types.Speaker
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 a2ccfb4f1b8..336e4acfd8f 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -18,45 +18,30 @@
# <pep8 compliant>
-
+import bpy
from bpy.types import Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
def gpencil_stroke_placement_settings(context, layout):
if context.space_data.type == 'VIEW_3D':
- propname = "gpencil_stroke_placement_view3d"
+ propname = "annotation_stroke_placement_view3d"
elif context.space_data.type == 'SEQUENCE_EDITOR':
- propname = "gpencil_stroke_placement_sequencer_preview"
+ propname = "annotation_stroke_placement_sequencer_preview"
elif context.space_data.type == 'IMAGE_EDITOR':
- propname = "gpencil_stroke_placement_image_editor"
+ propname = "annotation_stroke_placement_image_editor"
else:
- propname = "gpencil_stroke_placement_view2d"
+ propname = "annotation_stroke_placement_view2d"
ts = context.tool_settings
col = layout.column(align=True)
- col.label(text="Stroke Placement:")
-
- row = col.row(align=True)
- row.prop_enum(ts, propname, 'VIEW')
- row.prop_enum(ts, propname, 'CURSOR')
-
- if context.space_data.type == 'VIEW_3D':
+ if context.space_data.type != 'VIEW_3D':
+ col.label(text="Stroke Placement:")
row = col.row(align=True)
- row.prop_enum(ts, propname, 'SURFACE')
- row.prop_enum(ts, propname, 'STROKE')
-
- row = col.row(align=False)
- row.active = getattr(ts, propname) in {'SURFACE', 'STROKE'}
- row.prop(ts, "use_gpencil_stroke_endpoints")
-
- if context.scene.tool_settings.gpencil_stroke_placement_view3d == 'CURSOR':
- row = col.row(align=True)
- row.label("Lock axis:")
- row = col.row(align=True)
- row.prop(ts.gpencil_sculpt, "lockaxis", expand=True)
+ row.prop_enum(ts, propname, 'VIEW')
+ row.prop_enum(ts, propname, 'CURSOR', text="Cursor")
def gpencil_active_brush_settings_simple(context, layout):
@@ -73,7 +58,7 @@ def gpencil_active_brush_settings_simple(context, layout):
row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA')
row.prop(brush, "name", text="")
- col.prop(brush, "line_width", slider=True)
+ col.prop(brush, "size", slider=True)
row = col.row(align=True)
row.prop(brush, "use_random_pressure", text="", icon='RNDCURVE')
row.prop(brush, "pen_sensitivity_factor", slider=True)
@@ -90,6 +75,7 @@ def gpencil_active_brush_settings_simple(context, layout):
row.prop(brush, "angle_factor", text="Factor", slider=True)
+# XXX: To be replaced with active tools
class GreasePencilDrawingToolsPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
@@ -99,8 +85,7 @@ class GreasePencilDrawingToolsPanel:
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
+ return True
@staticmethod
def draw(self, context):
@@ -113,12 +98,12 @@ class GreasePencilDrawingToolsPanel:
col.label(text="Draw:")
row = col.row(align=True)
- row.operator("gpencil.draw", icon='GREASEPENCIL', text="Draw").mode = 'DRAW'
- row.operator("gpencil.draw", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' # XXX: Needs a dedicated icon
+ row.operator("gpencil.annotate", icon='GREASEPENCIL', text="Draw").mode = 'DRAW'
+ row.operator("gpencil.annotate", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' # XXX: Needs a dedicated icon
row = col.row(align=True)
- row.operator("gpencil.draw", icon='LINE_DATA', text="Line").mode = 'DRAW_STRAIGHT'
- row.operator("gpencil.draw", icon='MESH_DATA', text="Poly").mode = 'DRAW_POLY'
+ row.operator("gpencil.annotate", icon='LINE_DATA', text="Line").mode = 'DRAW_STRAIGHT'
+ row.operator("gpencil.annotate", icon='MESH_DATA', text="Poly").mode = 'DRAW_POLY'
col.separator()
@@ -126,15 +111,15 @@ class GreasePencilDrawingToolsPanel:
sub.operator("gpencil.blank_frame_add", icon='NEW')
sub.operator("gpencil.active_frames_delete_all", icon='X', text="Delete Frame(s)")
- sub = col.column(align=True)
- sub.prop(context.tool_settings, "use_gpencil_additive_drawing", text="Additive Drawing")
- sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing")
- sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back")
+ #sub = col.column(align=True)
+ #sub.prop(context.tool_settings, "use_gpencil_additive_drawing", text="Additive Drawing")
+ #sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing")
+ #sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back")
col.separator()
col.separator()
- if context.space_data.type in {'VIEW_3D', 'CLIP_EDITOR'}:
+ if context.space_data.type in {'CLIP_EDITOR'}:
col.separator()
col.label("Data Source:")
row = col.row(align=True)
@@ -143,8 +128,8 @@ class GreasePencilDrawingToolsPanel:
elif is_clip_editor:
row.prop(context.space_data, "grease_pencil_source", expand=True)
- col.separator()
- col.separator()
+ # col.separator()
+ # col.separator()
gpencil_stroke_placement_settings(context, col)
@@ -157,28 +142,16 @@ class GreasePencilDrawingToolsPanel:
col = layout.column(align=True)
col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
- if is_3d_view:
- col.separator()
- col.separator()
-
- col.label(text="Tools:")
- col.operator_menu_enum("gpencil.convert", text="Convert to Geometry...", property="type")
- col.operator("view3d.ruler")
-
class GreasePencilStrokeEditPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
bl_label = "Edit Strokes"
- bl_category = "Grease Pencil"
+ bl_category = "Tools"
bl_region_type = 'TOOLS'
- bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
if context.gpencil_data is None:
return False
@@ -204,7 +177,7 @@ class GreasePencilStrokeEditPanel:
col.operator("gpencil.select_linked")
col.operator("gpencil.select_more")
col.operator("gpencil.select_less")
- col.operator("gpencil.palettecolor_select")
+ col.operator("gpencil.select_alternate")
layout.label(text="Edit:")
row = layout.row(align=True)
@@ -228,261 +201,125 @@ class GreasePencilStrokeEditPanel:
layout.separator()
- col = layout.column(align=True)
- col.operator("transform.bend", text="Bend")
- col.operator("transform.mirror", text="Mirror")
- col.operator("transform.shear", text="Shear")
- col.operator("transform.tosphere", text="To Sphere")
-
layout.separator()
col = layout.column(align=True)
col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
- col.operator("gpencil.stroke_change_color", text="Move to Color")
-
- if is_3d_view:
- layout.separator()
+ col.operator("gpencil.stroke_change_color", text="Assign Material")
layout.separator()
col = layout.column(align=True)
col.operator("gpencil.stroke_subdivide", text="Subdivide")
- col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
- col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
- col.operator("gpencil.stroke_flip", text="Flip Direction")
-
- gpd = context.gpencil_data
- if gpd:
- col.prop(gpd, "show_stroke_direction", text="Show Directions")
-
- if is_3d_view:
- layout.separator()
- layout.operator_menu_enum("gpencil.reproject", text="Reproject Strokes...", property="type")
-
-
-class GreasePencilInterpolatePanel:
- bl_space_type = 'VIEW_3D'
- bl_label = "Interpolate"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.gpencil_data is None:
- return False
- elif context.space_data.type != 'VIEW_3D':
- return False
-
- gpd = context.gpencil_data
- return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
-
- @staticmethod
- def draw(self, context):
- layout = self.layout
- settings = context.tool_settings.gpencil_interpolate
-
- col = layout.column(align=True)
- col.operator("gpencil.interpolate", text="Interpolate")
- col.operator("gpencil.interpolate_sequence", text="Sequence")
- col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
-
- col = layout.column(align=True)
- col.label(text="Options:")
- col.prop(settings, "interpolate_all_layers")
- col.prop(settings, "interpolate_selected_only")
-
- col = layout.column(align=True)
- col.label(text="Sequence Options:")
- col.prop(settings, "type")
- if settings.type == 'CUSTOM':
- box = layout.box()
- # TODO: Options for loading/saving curve presets?
- box.template_curve_mapping(settings, "interpolation_curve", brush=True)
- elif settings.type != 'LINEAR':
- col.prop(settings, "easing")
-
- if settings.type == 'BACK':
- layout.prop(settings, "back")
- elif setting.type == 'ELASTIC':
- sub = layout.column(align=True)
- sub.prop(settings, "amplitude")
- sub.prop(settings, "period")
-
-
-class GreasePencilBrushPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Drawing Brushes"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
+ row = col.row(align=True)
+ row.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ row.operator("gpencil.stroke_simplify", text="Adaptative")
- @staticmethod
- def draw(self, context):
- layout = self.layout
+ col.separator()
- row = layout.row()
- col = row.column()
- ts = context.scene.tool_settings
- if len(ts.gpencil_brushes) >= 2:
- brows = 3
- else:
- brows = 2
- col.template_list("GPENCIL_UL_brush", "", ts, "gpencil_brushes", ts.gpencil_brushes, "active_index", rows=brows)
+ row = col.row(align=True)
+ row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
+ row.operator("gpencil.stroke_join", text="& Copy").type = 'JOINCOPY'
- col = row.column()
+ col.operator("gpencil.stroke_flip", text="Flip Direction")
- sub = col.column(align=True)
- sub.operator("gpencil.brush_add", icon='ZOOMIN', text="")
- sub.operator("gpencil.brush_remove", icon='ZOOMOUT', text="")
- sub.menu("GPENCIL_MT_brush_specials", icon='DOWNARROW_HLT', text="")
- brush = context.active_gpencil_brush
- if brush:
- if len(ts.gpencil_brushes) > 1:
- col.separator()
- sub = col.column(align=True)
- sub.operator("gpencil.brush_move", icon='TRIA_UP', text="").type = 'UP'
- sub.operator("gpencil.brush_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+ if is_3d_view:
+ layout.separator()
- # Brush details
- if brush is not None:
- row = layout.row()
- row.prop(brush, "line_width")
- row = layout.row(align=True)
- row.prop(brush, "use_random_pressure", text="", icon='RNDCURVE')
- row.prop(brush, "pen_sensitivity_factor", slider=True)
- row.prop(brush, "use_pressure", text="", icon='STYLUS_PRESSURE')
- row = layout.row(align=True)
- row.prop(brush, "use_random_strength", text="", icon='RNDCURVE')
- row.prop(brush, "strength", slider=True)
- row.prop(brush, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
- row = layout.row(align=True)
- row.prop(brush, "random_press", slider=True)
+ col = layout.column(align=True)
+ col.operator_menu_enum("gpencil.stroke_separate", text="Separate...", property="mode")
+ col.operator("gpencil.stroke_split", text="Split")
- row = layout.row(align=True)
- row.prop(brush, "jitter", slider=True)
- row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
- row = layout.row()
- row.prop(brush, "angle", slider=True)
- row.prop(brush, "angle_factor", text="Factor", slider=True)
-
- box = layout.box()
- col = box.column(align=True)
- col.label(text="Stroke Quality:")
- col.prop(brush, "pen_smooth_factor")
- col.prop(brush, "pen_smooth_steps")
- col.separator()
- row = col.row(align=False)
- row.prop(brush, "pen_subdivision_steps")
- row.prop(brush, "random_subdiv", text="Randomness", slider=True)
+ col = layout.column(align=True)
+ col.label(text="Cleanup:")
+ col.operator_menu_enum("gpencil.reproject", text="Reproject Strokes...", property="type")
+ col.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
class GreasePencilStrokeSculptPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
bl_label = "Sculpt Strokes"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.gpencil_data is None:
- return False
-
- gpd = context.gpencil_data
- return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+ bl_category = "Tools"
@staticmethod
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
settings = context.tool_settings.gpencil_sculpt
tool = settings.tool
brush = settings.brush
- layout.column().prop(settings, "tool")
+ layout.template_icon_view(settings, "tool", show_labels=True)
- col = layout.column()
- col.prop(brush, "size", slider=True)
- row = col.row(align=True)
+ layout.prop(brush, "size", slider=True)
+ row = layout.row(align=True)
row.prop(brush, "strength", slider=True)
row.prop(brush, "use_pressure_strength", text="")
- col.prop(brush, "use_falloff")
- if tool in {'SMOOTH', 'RANDOMIZE'}:
- row = layout.row(align=True)
- row.prop(settings, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
- row.prop(settings, "affect_strength", text="Strength", icon='COLOR', toggle=True)
- row.prop(settings, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
- layout.separator()
+ layout.prop(brush, "use_falloff")
- if tool == 'THICKNESS':
- layout.row().prop(brush, "direction", expand=True)
- elif tool == 'PINCH':
- row = layout.row(align=True)
- row.prop_enum(brush, "direction", 'ADD', text="Pinch")
- row.prop_enum(brush, "direction", 'SUBTRACT', text="Inflate")
- elif settings.tool == 'TWIST':
- row = layout.row(align=True)
- row.prop_enum(brush, "direction", 'SUBTRACT', text="CW")
- row.prop_enum(brush, "direction", 'ADD', text="CCW")
+ if tool in {'SMOOTH', 'RANDOMIZE'}:
+ layout.prop(settings, "affect_position", text="Affect Position")
+ layout.prop(settings, "affect_strength", text="Affect Strength")
+ layout.prop(settings, "affect_thickness", text="Affect Thickness")
- row = layout.row(align=True)
- row.prop(settings, "use_select_mask")
- row = layout.row(align=True)
- row.prop(settings, "selection_alpha", slider=True)
+ if tool == 'SMOOTH':
+ layout.prop(brush, "affect_pressure")
- if tool == 'SMOOTH':
- layout.prop(brush, "affect_pressure")
+ layout.prop(settings, "affect_uv", text="Affect UV")
+ if tool in {'THICKNESS', 'PINCH', 'TWIST'}:
+ layout.prop(brush, "direction", expand=True)
-class GreasePencilBrushCurvesPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Brush Curves"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
+
+# GP Object Tool Settings
+class GreasePencilAppearancePanel:
+ bl_label = "Brush Appearance"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.active_gpencil_brush is None:
- return False
-
- brush = context.active_gpencil_brush
- return bool(brush)
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL'
@staticmethod
def draw(self, context):
layout = self.layout
- brush = context.active_gpencil_brush
- # Brush
- layout.label("Sensitivity")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_sensitivity", brush=True)
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ ob = context.active_object
- layout.label("Strength")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_strength", brush=True)
+ if ob.mode == 'GPENCIL_PAINT':
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
- layout.label("Jitter")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_jitter", brush=True)
+ layout.prop(gp_settings, "gpencil_brush_type", text="Brush Type")
+ sub = layout.column(align=True)
+ sub.enabled = not brush.use_custom_icon
+ sub.prop(gp_settings, "gp_icon", text="Icon")
+
+ layout.prop(brush, "use_custom_icon")
+ sub = layout.column()
+ sub.active = brush.use_custom_icon
+ sub.prop(brush, "icon_filepath", text="")
+
+ layout.prop(gp_settings, "use_cursor", text="Show Brush")
+
+ if gp_settings.gpencil_brush_type == 'FILL':
+ layout.prop(brush, "cursor_color_add", text="Color")
+
+ elif ob.mode in ('GPENCIL_SCULPT', 'GPENCIL_WEIGHT'):
+ settings = context.tool_settings.gpencil_sculpt
+ brush = settings.brush
+
+ col = layout.column(align=True)
+ col.prop(brush, "use_cursor", text="Show Brush")
+ col.row().prop(brush, "cursor_color_add", text="Add")
+ col.row().prop(brush, "cursor_color_sub", text="Subtract")
-###############################
class GPENCIL_MT_pie_tool_palette(Menu):
"""A pie menu for quick access to Grease Pencil tools"""
@@ -539,6 +376,7 @@ class GPENCIL_MT_pie_tool_palette(Menu):
col.operator("gpencil.select_border", text="Border Select", icon='BORDER_RECT')
col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
+ col.operator("gpencil.select_alternate", text="Alternate Select", icon='BORDER_LASSO')
# SW - Edit Tools
col = pie.column()
@@ -566,7 +404,7 @@ class GPENCIL_MT_pie_settings_palette(Menu):
pie = layout.menu_pie()
gpd = context.gpencil_data
gpl = context.active_gpencil_layer
- palcolor = context.active_gpencil_palettecolor
+ palcolor = None # context.active_gpencil_palettecolor
brush = context.active_gpencil_brush
is_editmode = bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
@@ -668,7 +506,7 @@ class GPENCIL_MT_pie_tools_more(Menu):
class GPENCIL_MT_pie_sculpt(Menu):
- """A pie menu for accessing Grease Pencil stroke sculpting settings"""
+ """A pie menu for accessing Grease Pencil stroke sculpt settings"""
bl_label = "Grease Pencil Sculpt"
@classmethod
@@ -717,9 +555,6 @@ class GPENCIL_MT_pie_sculpt(Menu):
row.prop_enum(settings, "tool", value='RANDOMIZE')
-###############################
-
-
class GPENCIL_MT_snap(Menu):
bl_label = "Snap"
@@ -728,7 +563,7 @@ class GPENCIL_MT_snap(Menu):
layout.operator("gpencil.snap_to_grid", text="Selection to Grid")
layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor").use_offset = False
- layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Offset)").use_offset = True
+ layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True
layout.separator()
@@ -737,185 +572,110 @@ class GPENCIL_MT_snap(Menu):
layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
-class GPENCIL_MT_gpencil_edit_specials(Menu):
- bl_label = "GPencil Specials"
+class GPENCIL_MT_separate(Menu):
+ bl_label = "Separate"
def draw(self, context):
layout = self.layout
- is_3d_view = context.space_data.type == 'VIEW_3D'
+ layout.operator("gpencil.stroke_separate", text="Selected Points").mode = 'POINT'
+ layout.operator("gpencil.stroke_separate", text="Selected Strokes").mode = 'STROKE'
+ layout.operator("gpencil.stroke_separate", text="Active Layer").mode = 'LAYER'
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.operator("gpencil.stroke_subdivide", text="Subdivide")
- layout.separator()
+class GPENCIL_MT_gpencil_draw_specials(Menu):
+ bl_label = "GPencil Draw Specials"
- layout.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
- layout.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
- layout.operator("gpencil.stroke_flip", text="Flip Direction")
-
- if is_3d_view:
- layout.separator()
- layout.operator("gpencil.reproject")
-
-
-###############################
+ def draw(self, context):
+ layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
+ layout.operator_context = 'INVOKE_REGION_WIN'
-class GPENCIL_UL_brush(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.GPencilBrush)
- brush = item
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- row = layout.row(align=True)
- row.prop(brush, "name", text="", emboss=False, icon='BRUSH_DATA')
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
+ layout.separator()
+ layout.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE'
+ layout.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX'
+ layout.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE'
+ # Colors.
+ layout.separator()
+ layout.operator("gpencil.colorpick", text="Colors", icon="GROUP_VCOL")
-class GPENCIL_UL_palettecolor(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.PaletteColor)
- palcolor = item
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- if palcolor.lock:
- layout.active = False
+class GPENCIL_MT_gpencil_draw_delete(Menu):
+ bl_label = "GPencil Draw Delete"
- split = layout.split(percentage=0.25)
- row = split.row(align=True)
- row.enabled = not palcolor.lock
- row.prop(palcolor, "color", text="", emboss=palcolor.is_stroke_visible)
- row.prop(palcolor, "fill_color", text="", emboss=palcolor.is_fill_visible)
- split.prop(palcolor, "name", text="", emboss=False)
+ def draw(self, context):
+ layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
- row = layout.row(align=True)
- row.prop(palcolor, "lock", text="", emboss=False)
- row.prop(palcolor, "hide", text="", emboss=False)
- if palcolor.ghost is True:
- icon = 'GHOST_DISABLED'
- else:
- icon = 'GHOST_ENABLED'
- row.prop(palcolor, "ghost", text="", icon=icon, emboss=False)
+ layout.operator_context = 'INVOKE_REGION_WIN'
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
+ layout.operator("gpencil.active_frames_delete_all", text="Delete Frame")
-class GPENCIL_UL_layer(UIList):
+class GPENCIL_UL_annotation_layer(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.GPencilLayer)
gpl = item
+ gpd = context.gpencil_data
if self.layout_type in {'DEFAULT', 'COMPACT'}:
if gpl.lock:
layout.active = False
- row = layout.row(align=True)
- if gpl.is_parented:
- icon = 'BONE_DATA'
- else:
- icon = 'BLANK1'
-
- row.label(text="", icon=icon)
- row.prop(gpl, "info", text="", emboss=False)
+ split = layout.split(percentage=0.2)
+ split.prop(gpl, "color", text="", emboss=True)
+ split.prop(gpl, "info", text="", emboss=False)
row = layout.row(align=True)
- row.prop(gpl, "lock", text="", emboss=False)
+ # row.prop(gpl, "lock", text="", emboss=False)
row.prop(gpl, "hide", text="", emboss=False)
- row.prop(gpl, "unlock_color", text="", emboss=False)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
-class GPENCIL_MT_layer_specials(Menu):
- bl_label = "Layer"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
-
- layout.separator()
-
- layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
- layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
-
- layout.separator()
-
- layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
- layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
-
- layout.separator()
-
- layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
-
-
-class GPENCIL_MT_brush_specials(Menu):
- bl_label = "Layer"
-
- def draw(self, context):
- layout = self.layout
- layout.operator("gpencil.brush_copy", icon='PASTEDOWN', text="Copy Current Drawing Brush")
- layout.operator("gpencil.brush_presets_create", icon='HELP', text="Create a Set of Predefined Brushes")
-
-
-class GPENCIL_MT_palettecolor_specials(Menu):
- bl_label = "Layer"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("gpencil.palettecolor_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
- layout.operator("gpencil.palettecolor_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
-
- layout.separator()
-
- layout.operator("gpencil.palettecolor_lock_all", icon='LOCKED', text="Lock All")
- layout.operator("gpencil.palettecolor_unlock_all", icon='UNLOCKED', text="UnLock All")
- layout.operator("gpencil.palettecolor_copy", icon='PASTEDOWN', text="Copy Color")
-
- layout.separator()
-
- layout.operator("gpencil.palettecolor_select", icon='COLOR', text="Select Strokes")
- layout.operator("gpencil.stroke_change_color", icon='MAN_TRANS', text="Move to Color")
-
-
class GreasePencilDataPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Grease Pencil Layers"
+ bl_label = "Annotations"
bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ # Show this panel as long as someone that might own this exists
+ # AND the owner isn't an object (e.g. GP Object)
+ if context.gpencil_data_owner is None:
+ return False
+ elif type(context.gpencil_data_owner) is bpy.types.Object:
+ return False
+ else:
+ return True
@staticmethod
def draw_header(self, context):
- self.layout.prop(context.space_data, "show_grease_pencil", text="")
+ if context.space_data.type != 'VIEW_3D':
+ self.layout.prop(context.space_data, "show_annotation", text="")
@staticmethod
def draw(self, context):
layout = self.layout
+ layout.use_property_decorate = False
- # owner of Grease Pencil data
+ # Grease Pencil owner.
gpd_owner = context.gpencil_data_owner
gpd = context.gpencil_data
- # Owner Selector
- if context.space_data.type == 'VIEW_3D':
- layout.row().prop(context.tool_settings, "grease_pencil_source", expand=True)
- elif context.space_data.type == 'CLIP_EDITOR':
+ # Owner selector.
+ if context.space_data.type == 'CLIP_EDITOR':
layout.row().prop(context.space_data, "grease_pencil_source", expand=True)
- # Grease Pencil data selector
layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink")
- # Grease Pencil data...
- if (gpd is None) or (not gpd.layers):
- layout.operator("gpencil.layer_add", text="New Layer")
- else:
+ # List of layers/notes.
+ if gpd and gpd.layers:
self.draw_layers(context, layout, gpd)
def draw_layers(self, context, layout, gpd):
@@ -926,7 +686,7 @@ class GreasePencilDataPanel:
layer_rows = 5
else:
layer_rows = 2
- col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
+ col.template_list("GPENCIL_UL_annotation_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
col = row.column()
@@ -936,8 +696,6 @@ class GreasePencilDataPanel:
gpl = context.active_gpencil_layer
if gpl:
- sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
-
if len(gpd.layers) > 1:
col.separator()
@@ -945,211 +703,66 @@ class GreasePencilDataPanel:
sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
- col.separator()
-
- sub = col.column(align=True)
- sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
- sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
-
- if gpl:
- self.draw_layer(context, layout, gpl)
-
- def draw_layer(self, context, layout, gpl):
- row = layout.row(align=True)
- row.prop(gpl, "opacity", text="Opacity", slider=True)
-
- # Layer options
- split = layout.split(percentage=0.5)
- split.active = not gpl.lock
- split.prop(gpl, "show_x_ray")
- split.prop(gpl, "show_points")
-
- # Offsets + Parenting (where available)
- if context.space_data.type == 'VIEW_3D':
- split = layout.split(percentage=0.5)
+ tool_settings = context.tool_settings
+ if gpd and gpl:
+ layout.prop(gpl, "thickness")
else:
- split = layout.column() # parenting is not available in 2D editors...
- split.active = not gpl.lock
-
- # Offsets - Color Tint
- col = split.column()
- subcol = col.column(align=True)
- subcol.label("Tint")
- subcol.enabled = not gpl.lock
- subcol.prop(gpl, "tint_color", text="")
- subcol.prop(gpl, "tint_factor", text="Factor", slider=True)
-
- # Offsets - Thickness
- row = col.row(align=True)
- row.prop(gpl, "line_change", text="Thickness Change", slider=True)
- row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="")
-
- # Parenting
- if context.space_data.type == 'VIEW_3D':
- col = split.column(align=True)
- col.label(text="Parent:")
- col.prop(gpl, "parent", text="")
-
- sub = col.column()
- sub.prop(gpl, "parent_type", text="")
- parent = gpl.parent
- if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
- sub.prop_search(gpl, "parent_bone", parent.data, "bones", text="")
-
- layout.separator()
-
- # Full-Row - Frame Locking (and Delete Frame)
- row = layout.row(align=True)
- row.active = not gpl.lock
+ layout.prop(tool_settings, "annotation_thickness", text="Thickness")
- if gpl.active_frame:
- lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked")
- lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status)
- else:
- lock_label = iface_("Lock Frame")
- row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED')
- row.operator("gpencil.active_frame_delete", text="", icon='X')
-
- layout.separator()
-
- # Onion skinning
- col = layout.column(align=True)
- col.active = not gpl.lock
-
- row = col.row()
- row.prop(gpl, "use_onion_skinning")
- sub = row.row(align=True)
- icon = 'RESTRICT_RENDER_OFF' if gpl.use_ghosts_always else 'RESTRICT_RENDER_ON'
- sub.prop(gpl, "use_ghosts_always", text="", icon=icon)
- sub.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR')
-
- split = col.split(percentage=0.5)
- split.active = gpl.use_onion_skinning
-
- # - Before Frames
- sub = split.column(align=True)
- row = sub.row(align=True)
- row.active = gpl.use_ghost_custom_colors
- row.prop(gpl, "before_color", text="")
- sub.prop(gpl, "ghost_before_range", text="Before")
-
- # - After Frames
- sub = split.column(align=True)
- row = sub.row(align=True)
- row.active = gpl.use_ghost_custom_colors
- row.prop(gpl, "after_color", text="")
- sub.prop(gpl, "ghost_after_range", text="After")
-
-
-class GreasePencilPaletteColorPanel:
- # subclass must set
- bl_label = "Grease Pencil Colors"
- bl_region_type = 'UI'
+ if gpl:
+ # layout.prop(gpl, "opacity", text="Opacity", slider=True)
+ # Full-Row - Frame Locking (and Delete Frame)
+ row = layout.row(align=True)
+ row.active = not gpl.lock
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
+ if gpl.active_frame:
+ lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked")
+ lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status)
+ else:
+ lock_label = iface_("Lock Frame")
+ row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED')
+ row.operator("gpencil.active_frame_delete", text="", icon='X')
- if context.gpencil_data is None:
- return False
- gpd = context.gpencil_data
- return bool(gpd.layers.active)
+class GreasePencilOnionPanel:
@staticmethod
- def draw(self, context):
- layout = self.layout
- palette = context.active_gpencil_palette
-
- if palette:
- row = layout.row(align=True)
- row.operator_context = 'EXEC_REGION_WIN'
- row.operator_menu_enum("gpencil.palette_change", "palette", text="", icon='COLOR')
- row.prop(palette, "name", text="")
- row.operator("gpencil.palette_add", icon='ZOOMIN', text="")
- row.operator("gpencil.palette_remove", icon='X', text="")
-
- # Palette colors
- row = layout.row()
- col = row.column()
- if len(palette.colors) >= 2:
- color_rows = 5
- else:
- color_rows = 2
- col.template_list("GPENCIL_UL_palettecolor", "", palette, "colors", palette.colors, "active_index",
- rows=color_rows)
+ def draw_settings(layout, gp):
+ col = layout.column()
+ col.prop(gp, "onion_mode")
+ col.prop(gp, "onion_factor", text="Opacity", slider=True)
- col = row.column()
+ if gp.onion_mode in ('ABSOLUTE', 'RELATIVE'):
+ col = layout.column(align=True)
+ col.prop(gp, "ghost_before_range", text="Frames Before")
+ col.prop(gp, "ghost_after_range", text="After")
- sub = col.column(align=True)
- sub.operator("gpencil.palettecolor_add", icon='ZOOMIN', text="")
- sub.operator("gpencil.palettecolor_remove", icon='ZOOMOUT', text="")
+ layout.prop(gp, "use_ghost_custom_colors", text="Use Custom Colors")
- palcol = context.active_gpencil_palettecolor
- if palcol:
- sub.menu("GPENCIL_MT_palettecolor_specials", icon='DOWNARROW_HLT', text="")
+ if gp.use_ghost_custom_colors:
+ col = layout.column(align=True)
+ col.active = gp.use_ghost_custom_colors
+ col.prop(gp, "before_color", text="Color Before")
+ col.prop(gp, "after_color", text="After")
- if len(palette.colors) > 1:
- col.separator()
+ layout.prop(gp, "use_ghosts_always", text="View In Render")
- sub = col.column(align=True)
- sub.operator("gpencil.palettecolor_move", icon='TRIA_UP', text="").direction = 'UP'
- sub.operator("gpencil.palettecolor_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
-
- row = layout.row()
- sub = row.row(align=True)
- sub.label(text="Isolate:") # based on active color only
- sub.operator("gpencil.palettecolor_isolate", icon='LOCKED', text="").affect_visibility = False
- sub.operator("gpencil.palettecolor_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
- sub = row.row(align=True)
- sub.label(text="Lock:") # based on other stuff...
- sub.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="")
- sub.operator("gpencil.palette_lock_layer", icon='COLOR', text="")
-
- pcolor = palette.colors.active
- if pcolor:
- self.draw_palettecolors(layout, pcolor)
-
- # Draw palette colors
- def draw_palettecolors(self, layout, pcolor):
- # color settings
- split = layout.split(percentage=0.5)
- split.active = not pcolor.lock
-
- # Column 1 - Stroke
- col = split.column(align=True)
- col.enabled = not pcolor.lock
- col.label(text="Stroke:")
- col.prop(pcolor, "color", text="")
- col.prop(pcolor, "alpha", slider=True)
-
- # Column 2 - Fill
- col = split.column(align=True)
- col.enabled = not pcolor.lock
- col.label(text="Fill:")
- col.prop(pcolor, "fill_color", text="")
- col.prop(pcolor, "fill_alpha", text="Opacity", slider=True)
-
- # Options
- split = layout.split(percentage=0.5)
- split.active = not pcolor.lock
-
- col = split.column(align=True)
- col.active = not pcolor.lock
- col.prop(pcolor, "use_volumetric_strokes")
- col = split.column(align=True)
- col.active = not pcolor.lock
- col.prop(pcolor, "use_hq_fill")
+ col = layout.column(align=True)
+ col.active = gp.use_onion_skinning
+ col.prop(gp, "use_onion_fade", text="Fade")
+ if hasattr(gp, "use_onion_loop"): # XXX
+ sub = layout.column()
+ sub.active = gp.onion_mode in ('RELATIVE', 'SELECTED')
+ sub.prop(gp, "use_onion_loop", text="Loop")
class GreasePencilToolsPanel:
# For use in "2D" Editors without their own toolbar
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
- # bl_options = {'DEFAULT_CLOSED'}
bl_label = "Grease Pencil Settings"
bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@@ -1189,14 +802,14 @@ classes = (
GPENCIL_MT_pie_settings_palette,
GPENCIL_MT_pie_tools_more,
GPENCIL_MT_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,
+ GPENCIL_MT_separate,
+
+ GPENCIL_MT_gpencil_draw_specials,
+ GPENCIL_MT_gpencil_draw_delete,
+
+ GPENCIL_UL_annotation_layer,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index b601922e944..706ce497dee 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -73,7 +73,7 @@ class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "material"
_property_type = bpy.types.Material
@@ -82,12 +82,15 @@ class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_context = "material"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
- engine = context.engine
- return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
+ if context.active_object and context.active_object.type == 'GPENCIL':
+ return False
+ else:
+ engine = context.engine
+ return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -209,11 +212,7 @@ class EEVEE_MATERIAL_PT_options(MaterialButtonsPanel, Panel):
layout.prop(mat, "use_screen_refraction")
layout.prop(mat, "refraction_depth")
-
- layout.prop(mat, "use_screen_subsurface")
- row = layout.row()
- row.active = mat.use_screen_subsurface
- row.prop(mat, "use_sss_translucency")
+ layout.prop(mat, "use_sss_translucency")
class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py
new file mode 100644
index 00000000000..d83639a361c
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py
@@ -0,0 +1,321 @@
+# ##### 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 Menu, Panel, UIList
+from rna_prop_ui import PropertyPanel
+
+
+class GPENCIL_MT_color_specials(Menu):
+ bl_label = "Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.color_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
+ layout.operator("gpencil.color_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+
+ layout.separator()
+
+ layout.operator("gpencil.color_lock_all", icon='LOCKED', text="Lock All")
+ layout.operator("gpencil.color_unlock_all", icon='UNLOCKED', text="UnLock All")
+
+ layout.separator()
+
+ layout.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="Lock Unselected")
+ layout.operator("gpencil.lock_layer", icon='COLOR', text="Lock Unused")
+
+
+class GPENCIL_UL_matslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ slot = item
+ ma = slot.material
+ if (ma is not None) and (ma.grease_pencil is not None):
+ gpcolor = ma.grease_pencil
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpcolor.lock:
+ layout.active = False
+
+ row = layout.row(align=True)
+ row.enabled = not gpcolor.lock
+ row.prop(ma, "name", text="", emboss=False, icon_value=icon)
+
+ row = layout.row(align=True)
+ row.prop(gpcolor, "lock", text="", emboss=False)
+ row.prop(gpcolor, "hide", text="", emboss=False)
+ if gpcolor.ghost is True:
+ icon = 'GHOST_DISABLED'
+ else:
+ icon = 'GHOST_ENABLED'
+ row.prop(gpcolor, "ghost", text="", icon=icon, emboss=False)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GPMaterialButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "material"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'GPENCIL' and
+ ob.active_material and
+ ob.active_material.grease_pencil)
+
+
+class MATERIAL_PT_gpencil_slots(Panel):
+ bl_label = "Grease Pencil Material Slots"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "material"
+ bl_options = {'HIDE_HEADER'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ gpd = context.gpencil_data
+
+ mat = context.object.active_material
+ ob = context.object
+ slot = context.material_slot
+ space = context.space_data
+
+ if ob:
+ is_sortable = len(ob.material_slots) > 1
+ rows = 1
+ if (is_sortable):
+ rows = 4
+
+ row = layout.row()
+
+ row.template_list("GPENCIL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.material_slot_add", icon='ZOOMIN', text="")
+ col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
+
+ col.menu("GPENCIL_MT_color_specials", icon='DOWNARROW_HLT', text="")
+
+ if is_sortable:
+ col.separator()
+
+ col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False
+ sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
+
+ row = layout.row()
+
+ if ob:
+ row.template_ID(ob, "active_material", new="material.new", live_icon=True)
+
+ if slot:
+ icon_link = 'MESH_DATA' if slot.link == 'DATA' else 'OBJECT_DATA'
+ row.prop(slot, "link", icon=icon_link, icon_only=True)
+
+ if gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.operator("gpencil.stroke_change_color", text="Assign")
+ row.operator("gpencil.color_select", text="Select")
+
+ elif mat:
+ row.template_ID(space, "pin_id")
+
+
+# Used as parent for "Stroke" and "Fill" panels
+class MATERIAL_PT_gpencil_surface(GPMaterialButtonsPanel, Panel):
+ bl_label = "Surface"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ma = context.object.active_material
+ if ma is None or ma.grease_pencil is None:
+ return False
+
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+
+class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
+ bl_label = "Stroke"
+ bl_parent_id = 'MATERIAL_PT_gpencil_surface'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil is not None:
+ gpcolor = ma.grease_pencil
+
+ col = layout.column()
+ col.active = not gpcolor.lock
+
+ col.prop(gpcolor, "mode")
+
+ col.prop(gpcolor, "stroke_style", text="Style")
+
+ if gpcolor.stroke_style == 'TEXTURE':
+ row = col.row()
+ row.enabled = not gpcolor.lock
+ col = row.column(align=True)
+ col.template_ID(gpcolor, "stroke_image", open="image.open")
+ col.prop(gpcolor, "pixel_size", text="UV Factor")
+ col.prop(gpcolor, "use_stroke_pattern", text="Use As Pattern")
+
+ if gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern is True:
+ col.prop(gpcolor, "color", text="Color")
+
+
+class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel):
+ bl_label = "Fill"
+ bl_parent_id = 'MATERIAL_PT_gpencil_surface'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil:
+ gpcolor = ma.grease_pencil
+
+ # color settings
+ col = layout.column()
+ col.active = not gpcolor.lock
+ col.prop(gpcolor, "fill_style", text="Style")
+
+ if gpcolor.fill_style == 'GRADIENT':
+ col.prop(gpcolor, "gradient_type")
+
+ if gpcolor.fill_style != 'TEXTURE':
+ col.prop(gpcolor, "fill_color", text="Color")
+
+ if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
+ col.prop(gpcolor, "mix_color", text="Secondary Color")
+
+ if gpcolor.fill_style == 'GRADIENT':
+ col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
+
+ if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
+ col.prop(gpcolor, "flip", text="Flip Colors")
+
+ col.prop(gpcolor, "pattern_shift", text="Location")
+ col.prop(gpcolor, "pattern_scale", text="Scale")
+
+ if gpcolor.gradient_type == 'RADIAL' and gpcolor.fill_style not in ('SOLID', 'CHESSBOARD'):
+ col.prop(gpcolor, "pattern_radius", text="Radius")
+ else:
+ if gpcolor.fill_style != 'SOLID':
+ col.prop(gpcolor, "pattern_angle", text="Angle")
+
+ if gpcolor.fill_style == 'CHESSBOARD':
+ col.prop(gpcolor, "pattern_gridsize", text="Box Size")
+
+ # Texture
+ if gpcolor.fill_style == 'TEXTURE' or (gpcolor.texture_mix is True and gpcolor.fill_style == 'SOLID'):
+ col.template_ID(gpcolor, "fill_image", open="image.open")
+
+ if gpcolor.fill_style == 'TEXTURE':
+ col.prop(gpcolor, "use_fill_pattern", text="Use As Pattern")
+ if gpcolor.use_fill_pattern is True:
+ col.prop(gpcolor, "fill_color", text="Color")
+
+ col.prop(gpcolor, "texture_offset", text="Offset")
+ col.prop(gpcolor, "texture_scale", text="Scale")
+ col.prop(gpcolor, "texture_angle")
+ col.prop(gpcolor, "texture_opacity")
+ col.prop(gpcolor, "texture_clamp", text="Clip Image")
+
+ if gpcolor.use_fill_pattern is False:
+ col.prop(gpcolor, "texture_mix", text="Mix With Color")
+
+ if gpcolor.texture_mix is True:
+ col.prop(gpcolor, "fill_color", text="Mix Color")
+ col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
+
+
+class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ ma = context.object.active_material
+ self.layout.label(ma.name)
+ self.layout.template_preview(ma)
+
+
+class MATERIAL_PT_gpencil_custom_props(GPMaterialButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ _context_path = "object.active_material"
+ _property_type = bpy.types.Material
+
+
+class MATERIAL_PT_gpencil_options(GPMaterialButtonsPanel, Panel):
+ bl_label = "Options"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil is not None:
+ gpcolor = ma.grease_pencil
+ layout.prop(gpcolor, "pass_index")
+
+
+classes = (
+ GPENCIL_UL_matslots,
+ GPENCIL_MT_color_specials,
+ MATERIAL_PT_gpencil_slots,
+ MATERIAL_PT_gpencil_preview,
+ MATERIAL_PT_gpencil_surface,
+ MATERIAL_PT_gpencil_strokecolor,
+ MATERIAL_PT_gpencil_fillcolor,
+ MATERIAL_PT_gpencil_options,
+ MATERIAL_PT_gpencil_custom_props,
+)
+
+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_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 63b708ae059..79b2f7b8df8 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -329,6 +329,7 @@ from .properties_animviz import (
class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
#bl_label = "Object Motion Paths"
bl_context = "object"
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@@ -359,7 +360,7 @@ class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit fr
class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "object"
_property_type = bpy.types.Object
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 05538e71faf..393c9784be8 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -67,7 +67,7 @@ def particle_get_settings(context):
class PARTICLE_MT_specials(Menu):
bl_label = "Particle Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -88,7 +88,7 @@ class PARTICLE_PT_hair_dynamics_presets(PresetMenu):
preset_subdir = "hair_dynamics"
preset_operator = "script.execute_preset"
preset_add_operator = "particle.hair_dynamics_preset_add"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
class ParticleButtonsPanel:
@@ -132,7 +132,7 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList):
class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -235,7 +235,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -287,7 +287,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
bl_label = "Source"
bl_parent_id = "PARTICLE_PT_emission"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -325,7 +325,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
bl_label = "Hair Dynamics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -406,7 +406,7 @@ class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
bl_label = "Structure"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -438,7 +438,7 @@ class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
bl_label = "Volume"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -470,7 +470,7 @@ class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
bl_label = "Cache"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -501,7 +501,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
bl_label = "Velocity"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -550,7 +550,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
bl_label = "Rotation"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -603,7 +603,7 @@ class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel):
bl_label = "Angular Velocity"
bl_parent_id = "PARTICLE_PT_rotation"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -628,7 +628,7 @@ class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel):
class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
bl_label = "Physics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -662,171 +662,343 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
if part.physics_type == 'FLUID':
fluid = part.fluid
- col.label(text="Fluid")
+ col.separator()
col.prop(fluid, "solver")
col.prop(fluid, "stiffness", text="Stiffness")
col.prop(fluid, "linear_viscosity", text="Viscosity")
col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
- col.label(text="Advanced")
+ elif part.physics_type == 'KEYED':
+
+ sub = col.column()
+ sub.active = not psys.use_keyed_timing
+ sub.prop(part, "keyed_loops", text="Loops")
+ if psys:
+ col.prop(psys, "use_keyed_timing", text="Use Timing")
+
+ col.label(text="Keys")
+
+
+class PARTICLE_PT_physics_fluid_advanced(ParticleButtonsPanel, Panel):
+ bl_label = "Advanced"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- if fluid.solver == 'DDR':
- sub = col.column()
- sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
- sub.prop(fluid, "factor_repulsion")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ fluid = part.fluid
+ if part.physics_type == 'FLUID':
+ return True
+ else:
+ return False
- sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
- sub.prop(fluid, "factor_stiff_viscosity")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ fluid = part.fluid
+
+ col = layout.column()
+
+ if fluid.solver == 'DDR':
sub = col.column()
- sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
- sub.prop(fluid, "factor_radius")
+ sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
+ sub.prop(fluid, "factor_repulsion")
- sub.prop(fluid, "rest_density", slider=fluid.use_factor_density)
- sub.prop(fluid, "use_factor_density")
+ sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
+ sub.prop(fluid, "factor_stiff_viscosity")
- if fluid.solver == 'CLASSICAL':
- # With the classical solver, it is possible to calculate the
- # spacing between particles when the fluid is at rest. This
- # makes it easier to set stable initial conditions.
- particle_volume = part.mass / fluid.rest_density
- spacing = pow(particle_volume, 1.0 / 3.0)
+ sub = col.column()
+ sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
+ sub.prop(fluid, "factor_radius")
- sub.label(text="Spacing: %g" % spacing)
+ sub.prop(fluid, "rest_density", slider=fluid.use_factor_density)
+ sub.prop(fluid, "use_factor_density")
- elif fluid.solver == 'DDR':
+ if fluid.solver == 'CLASSICAL':
+ # With the classical solver, it is possible to calculate the
+ # spacing between particles when the fluid is at rest. This
+ # makes it easier to set stable initial conditions.
+ particle_volume = part.mass / fluid.rest_density
+ spacing = pow(particle_volume, 1.0 / 3.0)
- col.label(text="Springs")
- col.prop(fluid, "spring_force", text="Force")
- col.prop(fluid, "use_viscoelastic_springs")
+ sub.label(text="Spacing: %g" % spacing)
- sub = col.column()
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "yield_ratio", slider=True)
- sub.prop(fluid, "plasticity", slider=True)
- col.label(text="Advanced")
- sub = col.column()
- sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
- sub.prop(fluid, "factor_rest_length", text="")
+class PARTICLE_PT_physics_fluid_springs(ParticleButtonsPanel, Panel):
+ bl_label = "Springs"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- sub = col.column()
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "use_initial_rest_length")
- sub.prop(fluid, "spring_frames", text="Frames")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ fluid = part.fluid
+ if part.physics_type == 'FLUID' and fluid.solver == 'DDR':
+ return True
+ else:
+ return False
- elif part.physics_type == 'KEYED':
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- sub = col.column()
- sub.active = not psys.use_keyed_timing
- sub.prop(part, "keyed_loops", text="Loops")
- if psys:
- col.prop(psys, "use_keyed_timing", text="Use Timing")
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ fluid = part.fluid
- col.label(text="Keys")
+ col = layout.column()
- elif part.physics_type == 'BOIDS':
- boids = part.boids
+ col.prop(fluid, "spring_force", text="Force")
- row = layout.row()
- row.prop(boids, "use_flight")
- row.prop(boids, "use_land")
- row.prop(boids, "use_climb")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.active = boids.use_flight
- col.prop(boids, "air_speed_max")
- col.prop(boids, "air_speed_min", slider=True)
- col.prop(boids, "air_acc_max", slider=True)
- col.prop(boids, "air_ave_max", slider=True)
- col.prop(boids, "air_personal_space")
- row = col.row(align=True)
- row.active = (boids.use_land or boids.use_climb) and boids.use_flight
- row.prop(boids, "land_smooth")
-
- col = split.column(align=True)
- col.active = boids.use_land or boids.use_climb
- col.prop(boids, "land_speed_max")
- col.prop(boids, "land_jump_speed")
- col.prop(boids, "land_acc_max", slider=True)
- col.prop(boids, "land_ave_max", slider=True)
- col.prop(boids, "land_personal_space")
- col.prop(boids, "land_stick_force")
-
- layout.prop(part, "collision_group")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.label(text="Battle:")
- col.prop(boids, "health")
- col.prop(boids, "strength")
- col.prop(boids, "aggression")
- col.prop(boids, "accuracy")
- col.prop(boids, "range")
- col = split.column()
- col.label(text="Misc:")
- col.prop(boids, "bank", slider=True)
- col.prop(boids, "pitch", slider=True)
- col.prop(boids, "height", slider=True)
-
- if psys and part.physics_type in {'KEYED', 'BOIDS', 'FLUID'}:
- if part.physics_type == 'BOIDS':
- layout.label(text="Relations:")
- elif part.physics_type == 'FLUID':
- layout.label(text="Fluid Interaction:")
+class PARTICLE_PT_physics_fluid_springs_viscoelastic(ParticleButtonsPanel, Panel):
+ bl_label = "Viscoelastic Springs"
+ bl_parent_id = "PARTICLE_PT_physics_fluid_springs"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- row = layout.row()
- row.template_list("UI_UL_list", "particle_targets", psys, "targets",
- psys, "active_particle_target_index", rows=4)
-
- col = row.column()
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.new_target", icon='ZOOMIN', text="")
- subsub.operator("particle.target_remove", icon='ZOOMOUT', text="")
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.target_move_up", icon='TRIA_UP', text="")
- subsub.operator("particle.target_move_down", icon='TRIA_DOWN', text="")
-
- key = psys.active_particle_target
- if key:
- row = layout.row()
- if part.physics_type == 'KEYED':
- col = row.column()
- # doesn't work yet
- #col.alert = key.valid
- col.prop(key, "object", text="")
- col.prop(key, "system", text="System")
- col = row.column()
- col.active = psys.use_keyed_timing
- col.prop(key, "time")
- col.prop(key, "duration")
- elif part.physics_type == 'BOIDS':
- sub = row.row()
- # doesn't work yet
- #sub.alert = key.valid
- sub.prop(key, "object", text="")
- sub.prop(key, "system", text="System")
-
- layout.row().prop(key, "alliance", expand=True)
- elif part.physics_type == 'FLUID':
- sub = row.row()
- # doesn't work yet
- #sub.alert = key.valid
- sub.prop(key, "object", text="")
- sub.prop(key, "system", text="System")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ fluid = part.fluid
+ if part.physics_type == 'FLUID' and fluid.solver == 'DDR':
+ return True
+ else:
+ return False
+
+ def draw_header(self, context):
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ fluid = part.fluid
+
+ self.layout.prop(fluid, "use_viscoelastic_springs", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ fluid = part.fluid
+
+ col = layout.column()
+ col.active = fluid.use_viscoelastic_springs
+ col.prop(fluid, "yield_ratio", slider=True)
+ col.prop(fluid, "plasticity", slider=True)
+
+ col.separator()
+
+ col.prop(fluid, "use_initial_rest_length")
+ col.prop(fluid, "spring_frames", text="Frames")
+
+
+class PARTICLE_PT_physics_fluid_springs_advanced(ParticleButtonsPanel, Panel):
+ bl_label = "Advanced"
+ bl_parent_id = "PARTICLE_PT_physics_fluid_springs"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ fluid = part.fluid
+ if part.physics_type == 'FLUID' and fluid.solver == 'DDR':
+ return True
+ else:
+ return False
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ fluid = part.fluid
+
+ sub = layout.column()
+ sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
+ sub.prop(fluid, "factor_rest_length")
+
+
+class PARTICLE_PT_physics_boids_movement(ParticleButtonsPanel, Panel):
+ bl_label = "Movement"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type in {'BOIDS'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ boids = part.boids
+
+ col = layout.column()
+
+ col.prop(boids, "use_flight")
+ col.prop(boids, "use_land")
+ col.prop(boids, "use_climb")
+
+ col = layout.column()
+
+ col.active = boids.use_flight
+ sub = col.column()
+ sub.prop(boids, "air_speed_max")
+ sub.prop(boids, "air_speed_min", slider=True)
+ col.prop(boids, "air_acc_max", slider=True)
+ col.prop(boids, "air_ave_max", slider=True)
+ col.prop(boids, "air_personal_space")
+ row = col.row(align=True)
+ row.active = (boids.use_land or boids.use_climb) and boids.use_flight
+ row.prop(boids, "land_smooth")
+
+ layout.separator()
+
+ col = layout.column()
+ col.active = boids.use_land or boids.use_climb
+ col.prop(boids, "land_speed_max")
+ col.prop(boids, "land_jump_speed")
+ col.prop(boids, "land_acc_max", slider=True)
+ col.prop(boids, "land_ave_max", slider=True)
+ col.prop(boids, "land_personal_space")
+ col.prop(boids, "land_stick_force")
+
+ layout.separator()
+
+ layout.prop(part, "collision_group")
+
+
+class PARTICLE_PT_physics_boids_battle(ParticleButtonsPanel, Panel):
+ bl_label = "Battle"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type in {'BOIDS'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ boids = part.boids
+
+ col = layout.column()
+
+ col.prop(boids, "health")
+ col.prop(boids, "strength")
+ col.prop(boids, "aggression")
+ col.prop(boids, "accuracy")
+ col.prop(boids, "range")
+
+
+class PARTICLE_PT_physics_boids_misc(ParticleButtonsPanel, Panel):
+ bl_label = "Misc"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type in {'BOIDS'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+ boids = part.boids
+
+ col = layout.column()
+
+ col.prop(boids, "bank", slider=True)
+ col.prop(boids, "pitch", slider=True)
+ col.prop(boids, "height", slider=True)
+
+
+class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
+ bl_label = "Relations"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type in {'KEYED', 'BOIDS', 'FLUID'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ row = layout.row()
+ row.template_list("UI_UL_list", "particle_targets", psys, "targets",
+ psys, "active_particle_target_index", rows=4)
+
+ col = row.column()
+ sub = col.row()
+ subsub = sub.column(align=True)
+ subsub.operator("particle.new_target", icon='ZOOMIN', text="")
+ subsub.operator("particle.target_remove", icon='ZOOMOUT', text="")
+ sub = col.row()
+ subsub = sub.column(align=True)
+ subsub.operator("particle.target_move_up", icon='TRIA_UP', text="")
+ subsub.operator("particle.target_move_down", icon='TRIA_DOWN', text="")
+
+ key = psys.active_particle_target
+
+ if key:
+ if part.physics_type == 'KEYED':
+ col = layout.column()
+ # doesn't work yet
+ #col.alert = key.valid
+ col.prop(key, "object")
+ col.prop(key, "system", text="System")
+
+ col.active = psys.use_keyed_timing
+ col.prop(key, "time")
+ col.prop(key, "duration")
+ elif part.physics_type == 'BOIDS':
+ sub = layout.column()
+ # doesn't work yet
+ #sub.alert = key.valid
+ sub.prop(key, "object")
+ sub.prop(key, "system", text="System")
+ layout.prop(key, "alliance")
+ elif part.physics_type == 'FLUID':
+ sub = layout.column()
+ # doesn't work yet
+ #sub.alert = key.valid
+ sub.prop(key, "object")
+ sub.prop(key, "system", text="System")
class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel):
bl_label = "Deflection"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -852,7 +1024,7 @@ class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel):
class PARTICLE_PT_physics_forces(ParticleButtonsPanel, Panel):
bl_label = "Forces"
bl_parent_id = "PARTICLE_PT_physics"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -879,7 +1051,7 @@ class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel):
bl_label = "Integration"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_physics"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -911,7 +1083,10 @@ class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel):
class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
bl_label = "Boid Brain"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "PARTICLE_PT_physics"
+
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1015,7 +1190,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
bl_label = "Render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1055,7 +1230,7 @@ class PARTICLE_PT_render_extra(ParticleButtonsPanel, Panel):
bl_label = "Extra"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1082,7 +1257,7 @@ class PARTICLE_PT_render_line(ParticleButtonsPanel, Panel):
bl_label = "Line"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1110,7 +1285,7 @@ class PARTICLE_PT_render_path(ParticleButtonsPanel, Panel):
bl_label = "Path"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1145,7 +1320,7 @@ class PARTICLE_PT_render_path_timing(ParticleButtonsPanel, Panel):
bl_label = "Timing"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1177,7 +1352,7 @@ class PARTICLE_PT_render_object(ParticleButtonsPanel, Panel):
bl_label = "Object"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1205,7 +1380,7 @@ class PARTICLE_PT_render_collection(ParticleButtonsPanel, Panel):
bl_label = "Collection"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1237,7 +1412,7 @@ class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel):
bl_label = "Use Count"
bl_parent_id = "PARTICLE_PT_render_collection"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1288,7 +1463,7 @@ class PARTICLE_PT_render_billboards_alignment(ParticleButtonsPanel, Panel):
bl_label = "Billboard Alignment"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1314,7 +1489,7 @@ class PARTICLE_PT_render_billboards_tilt(ParticleButtonsPanel, Panel):
bl_label = "Billboard Tilt"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1348,7 +1523,7 @@ class PARTICLE_PT_render_billboards_uv(ParticleButtonsPanel, Panel):
bl_label = "Billboard UVs"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1384,7 +1559,7 @@ class PARTICLE_PT_render_trails(ParticleButtonsPanel, Panel):
bl_label = "Trails"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1412,7 +1587,7 @@ class PARTICLE_PT_render_trails(ParticleButtonsPanel, Panel):
class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1474,7 +1649,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
bl_label = "Children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1530,7 +1705,7 @@ class PARTICLE_PT_children_parting(ParticleButtonsPanel, Panel):
bl_label = "Parting"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1555,7 +1730,7 @@ class PARTICLE_PT_children_clumping(ParticleButtonsPanel, Panel):
bl_label = "Clumping"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1597,7 +1772,7 @@ class PARTICLE_PT_children_roughness(ParticleButtonsPanel, Panel):
bl_label = "Roughness"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1639,7 +1814,7 @@ class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel):
bl_label = "Kink"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1690,7 +1865,7 @@ class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel):
class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
bl_label = "Field Weights"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1711,7 +1886,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
bl_label = "Force Field Settings"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -1727,7 +1902,7 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields_type1(ParticleButtonsPanel, Panel):
bl_label = "Type 1"
bl_parent_id = "PARTICLE_PT_force_fields"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -1743,7 +1918,7 @@ class PARTICLE_PT_force_fields_type1(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields_type2(ParticleButtonsPanel, Panel):
bl_label = "Type 2"
bl_parent_id = "PARTICLE_PT_force_fields"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -1760,7 +1935,7 @@ class PARTICLE_PT_force_fields_type1_falloff(ParticleButtonsPanel, Panel):
bl_label = "Falloff"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_force_fields_type1"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -1775,7 +1950,7 @@ class PARTICLE_PT_force_fields_type2_falloff(ParticleButtonsPanel, Panel):
bl_label = "Falloff"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_force_fields_type2"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -1789,7 +1964,7 @@ class PARTICLE_PT_force_fields_type2_falloff(ParticleButtonsPanel, Panel):
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
bl_label = "Vertex Groups"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1862,7 +2037,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
class PARTICLE_PT_textures(ParticleButtonsPanel, Panel):
bl_label = "Textures"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1894,7 +2069,7 @@ class PARTICLE_PT_textures(ParticleButtonsPanel, Panel):
class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel):
bl_label = "Hair Shape"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -1921,7 +2096,7 @@ class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel):
class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings
@@ -1941,9 +2116,17 @@ classes = (
PARTICLE_PT_rotation,
PARTICLE_PT_rotation_angular_velocity,
PARTICLE_PT_physics,
+ PARTICLE_PT_physics_fluid_springs,
+ PARTICLE_PT_physics_fluid_springs_viscoelastic,
+ PARTICLE_PT_physics_fluid_springs_advanced,
+ PARTICLE_PT_physics_fluid_advanced,
+ PARTICLE_PT_physics_boids_movement,
+ PARTICLE_PT_physics_boids_battle,
+ PARTICLE_PT_physics_boids_misc,
PARTICLE_PT_physics_forces,
PARTICLE_PT_physics_deflection,
PARTICLE_PT_physics_integration,
+ PARTICLE_PT_physics_relations,
PARTICLE_PT_boidbrain,
PARTICLE_PT_render,
PARTICLE_PT_render_line,
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 2f659af3891..0a7318864a3 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -17,8 +17,11 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
+
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import (
+ Panel,
+)
from bl_operators.presets import PresetMenu
from .properties_physics_common import (
@@ -51,13 +54,14 @@ class PhysicButtonsPanel:
class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
bl_label = "Cloth"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header_preset(self, context):
CLOTH_PT_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
md = context.cloth
ob = context.object
@@ -65,71 +69,89 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
layout.active = cloth_panel_enabled(md)
- split = layout.split(percentage=0.25)
-
- split.label(text="Quality:")
- split.prop(cloth, "quality", text="Steps")
-
- split = layout.split(percentage=0.25)
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
- split.label(text="Speed:")
- split.prop(cloth, "time_scale", text="Multiplier")
+ col = flow.column()
+ col.prop(cloth, "quality", text="Quality Steps")
+ col.prop(cloth, "time_scale", text="Speed Multiplier")
- split = layout.split()
+ col.separator()
- col = split.column()
-
- col.label(text="Material:")
- col.prop(cloth, "mass")
+ col = flow.column()
+ col.prop(cloth, "mass", text="Material Mass")
col.prop(cloth, "structural_stiffness", text="Structural")
col.prop(cloth, "bending_stiffness", text="Bending")
- col = split.column()
+ col.separator()
- col.label(text="Damping:")
- col.prop(cloth, "spring_damping", text="Spring")
+ col = flow.column()
+ col.prop(cloth, "spring_damping", text="Damping Spring")
col.prop(cloth, "air_damping", text="Air")
col.prop(cloth, "vel_damping", text="Velocity")
- split = layout.split()
+ col = flow.column()
+ col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
- col = split.column()
+ key = ob.data.shape_keys
- col.prop(cloth, "use_pin_cloth", text="Pinning:")
- sub = col.column()
- sub.active = cloth.use_pin_cloth
- sub.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="")
- sub.prop(cloth, "pin_stiffness", text="Stiffness")
+ if key:
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.active = not cloth.use_dynamic_mesh
+ row.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="Rest Shape Key")
+ row.label(text="", icon='BLANK1')
- # Disabled for now
- """
- if cloth.vertex_group_mass:
- layout.label(text="Goal:")
- col = layout.column_flow()
- col.prop(cloth, "goal_default", text="Default")
- col.prop(cloth, "goal_spring", text="Stiffness")
- col.prop(cloth, "goal_friction", text="Friction")
- """
+class PHYSICS_PT_cloth_pinning(PhysicButtonsPanel, Panel):
+ bl_label = "Pinning"
+ bl_parent_id = 'PHYSICS_PT_cloth'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- col = split.column()
+ def draw_header(self, context):
+ md = context.cloth
+ cloth = md.settings
- col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
+ self.layout.active = cloth_panel_enabled(md) and cloth.use_pin_cloth
+ self.layout.prop(cloth, "use_pin_cloth", text="")
- key = ob.data.shape_keys
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- if key:
- sub = col.column()
- sub.active = not cloth.use_dynamic_mesh
- sub.label(text="Rest Shape Key:")
- sub.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="")
+ md = context.cloth
+ ob = context.object
+ cloth = md.settings
+
+ layout.active = cloth_panel_enabled(md) and cloth.use_pin_cloth
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+
+ col = flow.column()
+
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="Mass Group")
+ row.label(text="", icon='BLANK1')
+
+ col = flow.column()
+ col.prop(cloth, "pin_stiffness", text="Stiffness")
+
+ # Disabled for now.
+ """
+ if cloth.vertex_group_mass:
+ col = flow.column()
+ col.prop(cloth, "goal_default", text="Goal Default")
+ col.prop(cloth, "goal_spring", text="Stiffness")
+ col.prop(cloth, "goal_friction", text="Friction")
+ """
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
md = context.cloth
@@ -140,7 +162,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
bl_label = "Collision"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
cloth = context.cloth.collision_settings
@@ -150,38 +172,66 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
cloth = context.cloth.collision_settings
md = context.cloth
- ob = context.object
layout.active = cloth.use_collision and cloth_panel_enabled(md)
- split = layout.split()
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
- col = split.column()
+ col = flow.column()
col.prop(cloth, "collision_quality", text="Quality")
col.prop(cloth, "distance_min", slider=True, text="Distance")
col.prop(cloth, "repel_force", slider=True, text="Repel")
+
+ col = flow.column()
col.prop(cloth, "distance_repel", slider=True, text="Repel Distance")
col.prop(cloth, "friction")
+ col.prop(cloth, "group")
+
+
+class PHYSICS_PT_cloth_self_collision(PhysicButtonsPanel, Panel):
+ bl_label = "Self Collision"
+ bl_parent_id = 'PHYSICS_PT_cloth_collision'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
- col = split.column()
- col.prop(cloth, "use_self_collision", text="Self Collision")
- sub = col.column()
- sub.active = cloth.use_self_collision
- sub.prop(cloth, "self_collision_quality", text="Quality")
- sub.prop(cloth, "self_distance_min", slider=True, text="Distance")
- sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="")
+ def draw_header(self, context):
+ cloth = context.cloth.collision_settings
+
+ self.layout.active = cloth_panel_enabled(context.cloth) and cloth.use_self_collision
+ self.layout.prop(cloth, "use_self_collision", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ cloth = context.cloth.collision_settings
+ md = context.cloth
+ ob = context.object
+
+ layout.active = cloth.use_collision and cloth_panel_enabled(md) and cloth.use_self_collision
- layout.prop(cloth, "group")
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+
+ col = flow.column()
+ col.prop(cloth, "self_collision_quality", text="Quality")
+ col.prop(cloth, "self_distance_min", slider=True, text="Distance")
+
+ col = flow.column()
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="Vertex Group")
+ row.label(text="", icon='BLANK1')
class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
bl_label = "Stiffness Scaling"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -191,6 +241,7 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
md = context.cloth
ob = context.object
@@ -198,16 +249,27 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
layout.active = (cloth.use_stiffness_scale and cloth_panel_enabled(md))
- split = layout.split()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- col = split.column()
- col.label(text="Structural Stiffness:")
- col.prop_search(cloth, "vertex_group_structural_stiffness", ob, "vertex_groups", text="")
+ col = flow.column()
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.prop_search(
+ cloth, "vertex_group_structural_stiffness", ob, "vertex_groups",
+ text="Structural Group"
+ )
+ row.label(text="", icon='BLANK1')
col.prop(cloth, "structural_stiffness_max", text="Max")
- col = split.column()
- col.label(text="Bending Stiffness:")
- col.prop_search(cloth, "vertex_group_bending", ob, "vertex_groups", text="")
+ col.separator()
+
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop_search(
+ cloth, "vertex_group_bending", ob, "vertex_groups",
+ text="Bending Group"
+ )
+ row.label(text="", icon='BLANK1')
col.prop(cloth, "bending_stiffness_max", text="Max")
@@ -215,7 +277,7 @@ class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel):
bl_label = "Sewing Springs"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -225,23 +287,27 @@ class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
md = context.cloth
ob = context.object
cloth = context.cloth.settings
layout.active = (cloth.use_sewing_springs and cloth_panel_enabled(md))
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- layout.prop(cloth, "sewing_force_max", text="Sewing Force")
+ col = flow.column()
+ col.prop(cloth, "sewing_force_max", text="Sewing Force")
- split = layout.split()
+ col.separator()
- col = split.column(align=True)
- col.label(text="Shrinking:")
- col.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="")
+ col = col.column()
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.prop_search(cloth, "vertex_group_shrink", ob, "vertex_groups", text="Shrinking Group")
+ row.label(text="", icon='BLANK1')
- col = split.column(align=True)
- col.label()
+ col = flow.column(align=True)
col.prop(cloth, "shrink_min", text="Min")
col.prop(cloth, "shrink_max", text="Max")
@@ -250,7 +316,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
cloth = context.cloth.settings
@@ -262,6 +328,8 @@ classes = (
PHYSICS_PT_cloth,
PHYSICS_PT_cloth_cache,
PHYSICS_PT_cloth_collision,
+ PHYSICS_PT_cloth_self_collision,
+ PHYSICS_PT_cloth_pinning,
PHYSICS_PT_cloth_stiffness,
PHYSICS_PT_cloth_sewing,
PHYSICS_PT_cloth_field_weights,
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index e071de0108b..2da84ad84da 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -56,7 +56,7 @@ def physics_add_special(self, layout, data, name, addop, removeop, typeicon):
class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
obj = context.object
@@ -97,7 +97,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
'CONSTRAINT') # RB_TODO needs better icon
-# cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc
+# cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc.
def point_cache_ui(self, context, cache, enabled, cachetype):
layout = self.layout
@@ -112,8 +112,8 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
col.operator("ptcache.add", icon='ZOOMIN', text="")
col.operator("ptcache.remove", icon='ZOOMOUT', text="")
- row = layout.row()
if cachetype in {'PSYS', 'HAIR', 'SMOKE'}:
+ row = layout.row()
row.prop(cache, "use_external")
if cachetype == 'SMOKE':
@@ -131,7 +131,9 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
cache_info = cache.info
if cache_info:
- layout.label(text=cache_info)
+ col = layout.column()
+ col.alignment = 'RIGHT'
+ col.label(text=cache_info)
else:
if cachetype in {'SMOKE', 'DYNAMIC_PAINT'}:
if not bpy.data.is_saved:
@@ -147,45 +149,54 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
col.enabled = enabled
col.prop(cache, "frame_start", text="Simulation Start")
col.prop(cache, "frame_end")
+
if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
col.prop(cache, "frame_step")
- if cachetype != 'SMOKE':
- layout.label(text=cache.info)
+ cache_info = cache.info
+ if cachetype != 'SMOKE' and cache_info: # avoid empty space.
+ col = layout.column(align=True)
+ col.alignment = 'RIGHT'
+ col.label(text=cache_info)
can_bake = True
if cachetype not in {'SMOKE', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
- split = layout.split()
- split.enabled = enabled and bpy.data.is_saved
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+ flow.enabled = enabled and bpy.data.is_saved
- col = split.column()
- col.prop(cache, "use_disk_cache")
+ flow.use_property_split = True
- col = split.column()
- col.active = cache.use_disk_cache
- col.prop(cache, "use_library_path", "Use Lib Path")
+ # NOTE: TODO temporarly used until the animate properties are properly skipped.
+ flow.use_property_decorate = False # No animation (remove this later on)
- row = layout.row()
- row.enabled = enabled and bpy.data.is_saved
- row.active = cache.use_disk_cache
- row.label(text="Compression:")
- row.prop(cache, "compression", expand=True)
+ col = flow.column()
+ col.prop(cache, "use_disk_cache")
- layout.separator()
+ subcol = col.column()
+ subcol.active = cache.use_disk_cache
+ subcol.prop(cache, "use_library_path", "Use Lib Path")
+
+ col = flow.column()
+ col.enabled = enabled and bpy.data.is_saved
+ col.active = cache.use_disk_cache
+ col.prop(cache, "compression", text="Compression", expand=True)
if cache.id_data.library and not cache.use_disk_cache:
can_bake = False
col = layout.column(align=True)
- col.label(text="Linked object baking requires Disk Cache to be enabled", icon='INFO')
+ col.alignment = 'RIGHT'
+
+ col.separator()
+
+ col.label(text="Linked object baking requires Disk Cache to be enabled")
else:
layout.separator()
- split = layout.split()
- split.active = can_bake
-
- col = split.column()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ col = flow.column()
+ col.active = can_bake
if cache.is_baked is True:
col.operator("ptcache.free_bake", text="Free Bake")
@@ -200,7 +211,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
sub.enabled = enabled
sub.operator("ptcache.bake_from_cache", text="Current Cache to Bake")
- col = split.column()
+ col = flow.column()
col.operator("ptcache.bake_all", text="Bake All Dynamics").bake = True
col.operator("ptcache.free_bake_all", text="Free All Bakes")
col.operator("ptcache.bake_all", text="Update All To Frame").bake = False
@@ -212,31 +223,31 @@ def effector_weights_ui(self, context, weights, weight_type):
layout.prop(weights, "group")
- layout.use_property_split = False
-
- split = layout.split()
-
- split.prop(weights, "gravity", slider=True)
- split.prop(weights, "all", slider=True)
+ # NOTE: TODO temporarly used until the animate properties are properly skipped
+ layout.use_property_decorate = False # No animation (remove this later on)
- layout.separator()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- split = layout.split()
-
- col = split.column()
+ col = flow.column()
+ col.prop(weights, "gravity", slider=True)
+ col.prop(weights, "all", slider=True)
col.prop(weights, "force", slider=True)
col.prop(weights, "vortex", slider=True)
+
+ col = flow.column()
col.prop(weights, "magnetic", slider=True)
+ col.prop(weights, "harmonic", slider=True)
+ col.prop(weights, "charge", slider=True)
+ col.prop(weights, "lennardjones", slider=True)
+
+ col = flow.column()
col.prop(weights, "wind", slider=True)
col.prop(weights, "curve_guide", slider=True)
col.prop(weights, "texture", slider=True)
if weight_type != 'SMOKE':
col.prop(weights, "smokeflow", slider=True)
- col = split.column()
- col.prop(weights, "harmonic", slider=True)
- col.prop(weights, "charge", slider=True)
- col.prop(weights, "lennardjones", slider=True)
+ col = flow.column()
col.prop(weights, "turbulence", slider=True)
col.prop(weights, "drag", slider=True)
col.prop(weights, "boid", slider=True)
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 6a66dafadf0..3a475c82f5c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -60,7 +60,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
bl_label = "Dynamic Paint"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -87,24 +87,21 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="")
col.operator("dpaint.surface_slot_remove", icon='ZOOMOUT', text="")
+ layout.use_property_split = True
+
if surface:
layout.prop(surface, "surface_format")
col = layout.column()
if surface.surface_format != 'VERTEX':
- col.label(text="Quality:")
col.prop(surface, "image_resolution")
col.prop(surface, "use_antialiasing")
- col = layout.column()
- col.label(text="Frames:")
- split = col.split()
-
- col = split.column(align=True)
- col.prop(surface, "frame_start", text="Start")
- col.prop(surface, "frame_end", text="End")
+ sub = col.column(align=True)
+ sub.prop(surface, "frame_start", text="Frame Start")
+ sub.prop(surface, "frame_end", text="End")
- split.prop(surface, "frame_substeps")
+ col.prop(surface, "frame_substeps")
elif md.ui_type == 'BRUSH':
brush = md.brush_settings
@@ -114,22 +111,20 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
else:
layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH'
- split = layout.split()
+ layout.use_property_split = True
- col = split.column()
+ col = layout.column()
+ col.prop(brush, "paint_color")
+ col.prop(brush, "paint_alpha", text="Alpha", slider=True)
+ col.prop(brush, "paint_wetness", text="Wetness", slider=True)
col.prop(brush, "use_absolute_alpha")
col.prop(brush, "use_paint_erase")
- col.prop(brush, "paint_wetness", text="Wetness")
-
- col = split.column()
- col.prop(brush, "paint_color", text="")
- col.prop(brush, "paint_alpha", text="Alpha")
class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -141,72 +136,119 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel):
canvas = context.dynamic_paint.canvas_settings
surface = canvas.canvas_surfaces.active
-
surface_type = surface.surface_type
+ layout.use_property_split = True
+
layout.prop(surface, "surface_type")
+
layout.separator()
- # dissolve
- if surface_type == 'PAINT':
- split = layout.split(percentage=0.35)
- split.prop(surface, "use_drying", text="Dry:")
-
- col = split.column()
- col.active = surface.use_drying
- split = col.split(percentage=0.7)
- col = split.column(align=True)
- col.prop(surface, "dry_speed", text="Time")
- col.prop(surface, "color_dry_threshold")
- split.prop(surface, "use_dry_log", text="Slow")
-
- if surface_type != 'WAVE':
- split = layout.split(percentage=0.35)
- col = split.column()
- if surface_type == 'WEIGHT':
- col.prop(surface, "use_dissolve", text="Fade:")
- else:
- col.prop(surface, "use_dissolve", text="Dissolve:")
- col = split.column()
- col.active = surface.use_dissolve
- split = col.split(percentage=0.7)
- split.prop(surface, "dissolve_speed", text="Time")
- split.prop(surface, "use_dissolve_log", text="Slow")
+ col = layout.column()
# per type settings
if surface_type == 'DISPLACE':
- layout.prop(surface, "use_incremental_displace")
+ col.prop(surface, "use_incremental_displace")
if surface.surface_format == 'VERTEX':
- row = layout.row()
- row.prop(surface, "depth_clamp")
- row.prop(surface, "displace_factor")
-
- elif surface_type == 'WAVE':
- layout.prop(surface, "use_wave_open_border")
+ col.prop(surface, "depth_clamp")
+ col.prop(surface, "displace_factor")
- split = layout.split()
+ col.separator()
- col = split.column(align=True)
+ elif surface_type == 'WAVE':
+ col.prop(surface, "use_wave_open_border")
col.prop(surface, "wave_timescale")
col.prop(surface, "wave_speed")
-
- col = split.column(align=True)
col.prop(surface, "wave_damping")
col.prop(surface, "wave_spring")
col.prop(surface, "wave_smoothness")
- layout.separator()
- layout.prop(surface, "brush_group")
- row = layout.row()
- row.prop(surface, "brush_influence_scale")
- row.prop(surface, "brush_radius_scale")
+ col.separator()
+
+ col.prop(surface, "brush_group")
+ col.prop(surface, "brush_influence_scale")
+ col.prop(surface, "brush_radius_scale")
+
+
+class PHYSICS_PT_dp_advanced_canvas_paint_dry(PhysicButtonsPanel, Panel):
+ bl_label = "Dry"
+ bl_parent_id = "PHYSICS_PT_dp_advanced_canvas"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.dynamic_paint
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ surface_type = surface.surface_type
+
+ return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and surface_type == 'PAINT' and context.engine in cls.COMPAT_ENGINES
+
+ def draw_header(self, context):
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ self.layout.prop(surface, "use_drying", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ surface_type = surface.surface_type
+
+ layout.use_property_split = True
+
+ layout.active = surface.use_drying
+
+ col = layout.column()
+ col.prop(surface, "dry_speed", text="Time")
+ col.prop(surface, "color_dry_threshold")
+ col.prop(surface, "use_dry_log", text="Slow")
+
+
+class PHYSICS_PT_dp_advanced_canvas_paint_dissolve(PhysicButtonsPanel, Panel):
+ bl_label = "Dissolve"
+ bl_parent_id = "PHYSICS_PT_dp_advanced_canvas"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.dynamic_paint
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ surface_type = surface.surface_type
+
+ return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and surface_type != 'WAVE' and context.engine in cls.COMPAT_ENGINES
+
+ def draw_header(self, context):
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ self.layout.prop(surface, "use_dissolve", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ surface_type = surface.surface_type
+
+ layout.use_property_split = True
+
+ layout.active = surface.use_dissolve
+
+ col = layout.column()
+
+ col.prop(surface, "dissolve_speed", text="Time")
+ col.prop(surface, "use_dissolve_log", text="Slow")
class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
bl_label = "Output"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -220,6 +262,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
canvas = context.dynamic_paint.canvas_settings
surface = canvas.canvas_surfaces.active
@@ -300,7 +343,7 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
bl_label = "Initial Color"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -317,6 +360,8 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
surface = canvas.canvas_surfaces.active
ob = context.object
+ layout.use_property_split = True
+
layout.prop(surface, "init_color_type", expand=False)
if surface.init_color_type != 'NONE':
layout.separator()
@@ -337,7 +382,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
bl_label = "Effects"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -350,44 +395,93 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+
+class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel):
+ bl_label = "Spread"
+ bl_parent_id = "PHYSICS_PT_dp_effects"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw_header(self, context):
canvas = context.dynamic_paint.canvas_settings
surface = canvas.canvas_surfaces.active
- layout.row().prop(surface, "effect_ui", expand=True)
+ self.layout.prop(surface, "use_spread", text="")
- if surface.effect_ui == 'SPREAD':
- layout.prop(surface, "use_spread")
+ def draw(self, context):
+ layout = self.layout
- row = layout.row()
- row.active = surface.use_spread
- row.prop(surface, "spread_speed")
- row.prop(surface, "color_spread_speed")
+ layout.use_property_split = True
- elif surface.effect_ui == 'DRIP':
- layout.prop(surface, "use_drip")
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ layout.active = surface.use_spread
- col = layout.column()
- col.active = surface.use_drip
- effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT')
+ col = layout.column()
- layout.label(text="Surface Movement:")
- row = layout.row()
- row.prop(surface, "drip_velocity", slider=True)
- row.prop(surface, "drip_acceleration", slider=True)
+ col.prop(surface, "spread_speed")
+ col.prop(surface, "color_spread_speed")
- elif surface.effect_ui == 'SHRINK':
- layout.prop(surface, "use_shrink")
- row = layout.row()
- row.active = surface.use_shrink
- row.prop(surface, "shrink_speed")
+class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel):
+ bl_label = "Drip"
+ bl_parent_id = "PHYSICS_PT_dp_effects"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw_header(self, context):
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+
+ self.layout.prop(surface, "use_drip", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+
+ layout.active = surface.use_drip
+
+ col = layout.column()
+ col.prop(surface, "drip_velocity", slider=True)
+ col.prop(surface, "drip_acceleration", slider=True)
+
+ col.separator()
+
+ effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT')
+
+
+class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel):
+ bl_label = "Shrink"
+ bl_parent_id = "PHYSICS_PT_dp_effects"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw_header(self, context):
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+
+ self.layout.prop(surface, "use_shrink", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ layout.active = surface.use_shrink
+
+ layout.prop(surface, "shrink_speed")
class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -409,7 +503,7 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
bl_label = "Source"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -418,6 +512,7 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
brush = context.dynamic_paint.brush_settings
ob = context.object
@@ -427,7 +522,7 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
col.prop(brush, "paint_source")
if brush.paint_source == 'PARTICLE_SYSTEM':
- col.prop_search(brush, "particle_system", ob, "particle_systems", text="")
+ col.prop_search(brush, "particle_system", ob, "particle_systems")
if brush.particle_system:
col.label(text="Particle Effect:")
sub = col.column()
@@ -438,22 +533,19 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
col.prop(brush, "paint_distance", text="Paint Distance")
- split = layout.row().split(percentage=0.4)
- sub = split.column()
+
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}:
- sub.prop(brush, "use_proximity_project")
+ col.prop(brush, "use_proximity_project")
if brush.paint_source == 'VOLUME_DISTANCE':
- sub.prop(brush, "invert_proximity")
- sub.prop(brush, "use_negative_volume")
-
- sub = split.column()
+ col.prop(brush, "invert_proximity")
+ col.prop(brush, "use_negative_volume")
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}:
- column = sub.column()
- column.active = brush.use_proximity_project
- column.prop(brush, "ray_direction")
- sub.prop(brush, "proximity_falloff")
+ sub = col.column()
+ sub.active = brush.use_proximity_project
+ sub.prop(brush, "ray_direction")
+ col.prop(brush, "proximity_falloff")
if brush.proximity_falloff == 'RAMP':
- col = layout.row().column()
+
col.separator()
col.prop(brush, "use_proximity_ramp_alpha", text="Only Use Alpha")
col.template_color_ramp(brush, "paint_ramp", expand=True)
@@ -463,7 +555,7 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
bl_label = "Velocity"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -472,35 +564,52 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
brush = context.dynamic_paint.brush_settings
- split = layout.split()
-
- col = split.column()
+ col = layout.column()
col.prop(brush, "use_velocity_alpha")
col.prop(brush, "use_velocity_color")
-
- split.prop(brush, "use_velocity_depth")
+ col.prop(brush, "use_velocity_depth")
col = layout.column()
col.active = (brush.use_velocity_alpha or brush.use_velocity_color or brush.use_velocity_depth)
col.prop(brush, "velocity_max")
col.template_color_ramp(brush, "velocity_ramp", expand=True)
- layout.separator()
- row = layout.row()
- row.prop(brush, "use_smudge")
- sub = row.row()
- sub.active = brush.use_smudge
- sub.prop(brush, "smudge_strength")
+
+class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel):
+ bl_label = "Smudge"
+ bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.dynamic_paint
+ return md and md.ui_type == 'BRUSH' and md.brush_settings and (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ brush = context.dynamic_paint.brush_settings
+
+ self.layout.prop(brush, "use_smudge", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ brush = context.dynamic_paint.brush_settings
+
+ layout.active = brush.use_smudge
+ layout.prop(brush, "smudge_strength", slider=True)
class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
bl_label = "Waves"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -509,26 +618,33 @@ class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
brush = context.dynamic_paint.brush_settings
layout.prop(brush, "wave_type")
if brush.wave_type != 'REFLECT':
- row = layout.row()
- row.prop(brush, "wave_factor")
- row.prop(brush, "wave_clamp")
+ col = layout.column()
+ col.prop(brush, "wave_factor")
+ col.prop(brush, "wave_clamp")
classes = (
PHYSICS_UL_dynapaint_surfaces,
PHYSICS_PT_dynamic_paint,
PHYSICS_PT_dp_advanced_canvas,
+ PHYSICS_PT_dp_advanced_canvas_paint_dry,
+ PHYSICS_PT_dp_advanced_canvas_paint_dissolve,
PHYSICS_PT_dp_canvas_output,
PHYSICS_PT_dp_canvas_initial_color,
PHYSICS_PT_dp_effects,
+ PHYSICS_PT_dp_effects_spread,
+ PHYSICS_PT_dp_effects_drip,
+ PHYSICS_PT_dp_effects_shrink,
PHYSICS_PT_dp_cache,
PHYSICS_PT_dp_brush_source,
PHYSICS_PT_dp_brush_velocity,
+ PHYSICS_PT_dp_brush_velocity_smudge,
PHYSICS_PT_dp_brush_wave,
)
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 3b01015047f..1a4e24fbc0c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -38,7 +38,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
bl_label = "Force Fields"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -112,7 +112,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
bl_label = "Falloff"
bl_parent_id = "PHYSICS_PT_field"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -170,7 +170,7 @@ class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
bl_label = "Collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -199,7 +199,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
bl_label = "Particle"
bl_parent_id = "PHYSICS_PT_collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -241,7 +241,7 @@ class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
class PHYSICS_PT_collision_softbody(PhysicButtonsPanel, Panel):
bl_label = "Softbody"
bl_parent_id = "PHYSICS_PT_collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index db59665e21d..d121b6a389d 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -29,7 +29,7 @@ class PHYSICS_PT_rigidbody_panel:
class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Rigid Body"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -39,25 +39,27 @@ class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
rbo = ob.rigid_body
if rbo is not None:
layout.prop(rbo, "type", text="Type")
- row = layout.row()
- if rbo.type == 'ACTIVE':
- row.prop(rbo, "enabled", text="Dynamic")
- row.prop(rbo, "kinematic", text="Animated")
if rbo.type == 'ACTIVE':
layout.prop(rbo, "mass")
+ col = layout.column()
+ if rbo.type == 'ACTIVE':
+ col.prop(rbo, "enabled", text="Dynamic")
+ col.prop(rbo, "kinematic", text="Animated")
+
class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Collisions"
bl_parent_id = 'PHYSICS_PT_rigid_body'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -70,6 +72,7 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
ob = context.object
rbo = ob.rigid_body
+ layout.use_property_split = True
layout.prop(rbo, "collision_shape", text="Shape")
@@ -79,15 +82,52 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
if rbo.collision_shape == 'MESH' and rbo.mesh_source == 'DEFORM':
layout.prop(rbo, "use_deform", text="Deforming")
- split = layout.split()
- col = split.column()
- col.label(text="Surface Response:")
+class PHYSICS_PT_rigid_body_collisions_surface(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Surface Response"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+ layout.use_property_split = True
+
+ col = layout.column()
col.prop(rbo, "friction")
col.prop(rbo, "restitution", text="Bounciness")
- col = split.column()
- col.label(text="Sensitivity:")
+
+class PHYSICS_PT_rigid_body_collisions_sensitivity(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Sensitivity"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+ layout.use_property_split = True
+
+ col = layout.column()
+
if rbo.collision_shape in {'MESH', 'CONE'}:
col.prop(rbo, "collision_margin", text="Margin")
else:
@@ -96,14 +136,33 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
sub.active = rbo.use_margin
sub.prop(rbo, "collision_margin", text="Margin")
- layout.prop(rbo, "collision_groups")
+
+class PHYSICS_PT_rigid_body_collisions_collections(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Collision Collections"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ layout.prop(rbo, "collision_groups", text="")
class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Dynamics"
bl_parent_id = 'PHYSICS_PT_rigid_body'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -114,6 +173,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
rbo = ob.rigid_body
@@ -122,28 +182,53 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
# col.label(text="Activation:")
# XXX: settings such as activate on collison/etc.
- split = layout.split()
+ col = layout.column()
+ col.prop(rbo, "linear_damping", text="Translation Damping")
+ col.prop(rbo, "angular_damping", text="Rotation Damping")
- col = split.column()
- col.label(text="Deactivation:")
- col.prop(rbo, "use_deactivation")
- sub = col.column()
- sub.active = rbo.use_deactivation
- sub.prop(rbo, "use_start_deactivated")
- sub.prop(rbo, "deactivate_linear_velocity", text="Linear Vel")
- sub.prop(rbo, "deactivate_angular_velocity", text="Angular Vel")
- # TODO: other params such as time?
- col = split.column()
- col.label(text="Damping:")
- col.prop(rbo, "linear_damping", text="Translation")
- col.prop(rbo, "angular_damping", text="Rotation")
+class PHYSICS_PT_rigid_body_dynamics_deactivation(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Deactivation"
+ bl_parent_id = 'PHYSICS_PT_rigid_body_dynamics'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ obj.rigid_body.type == 'ACTIVE' and
+ (context.engine in cls.COMPAT_ENGINES))
+
+ def draw_header(self, context):
+ ob = context.object
+ rbo = ob.rigid_body
+ self.layout.prop(rbo, "use_deactivation", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ layout.active = rbo.use_deactivation
+
+ col = layout.column()
+ col.prop(rbo, "use_start_deactivated")
+ col.prop(rbo, "deactivate_linear_velocity", text="Linear Velocity")
+ col.prop(rbo, "deactivate_angular_velocity", text="Angular Velocity")
+ # TODO: other params such as time?
classes = (
PHYSICS_PT_rigid_body,
PHYSICS_PT_rigid_body_collisions,
+ PHYSICS_PT_rigid_body_collisions_surface,
+ PHYSICS_PT_rigid_body_collisions_sensitivity,
+ PHYSICS_PT_rigid_body_collisions_collections,
PHYSICS_PT_rigid_body_dynamics,
+ PHYSICS_PT_rigid_body_dynamics_deactivation,
)
if __name__ == "__main__": # only for live edit.
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 aca989fd0ba..5e67caadc90 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
@@ -29,7 +29,7 @@ class PHYSICS_PT_rigidbody_constraint_panel:
class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Rigid Body Constraint"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -139,6 +139,11 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa
sub.prop(rbc, "motor_ang_max_impulse", text="Max Impulse")
elif rbc.type in {'GENERIC', 'GENERIC_SPRING'}:
+ if rbc.type == 'GENERIC_SPRING':
+ row = layout.row()
+ row.label("Spring Type:")
+ row.prop(rbc, "spring_type", text="")
+
col = layout.column(align=True)
col.label("Limits:")
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index acbaecbda4c..0a4f1c71126 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -39,7 +39,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
bl_label = "Smoke"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -138,7 +138,7 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -174,7 +174,7 @@ class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
bl_label = "Flames"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -205,7 +205,7 @@ class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
bl_label = "Adaptive Domain"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -240,7 +240,7 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
bl_label = "High Resolution"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -280,7 +280,7 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
bl_label = "Groups"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -309,7 +309,7 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -346,7 +346,7 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 68db165875e..77440bdc628 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -46,7 +46,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
bl_label = "Soft Body"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -77,7 +77,7 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
md = context.soft_body
@@ -88,7 +88,7 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
bl_label = "Goal"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -129,7 +129,7 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
bl_label = "Edges"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -180,7 +180,7 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
bl_label = "Self Collision"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -210,7 +210,7 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
bl_label = "Solver"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -244,7 +244,7 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
md = context.soft_body
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index a7cfee5ed8f..2b91eec67c4 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -21,6 +21,11 @@
import bpy
from bpy.types import Menu, Panel, UIList
from bl_operators.presets import PresetMenu
+from .space_view3d import (
+ VIEW3D_PT_shading_lighting,
+ VIEW3D_PT_shading_color,
+ VIEW3D_PT_shading_options,
+)
class RENDER_PT_presets(PresetMenu):
@@ -79,7 +84,7 @@ class RENDER_PT_context(Panel):
class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
bl_label = "Dimensions"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_frame_rate_args_prev = None
_preset_class = None
@@ -115,7 +120,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
return args
@staticmethod
- def draw_framerate(sub, rd):
+ def draw_framerate(layout, sub, rd):
if RENDER_PT_dimensions._preset_class is None:
RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets
@@ -125,8 +130,9 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
if show_framerate:
- sub.prop(rd, "fps")
- sub.prop(rd, "fps_base", text="/")
+ col = layout.column(align=True)
+ col.prop(rd, "fps")
+ col.prop(rd, "fps_base", text="Base")
def draw(self, context):
layout = self.layout
@@ -156,17 +162,17 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
col.prop(scene, "frame_end", text="End")
col.prop(scene, "frame_step", text="Step")
- col = layout.split(percentage=0.5)
+ col = layout.split()
col.alignment = 'RIGHT'
col.label(text="Frame Rate")
- self.draw_framerate(col, rd)
+ self.draw_framerate(layout, col, rd)
class RENDER_PT_frame_remapping(RenderButtonsPanel, Panel):
bl_label = "Time Remapping"
bl_parent_id = "RENDER_PT_dimensions"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -183,7 +189,7 @@ class RENDER_PT_frame_remapping(RenderButtonsPanel, Panel):
class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -201,7 +207,7 @@ class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
class RENDER_PT_stamp(RenderButtonsPanel, Panel):
bl_label = "Metadata"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -213,23 +219,35 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
split = layout.split()
col = split.column(align=True)
- col.prop(rd, "use_stamp_time", text="Time")
col.prop(rd, "use_stamp_date", text="Date")
- col.prop(rd, "use_stamp_render_time", text="RenderTime")
+ col.prop(rd, "use_stamp_time", text="Time")
+
+ col.separator()
+
+ col.prop(rd, "use_stamp_render_time", text="Render Time")
col.prop(rd, "use_stamp_frame", text="Frame")
- col.prop(rd, "use_stamp_scene", text="Scene")
+ col.prop(rd, "use_stamp_frame_range", text="Frame Range")
col.prop(rd, "use_stamp_memory", text="Memory")
col = split.column(align=True)
col.prop(rd, "use_stamp_camera", text="Camera")
col.prop(rd, "use_stamp_lens", text="Lens")
- col.prop(rd, "use_stamp_filename", text="Filename")
- col.prop(rd, "use_stamp_frame_range", text="Frame range")
+
+ col.separator()
+
+ col.prop(rd, "use_stamp_scene", text="Scene")
col.prop(rd, "use_stamp_marker", text="Marker")
- col.prop(rd, "use_stamp_sequencer_strip", text="Seq. Strip")
+
+ col.separator()
+
+ col.prop(rd, "use_stamp_filename", text="Filename")
+
+ col.separator()
+
+ col.prop(rd, "use_stamp_sequencer_strip", text="Strip Name")
if rd.use_sequencer:
- col.prop(rd, "use_stamp_strip_meta", text="Sequence Strip")
+ col.prop(rd, "use_stamp_strip_meta", text="Use Strip Metadata")
row = layout.split(percentage=0.3)
row.prop(rd, "use_stamp_note", text="Note")
@@ -242,7 +260,7 @@ class RENDER_PT_stamp_burn(RenderButtonsPanel, Panel):
bl_label = "Burn Into Image"
bl_parent_id = "RENDER_PT_stamp"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
rd = context.scene.render
@@ -266,7 +284,7 @@ class RENDER_PT_stamp_burn(RenderButtonsPanel, Panel):
class RENDER_PT_output(RenderButtonsPanel, Panel):
bl_label = "Output"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -298,7 +316,7 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
class RENDER_PT_encoding(RenderButtonsPanel, Panel):
bl_label = "Encoding"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header_preset(self, context):
RENDER_PT_ffmpeg_presets.draw_panel_header(self.layout)
@@ -395,7 +413,7 @@ class RENDER_UL_renderviews(UIList):
class RENDER_PT_stereoscopy(RenderButtonsPanel, Panel):
bl_label = "Stereoscopy"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
@@ -589,8 +607,6 @@ class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
sub = col.column()
sub.active = props.use_volumetric_shadows
sub.prop(props, "volumetric_shadow_samples", text="Shadow Samples")
- col.separator()
- col.prop(props, "use_volumetric_colored_transmittance")
class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel):
@@ -777,7 +793,7 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
col.prop(rd, "alpha_mode", text="Alpha")
-class RENDER_PT_hair(RenderButtonsPanel, Panel):
+class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
bl_label = "Hair"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE'}
@@ -798,6 +814,60 @@ class RENDER_PT_hair(RenderButtonsPanel, Panel):
layout.prop(rd, "hair_subdiv")
+class RENDER_PT_opengl_film(RenderButtonsPanel, Panel):
+ bl_label = "Film"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_OPENGL'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ rd = context.scene.render
+
+ layout.prop(rd, "use_antialiasing")
+
+ layout.prop(rd, "antialiasing_samples")
+ layout.prop(rd, "alpha_mode")
+
+
+class RENDER_PT_opengl_lighting(RenderButtonsPanel, Panel):
+ bl_label = "Lighting"
+ COMPAT_ENGINES = {'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ VIEW3D_PT_shading_lighting.draw(self, context)
+
+
+class RENDER_PT_opengl_color(RenderButtonsPanel, Panel):
+ bl_label = "Color"
+ COMPAT_ENGINES = {'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ VIEW3D_PT_shading_color.draw(self, context)
+
+
+class RENDER_PT_opengl_options(RenderButtonsPanel, Panel):
+ bl_label = "Options"
+ COMPAT_ENGINES = {'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ VIEW3D_PT_shading_options.draw(self, context)
+
+
classes = (
RENDER_PT_presets,
RENDER_PT_ffmpeg_presets,
@@ -812,7 +882,7 @@ classes = (
RENDER_PT_stamp_burn,
RENDER_UL_renderviews,
RENDER_PT_stereoscopy,
- RENDER_PT_hair,
+ RENDER_PT_eevee_hair,
RENDER_PT_eevee_sampling,
RENDER_PT_eevee_film,
RENDER_PT_eevee_shadows,
@@ -824,6 +894,10 @@ classes = (
RENDER_PT_eevee_motion_blur,
RENDER_PT_eevee_depth_of_field,
RENDER_PT_eevee_bloom,
+ RENDER_PT_opengl_film,
+ RENDER_PT_opengl_lighting,
+ RENDER_PT_opengl_color,
+ RENDER_PT_opengl_options,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index d0fce0a2582..5d87b858da6 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -17,9 +17,9 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
+
import bpy
from bpy.types import (
- Menu,
Panel,
UIList,
)
@@ -66,11 +66,12 @@ class SceneButtonsPanel:
class SCENE_PT_scene(SceneButtonsPanel, Panel):
bl_label = "Scene"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
+
scene = context.scene
layout.prop(scene, "camera")
@@ -80,7 +81,7 @@ class SCENE_PT_scene(SceneButtonsPanel, Panel):
class SCENE_PT_unit(SceneButtonsPanel, Panel):
bl_label = "Units"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header_preset(self, context):
SCENE_PT_units_length_presets.draw_panel_header(self.layout)
@@ -92,13 +93,13 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
layout.use_property_split = True
- col = layout.column()
- col.prop(unit, "system")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
- col = layout.column()
+ col = flow.column()
+ col.prop(unit, "system")
col.prop(unit, "system_rotation")
- col = layout.column()
+ col = flow.column()
col.enabled = unit.system != 'NONE'
col.prop(unit, "scale_length")
col.prop(unit, "use_separate")
@@ -147,25 +148,28 @@ class SceneKeyingSetsPanel:
propname = prop
row = layout.row(align=True)
- row.prop(item, toggle_prop, text="", icon='STYLUS_PRESSURE', toggle=True) # XXX: needs dedicated icon
- subrow = row.row()
+ subrow = row.row(align=True)
subrow.active = getattr(item, toggle_prop)
+
if subrow.active:
subrow.prop(item, prop, text=label)
else:
subrow.prop(owner, propname, text=label)
+ row.prop(item, toggle_prop, text="", icon='STYLUS_PRESSURE', toggle=True) # XXX: needs dedicated icon
+
class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Keying Sets"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
scene = context.scene
+
row = layout.row()
col = row.column()
@@ -175,26 +179,62 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
col.operator("anim.keying_set_remove", icon='ZOOMOUT', text="")
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
+
ks = scene.keying_sets.active
if ks and ks.is_path_absolute:
- row = layout.row()
-
- col = row.column()
+ col = flow.column()
col.prop(ks, "bl_description")
- subcol = col.column()
+ subcol = flow.column()
subcol.operator_context = 'INVOKE_DEFAULT'
subcol.operator("anim.keying_set_export", text="Export to File").filepath = "keyingset.py"
- col = row.column()
- col.label(text="Keyframing Settings:")
- self.draw_keyframing_settings(context, col, ks, None)
+
+class SCENE_PT_keyframing_settings(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
+ bl_label = "Keyframing Settings"
+ bl_parent_id = "SCENE_PT_keying_sets"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ ks = context.scene.keying_sets.active
+ return (ks and ks.is_path_absolute)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ scene = context.scene
+ ks = scene.keying_sets.active
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+ col = flow.column(align=True)
+ col.alignment = 'RIGHT'
+ col.label(text="General Override")
+
+ self.draw_keyframing_settings(context, col, ks, None)
+
+ ksp = ks.paths.active
+ if ksp:
+ col.separator()
+
+ col = flow.column(align=True)
+ col.alignment = 'RIGHT'
+ col.label(text="Active Set Override")
+
+ self.draw_keyframing_settings(context, col, ks, ksp)
class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Active Keying Set"
bl_parent_id = "SCENE_PT_keying_sets"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -219,39 +259,45 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
col.operator("anim.keying_set_path_remove", icon='ZOOMOUT', text="")
+ # TODO: 1) the template_any_ID needs to be fixed for the text alignment.
+ # 2) use_property_decorate has to properly skip the non animatable properties.
+ # Properties affected with needless draw:
+ # group_method, template_any_ID dropdown, use_entire_array
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation (remove this later on).
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
+
ksp = ks.paths.active
if ksp:
- col = layout.column()
- col.label(text="Target:")
- col.template_any_ID(ksp, "id", "id_type")
- col.template_path_builder(ksp, "data_path", ksp.id)
-
- row = col.row(align=True)
- row.label(text="Array Target:")
- row.prop(ksp, "use_entire_array", text="All Items")
- if ksp.use_entire_array:
- row.label(text=" ") # padding
- else:
- row.prop(ksp, "array_index", text="Index")
+ col = flow.column(align=True)
+ col.alignment = 'RIGHT'
- layout.separator()
+ col.template_any_ID(ksp, "id", "id_type", text="Target ID-Block")
- row = layout.row()
- col = row.column()
- col.label(text="F-Curve Grouping:")
- col.prop(ksp, "group_method", text="")
+ col.separator()
+
+ col.template_path_builder(ksp, "data_path", ksp.id, text="Data Path")
+
+ col = flow.column()
+
+ col.prop(ksp, "use_entire_array", text="Array All Items")
+
+ if not ksp.use_entire_array:
+ col.prop(ksp, "array_index", text="Index")
+
+ col.separator()
+
+ col.prop(ksp, "group_method", text="F-Curve Grouping")
if ksp.group_method == 'NAMED':
col.prop(ksp, "group")
- col = row.column()
- col.label(text="Keyframing Settings:")
- self.draw_keyframing_settings(context, col, ks, ksp)
-
class SCENE_PT_color_management(SceneButtonsPanel, Panel):
bl_label = "Color Management"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -260,16 +306,19 @@ class SCENE_PT_color_management(SceneButtonsPanel, Panel):
scene = context.scene
view = scene.view_settings
- col = layout.column()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+ col = flow.column()
col.prop(scene.display_settings, "display_device")
col.separator()
- col = layout.column()
col.prop(view, "view_transform")
+ col.prop(view, "look")
+
+ col = flow.column()
col.prop(view, "exposure")
col.prop(view, "gamma")
- col.prop(view, "look")
col.separator()
@@ -280,7 +329,7 @@ class SCENE_PT_color_management_curves(SceneButtonsPanel, Panel):
bl_label = "Use Curves"
bl_parent_id = "SCENE_PT_color_management"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
@@ -304,7 +353,7 @@ class SCENE_PT_color_management_curves(SceneButtonsPanel, Panel):
class SCENE_PT_audio(SceneButtonsPanel, Panel):
bl_label = "Audio"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -314,21 +363,28 @@ class SCENE_PT_audio(SceneButtonsPanel, Panel):
rd = context.scene.render
ffmpeg = rd.ffmpeg
- layout.prop(scene, "audio_volume")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- col = layout.column()
- col.prop(scene, "audio_distance_model")
+ col = flow.column()
+ col.prop(scene, "audio_volume")
+
+ col.separator()
+ col.prop(scene, "audio_distance_model")
col.prop(ffmpeg, "audio_channels")
+
+ col.separator()
+
+ col = flow.column()
col.prop(ffmpeg, "audio_mixrate", text="Sample Rate")
- layout.separator()
+ col.separator()
- col = layout.column(align=True)
+ col = col.column(align=True)
col.prop(scene, "audio_doppler_speed", text="Doppler Speed")
col.prop(scene, "audio_doppler_factor", text="Doppler Factor")
- layout.separator()
+ col.separator()
layout.operator("sound.bake_animation")
@@ -336,7 +392,7 @@ class SCENE_PT_audio(SceneButtonsPanel, Panel):
class SCENE_PT_physics(SceneButtonsPanel, Panel):
bl_label = "Gravity"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
self.layout.prop(context.scene, "use_gravity", text="")
@@ -355,7 +411,7 @@ class SCENE_PT_physics(SceneButtonsPanel, Panel):
class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
bl_label = "Rigid Body World"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -372,7 +428,6 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
layout.use_property_split = True
scene = context.scene
-
rbw = scene.rigidbody_world
if rbw is None:
@@ -380,7 +435,28 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
else:
layout.operator("rigidbody.world_remove")
- col = layout.column()
+
+class SCENE_PT_rigid_body_world_settings(SceneButtonsPanel, Panel):
+ bl_label = "Settings"
+ bl_parent_id = "SCENE_PT_rigid_body_world"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ rbw = scene.rigidbody_world
+
+ if rbw:
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+
+ col = flow.column()
col.active = rbw.enabled
col = col.column()
@@ -389,6 +465,9 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
col = col.column()
col.prop(rbw, "time_scale", text="Speed")
+
+ col = flow.column()
+ col.active = rbw.enabled
col.prop(rbw, "use_split_impulse")
col = col.column()
@@ -400,7 +479,7 @@ class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = "SCENE_PT_rigid_body_world"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -418,7 +497,7 @@ class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = "SCENE_PT_rigid_body_world"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -435,7 +514,7 @@ class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
class SCENE_PT_simplify(SceneButtonsPanel, Panel):
bl_label = "Simplify"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw_header(self, context):
rd = context.scene.render
@@ -448,7 +527,7 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
class SCENE_PT_simplify_viewport(SceneButtonsPanel, Panel):
bl_label = "Viewport"
bl_parent_id = "SCENE_PT_simplify"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -458,15 +537,19 @@ class SCENE_PT_simplify_viewport(SceneButtonsPanel, Panel):
layout.active = rd.use_simplify
- col = layout.column()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+ col = flow.column()
col.prop(rd, "simplify_subdivision", text="Max Subdivision")
+
+ col = flow.column()
col.prop(rd, "simplify_child_particles", text="Max Child Particles")
class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
bl_label = "Render"
bl_parent_id = "SCENE_PT_simplify"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -476,13 +559,47 @@ class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
layout.active = rd.use_simplify
- col = layout.column()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+ col = flow.column()
col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
+
+ col = flow.column()
col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
+class SCENE_PT_simplify_greasepencil(SceneButtonsPanel, Panel):
+ bl_label = "Grease Pencil"
+ bl_parent_id = "SCENE_PT_simplify"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "simplify_gpencil", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ rd = context.scene.render
+
+ layout.active = rd.simplify_gpencil
+
+ col = layout.column()
+ col.prop(rd, "simplify_gpencil_onplay", text="Playback Only")
+ col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
+ col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX")
+
+ col = layout.column(align=True)
+ col.prop(rd, "simplify_gpencil_view_fill")
+ sub = col.column()
+ sub.active = rd.simplify_gpencil_view_fill
+ sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
+
+
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "scene"
_property_type = bpy.types.Scene
@@ -494,16 +611,19 @@ classes = (
SCENE_PT_unit,
SCENE_PT_keying_sets,
SCENE_PT_keying_set_paths,
+ SCENE_PT_keyframing_settings,
SCENE_PT_color_management,
SCENE_PT_color_management_curves,
SCENE_PT_audio,
SCENE_PT_physics,
SCENE_PT_rigid_body_world,
+ SCENE_PT_rigid_body_world_settings,
SCENE_PT_rigid_body_cache,
SCENE_PT_rigid_body_field_weights,
SCENE_PT_simplify,
SCENE_PT_simplify_viewport,
SCENE_PT_simplify_render,
+ SCENE_PT_simplify_greasepencil,
SCENE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index b3b7341a734..a4f6f753669 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -17,19 +17,21 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
-import bpy
-from bpy.types import Menu, Panel, UIList
+import bpy
+from bpy.types import (
+ Menu,
+ Panel,
+ UIList,
+)
from bpy.types import (
Brush,
FreestyleLineStyle,
- Object,
ParticleSettings,
Texture,
)
from rna_prop_ui import PropertyPanel
-
from .properties_paint_common import brush_texture_settings
@@ -47,9 +49,9 @@ class TEXTURE_MT_specials(Menu):
class TEXTURE_UL_texslots(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- ma = data
slot = item
tex = slot.texture if slot else None
+
if self.layout_type in {'DEFAULT', 'COMPACT'}:
if tex:
layout.prop(tex, "name", text="", emboss=False, icon_value=icon)
@@ -83,7 +85,7 @@ class TextureButtonsPanel:
class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -112,7 +114,7 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
bl_label = ""
bl_context = "texture"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -131,18 +133,18 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
if not pin_id:
col.template_texture_user()
- col.separator()
-
if user or pin_id:
+ col.separator()
+
if pin_id:
col.template_ID(space, "pin_id")
else:
propname = context.texture_user_property.identifier
col.template_ID(user, propname, new="texture.new")
- col.separator()
-
if tex:
+ col.separator()
+
split = col.split(percentage=0.2)
split.label(text="Type")
split.prop(tex, "type", text="")
@@ -151,7 +153,7 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
class TEXTURE_PT_node(TextureButtonsPanel, Panel):
bl_label = "Node"
bl_context = "texture"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -169,7 +171,7 @@ class TEXTURE_PT_node(TextureButtonsPanel, Panel):
class TEXTURE_PT_node_mapping(TextureButtonsPanel, Panel):
bl_label = "Mapping"
bl_context = "texture"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -179,25 +181,35 @@ class TEXTURE_PT_node_mapping(TextureButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
node = context.texture_node
mapping = node.texture_mapping
- layout.prop(mapping, "vector_type", expand=True)
+ col = flow.column()
+ col.prop(mapping, "vector_type")
+
+ col.separator()
+
+ col = col.column(align=True)
+ col.prop(mapping, "mapping_x", text="Projection X")
+ col.prop(mapping, "mapping_y", text="Y")
+ col.prop(mapping, "mapping_z", text="Z")
- row = layout.row()
+ col.separator()
- row.column().prop(mapping, "translation")
- row.column().prop(mapping, "rotation")
- row.column().prop(mapping, "scale")
+ col = flow.column()
+ col.column().prop(mapping, "translation")
- layout.label(text="Projection:")
+ col = flow.column()
+ col.column().prop(mapping, "rotation")
- row = layout.row()
- row.prop(mapping, "mapping_x", text="")
- row.prop(mapping, "mapping_y", text="")
- row.prop(mapping, "mapping_z", text="")
+ col = flow.column()
+ col.column().prop(mapping, "scale")
class TextureTypePanel(TextureButtonsPanel):
@@ -212,79 +224,102 @@ class TextureTypePanel(TextureButtonsPanel):
class TEXTURE_PT_clouds(TextureTypePanel, Panel):
bl_label = "Clouds"
tex_type = 'CLOUDS'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
tex = context.texture
- layout.row().prop(tex, "cloud_type", expand=True)
- layout.label(text="Noise:")
- layout.row().prop(tex, "noise_type", text="Type", expand=True)
- layout.prop(tex, "noise_basis", text="Basis")
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
+
+ col.separator()
+
+ col.prop(tex, "noise_type", text="Type")
- split = layout.split()
+ col.separator()
- col = split.column()
+ col = flow.column()
+ col.prop(tex, "cloud_type")
+
+ col.separator()
+
+ col = flow.column()
col.prop(tex, "noise_scale", text="Size")
col.prop(tex, "noise_depth", text="Depth")
-
- split.prop(tex, "nabla", text="Nabla")
+ col.prop(tex, "nabla", text="Nabla")
class TEXTURE_PT_wood(TextureTypePanel, Panel):
bl_label = "Wood"
tex_type = 'WOOD'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=False)
tex = context.texture
- layout.row().prop(tex, "noise_basis_2", expand=True)
- layout.row().prop(tex, "wood_type", expand=True)
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
- col = layout.column()
- col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
- col.label(text="Noise:")
- col.row().prop(tex, "noise_type", text="Type", expand=True)
- layout.prop(tex, "noise_basis", text="Basis")
+ col.separator()
- split = layout.split()
- split.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
+ col.prop(tex, "wood_type")
- col = split.column()
- col.prop(tex, "noise_scale", text="Size")
- col.prop(tex, "turbulence")
+ col.separator()
- split.prop(tex, "nabla")
+ col = flow.column()
+ col.prop(tex, "noise_basis_2", text="Second Basis")
+
+ col = col.column()
+ col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
+ col.prop(tex, "noise_type", text="Type")
+
+ col.separator()
+
+ sub = flow.column()
+ sub.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
+ sub.prop(tex, "noise_scale", text="Size")
+ sub.prop(tex, "turbulence")
+ sub.prop(tex, "nabla")
class TEXTURE_PT_marble(TextureTypePanel, Panel):
bl_label = "Marble"
tex_type = 'MARBLE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
tex = context.texture
- layout.row().prop(tex, "marble_type", expand=True)
- layout.row().prop(tex, "noise_basis_2", expand=True)
- layout.label(text="Noise:")
- layout.row().prop(tex, "noise_type", text="Type", expand=True)
- layout.prop(tex, "noise_basis", text="Basis")
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
+
+ col.separator()
+
+ col.prop(tex, "marble_type")
+
+ col.separator()
+
+ col = flow.column()
+ col.prop(tex, "noise_basis_2", text="Second Basis")
+ col.prop(tex, "noise_type", text="Type")
- split = layout.split()
+ col.separator()
- col = split.column()
+ col = flow.column()
col.prop(tex, "noise_scale", text="Size")
col.prop(tex, "noise_depth", text="Depth")
-
- col = split.column()
col.prop(tex, "turbulence")
col.prop(tex, "nabla")
@@ -292,60 +327,91 @@ class TEXTURE_PT_marble(TextureTypePanel, Panel):
class TEXTURE_PT_magic(TextureTypePanel, Panel):
bl_label = "Magic"
tex_type = 'MAGIC'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
tex = context.texture
- row = layout.row()
- row.prop(tex, "noise_depth", text="Depth")
- row.prop(tex, "turbulence")
+ col = flow.column()
+ col.prop(tex, "noise_depth", text="Depth")
+
+ col = flow.column()
+ col.prop(tex, "turbulence")
class TEXTURE_PT_blend(TextureTypePanel, Panel):
bl_label = "Blend"
tex_type = 'BLEND'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
tex = context.texture
- layout.prop(tex, "progression")
+ col = flow.column()
+ col.prop(tex, "progression")
- sub = layout.row()
+ col.separator()
- sub.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'})
- sub.prop(tex, "use_flip_axis", expand=True)
+ col = flow.column()
+ col.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'})
+ col.prop(tex, "use_flip_axis", text="Orientation")
class TEXTURE_PT_stucci(TextureTypePanel, Panel):
bl_label = "Stucci"
tex_type = 'STUCCI'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
tex = context.texture
- layout.row().prop(tex, "stucci_type", expand=True)
- layout.label(text="Noise:")
- layout.row().prop(tex, "noise_type", text="Type", expand=True)
- layout.prop(tex, "noise_basis", text="Basis")
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
+
+ col.separator()
+
+ col.row().prop(tex, "stucci_type")
+
+ col.separator()
+
+ col = flow.column()
+ col.prop(tex, "noise_type", text="Type")
+
+ col.separator()
- row = layout.row()
- row.prop(tex, "noise_scale", text="Size")
- row.prop(tex, "turbulence")
+ col = flow.column()
+ col.prop(tex, "noise_scale", text="Size")
+ col.prop(tex, "turbulence")
class TEXTURE_PT_image(TextureTypePanel, Panel):
bl_label = "Image"
tex_type = 'IMAGE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw(self, context):
+ # TODO: maybe expose the template_ID from the template image here.
+ layout = self.layout
+ del layout
+
+
+class TEXTURE_PT_image_settings(TextureTypePanel, Panel):
+ bl_label = "Settings"
+ bl_parent_id = 'TEXTURE_PT_image'
+ tex_type = 'IMAGE'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
@@ -356,11 +422,13 @@ class TEXTURE_PT_image(TextureTypePanel, Panel):
def texture_filter_common(tex, layout):
layout.prop(tex, "filter_type", text="Filter Type")
+
if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}:
+ col = layout.column()
if tex.filter_type == 'FELINE':
- layout.prop(tex, "filter_lightprobes", text="Light Probes")
+ col.prop(tex, "filter_lightprobes", text="Light Probes")
else:
- layout.prop(tex, "filter_eccentricity", text="Eccentricity")
+ col.prop(tex, "filter_eccentricity", text="Eccentricity")
layout.prop(tex, "filter_size", text="Size")
layout.prop(tex, "use_filter_size_min", text="Minimum Size")
@@ -376,14 +444,11 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- idblock = context_tex_datablock(context)
tex = context.texture
- slot = getattr(context, "texture_slot", None)
col = flow.column()
- col.prop(tex, "use_flip_axis", text="Flip X/Y Axis")
col.prop(tex, "use_interpolation")
col.separator()
@@ -396,8 +461,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
col.separator()
- col = flow.column()
- texture_filter_common(tex, col)
+ texture_filter_common(tex, flow)
class TEXTURE_PT_image_alpha(TextureTypePanel, Panel):
@@ -433,141 +497,200 @@ class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
tex = context.texture
- col = flow.column()
- col.prop(tex, "extension")
+ col = layout.column()
+ col.prop(tex, "use_flip_axis", text="Flip Axes")
+
+ col.separator()
+
+ subcol = layout.column()
+ subcol.prop(tex, "extension") # use layout, to keep the same location in case of button cycling.
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
if tex.extension == 'REPEAT':
+
+ col = flow.column()
sub = col.column(align=True)
sub.prop(tex, "repeat_x", text="Repeat X")
sub.prop(tex, "repeat_y", text="Y")
+ col = flow.column()
sub = col.column()
- sub.prop(tex, "use_mirror_x", text="Mirror X")
sub.active = (tex.repeat_x > 1)
+ sub.prop(tex, "use_mirror_x", text="Mirror X")
sub = col.column()
- sub.prop(tex, "use_mirror_y", text="Y")
sub.active = (tex.repeat_y > 1)
+ sub.prop(tex, "use_mirror_y", text="Y")
elif tex.extension == 'CHECKER':
- col = layout.column(align=True)
- col.prop(tex, "use_checker_even", text="Even")
- col.prop(tex, "use_checker_odd", text="Odd")
+ subcol.separator()
- col = layout.column()
+ col = flow.column()
col.prop(tex, "checker_distance", text="Distance")
- col = flow.column()
- sub = col.column(align=True)
+ col = flow.column()
+ col.prop(tex, "use_checker_even", text="Tiles Even")
+ col.prop(tex, "use_checker_odd", text="Odd")
+ else:
+ del flow
+
+
+class TEXTURE_PT_image_mapping_crop(TextureTypePanel, Panel):
+ bl_label = "Crop"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'TEXTURE_PT_image_mapping'
+ tex_type = 'IMAGE'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ tex = context.texture
+
+ col = flow.column(align=True)
# col.prop(tex, "crop_rectangle")
- sub.prop(tex, "crop_min_x", text="Crop Minimum X")
- sub.prop(tex, "crop_min_y", text="Y")
+ col.prop(tex, "crop_min_x", text="Minimum X")
+ col.prop(tex, "crop_min_y", text="Y")
- sub = col.column(align=True)
- sub.prop(tex, "crop_max_x", text="Crop Maximum X")
- sub.prop(tex, "crop_max_y", text="Y")
+ col = flow.column(align=True)
+ col.prop(tex, "crop_max_x", text="Maximum X")
+ col.prop(tex, "crop_max_y", text="Y")
class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
bl_label = "Musgrave"
tex_type = 'MUSGRAVE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
tex = context.texture
- layout.prop(tex, "musgrave_type")
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
+
+ col.separator()
+
+ col.prop(tex, "musgrave_type")
- split = layout.split()
+ col.separator()
- col = split.column()
+ col.prop(tex, "noise_scale", text="Size")
+ col.prop(tex, "nabla")
+
+ col.separator()
+
+ col = flow.column()
col.prop(tex, "dimension_max", text="Dimension")
col.prop(tex, "lacunarity")
col.prop(tex, "octaves")
+ col.separator()
+
musgrave_type = tex.musgrave_type
- col = split.column()
+
+ col = flow.column()
+
if musgrave_type in {'HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "offset")
col.prop(tex, "noise_intensity", text="Intensity")
+
if musgrave_type in {'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "gain")
- layout.label(text="Noise:")
-
- layout.prop(tex, "noise_basis", text="Basis")
-
- row = layout.row()
- row.prop(tex, "noise_scale", text="Size")
- row.prop(tex, "nabla")
-
class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
bl_label = "Voronoi"
tex_type = 'VORONOI'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
tex = context.texture
- split = layout.split()
+ col = flow.column()
+ col.prop(tex, "distance_metric")
- col = split.column()
- col.label(text="Distance Metric:")
- col.prop(tex, "distance_metric", text="")
sub = col.column()
sub.active = tex.distance_metric == 'MINKOVSKY'
sub.prop(tex, "minkovsky_exponent", text="Exponent")
- col.label(text="Coloring:")
- col.prop(tex, "color_mode", text="")
+
+ sub.separator()
+
+ col = flow.column()
+ col.prop(tex, "color_mode")
col.prop(tex, "noise_intensity", text="Intensity")
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Feature Weights:")
- sub.prop(tex, "weight_1", text="1", slider=True)
- sub.prop(tex, "weight_2", text="2", slider=True)
- sub.prop(tex, "weight_3", text="3", slider=True)
- sub.prop(tex, "weight_4", text="4", slider=True)
+ col.separator()
- layout.label(text="Noise:")
- row = layout.row()
- row.prop(tex, "noise_scale", text="Size")
- row.prop(tex, "nabla")
+ col = flow.column()
+ col.prop(tex, "noise_scale", text="Size")
+ col.prop(tex, "nabla")
+
+
+class TEXTURE_PT_voronoi_feature_weights(TextureTypePanel, Panel):
+ bl_label = "Feature Weights"
+ bl_parent_id = "TEXTURE_PT_voronoi"
+ tex_type = 'VORONOI'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+
+ tex = context.texture
+
+ col = flow.column(align=True)
+ col.prop(tex, "weight_1", text="First", slider=True)
+ col.prop(tex, "weight_2", text="Second", slider=True)
+
+ sub = flow.column(align=True)
+ sub.prop(tex, "weight_3", text="Third", slider=True)
+ sub.prop(tex, "weight_4", text="Fourth", slider=True)
class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
bl_label = "Distorted Noise"
tex_type = 'DISTORTED_NOISE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
tex = context.texture
- layout.prop(tex, "noise_distortion")
- layout.prop(tex, "noise_basis", text="Basis")
+ col = flow.column()
+ col.prop(tex, "noise_basis", text="Noise Basis")
- split = layout.split()
+ col.separator()
- col = split.column()
- col.prop(tex, "distortion", text="Distortion")
- col.prop(tex, "noise_scale", text="Size")
+ col.prop(tex, "noise_distortion", text="Distortion")
- split.prop(tex, "nabla")
+ col.separator()
+
+ col = flow.column()
+ col.prop(tex, "distortion", text="Amount")
+ col.prop(tex, "noise_scale", text="Size")
+ col.prop(tex, "nabla")
class TextureSlotPanel(TextureButtonsPanel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -579,7 +702,7 @@ class TextureSlotPanel(TextureButtonsPanel):
class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
bl_label = "Mapping"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -595,69 +718,65 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
idblock = context_tex_datablock(context)
tex = context.texture_slot
- if not isinstance(idblock, Brush):
- split = layout.split(percentage=0.3)
- col = split.column()
- col.label(text="Coordinates:")
- col = split.column()
- col.prop(tex, "texture_coords", text="")
+ if isinstance(idblock, Brush):
+ if context.sculpt_object or context.image_paint_object:
+ brush_texture_settings(layout, idblock, context.sculpt_object)
+ else:
+ col = flow.column()
- if tex.texture_coords == 'ORCO':
- """
- ob = context.object
- if ob and ob.type == 'MESH':
- split = layout.split(percentage=0.3)
- split.label(text="Mesh:")
- split.prop(ob.data, "texco_mesh", text="")
- """
- elif tex.texture_coords == 'UV':
- split = layout.split(percentage=0.3)
- split.label(text="Map:")
+ col.prop(tex, "texture_coords", text="Coordinates")
+
+ # Note: the ORCO case used to call ob.data, "texco_mesh" prop.
+ if tex.texture_coords == 'UV':
ob = context.object
+
if ob and ob.type == 'MESH':
- split.prop_search(tex, "uv_layer", ob.data, "uv_layers", text="")
+ # Note: TODO prop_search doesn't align on the right.
+ row = col.row(align=True)
+ row.prop_search(tex, "uv_layer", ob.data, "uv_layers", text="Map")
+ row.label(text="", icon='BLANK1')
else:
- split.prop(tex, "uv_layer", text="")
+ col.prop(tex, "uv_layer", text="Map")
elif tex.texture_coords == 'OBJECT':
- split = layout.split(percentage=0.3)
- split.label(text="Object:")
- split.prop(tex, "object", text="")
+ col.prop(tex, "object", text="Object")
elif tex.texture_coords == 'ALONG_STROKE':
- split = layout.split(percentage=0.3)
- split.label(text="Use Tips:")
- split.prop(tex, "use_tips", text="")
+ col.prop(tex, "use_tips", text="Use Tips")
+
+ col.separator()
- if isinstance(idblock, Brush):
- if context.sculpt_object or context.image_paint_object:
- brush_texture_settings(layout, idblock, context.sculpt_object)
- else:
if isinstance(idblock, FreestyleLineStyle):
- split = layout.split(percentage=0.3)
- split.label(text="Projection:")
- split.prop(tex, "mapping", text="")
+ col = flow.column()
+ col.prop(tex, "mapping", text="Projection")
+
+ col.separator()
+
+ col = flow.column()
+ col.prop(tex, "mapping_x", text="Mapping X")
+ col.prop(tex, "mapping_y", text="Y")
+ col.prop(tex, "mapping_z", text="Z")
+
+ col.separator()
- split = layout.split(percentage=0.3)
- split.separator()
- row = split.row()
- row.prop(tex, "mapping_x", text="")
- row.prop(tex, "mapping_y", text="")
- row.prop(tex, "mapping_z", text="")
+ col = flow.column(align=True)
+ col.column().prop(tex, "offset")
- row = layout.row()
- row.column().prop(tex, "offset")
- row.column().prop(tex, "scale")
+ col = flow.column(align=True)
+ col.column().prop(tex, "scale")
class TEXTURE_PT_influence(TextureSlotPanel, Panel):
bl_label = "Influence"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -672,111 +791,130 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
return (engine in cls.COMPAT_ENGINES)
def draw(self, context):
-
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
idblock = context_tex_datablock(context)
-
tex = context.texture_slot
def factor_but(layout, toggle, factor, name):
row = layout.row(align=True)
- row.prop(tex, toggle, text="")
+ row.active = getattr(tex, toggle)
+
+ row.prop(tex, factor, text=name, slider=True)
sub = row.row(align=True)
- sub.active = getattr(tex, toggle)
- sub.prop(tex, factor, text=name, slider=True)
+ sub.prop(tex, toggle, text="")
return sub # XXX, temp. use_map_normal needs to override.
if isinstance(idblock, ParticleSettings):
- split = layout.split()
-
- col = split.column()
- col.label(text="General:")
- factor_but(col, "use_map_time", "time_factor", "Time")
+ col = flow.column()
+ factor_but(col, "use_map_time", "time_factor", "General Time")
factor_but(col, "use_map_life", "life_factor", "Lifetime")
factor_but(col, "use_map_density", "density_factor", "Density")
factor_but(col, "use_map_size", "size_factor", "Size")
- col = split.column()
- col.label(text="Physics:")
- factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
+ col.separator()
+
+ col = flow.column()
+ factor_but(col, "use_map_velocity", "velocity_factor", "Physics Velocity")
factor_but(col, "use_map_damp", "damp_factor", "Damp")
factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
factor_but(col, "use_map_field", "field_factor", "Force Fields")
- layout.label(text="Hair:")
-
- split = layout.split()
+ col.separator()
- col = split.column()
- factor_but(col, "use_map_length", "length_factor", "Length")
+ col = flow.column()
+ factor_but(col, "use_map_length", "length_factor", "Hair Length")
factor_but(col, "use_map_clump", "clump_factor", "Clump")
factor_but(col, "use_map_twist", "twist_factor", "Twist")
- col = split.column()
+ col = flow.column()
factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude")
factor_but(col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency")
factor_but(col, "use_map_rough", "rough_factor", "Rough")
elif isinstance(idblock, FreestyleLineStyle):
- split = layout.split()
-
- col = split.column()
+ col = flow.column()
factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
- col = split.column()
factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
- layout.separator()
-
if not isinstance(idblock, ParticleSettings):
- split = layout.split()
+ col = flow.column()
- col = split.column()
col.prop(tex, "blend_type", text="Blend")
col.prop(tex, "use_rgb_to_intensity")
+
# color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
col.prop(tex, "color", text="")
- col = split.column()
+ col = flow.column()
col.prop(tex, "invert", text="Negative")
col.prop(tex, "use_stencil")
-class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
- bl_label = "Colors"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
-
+class TextureColorsPoll:
@classmethod
def poll(cls, context):
tex = context.texture
return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.engine in cls.COMPAT_ENGINES)
+
+class TEXTURE_PT_colors(TextureButtonsPanel, TextureColorsPoll, Panel):
+ bl_label = "Colors"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
tex = context.texture
- col = layout.column()
- sub = col.column(align=True)
- sub.prop(tex, "factor_red", text="Multiply R")
- sub.prop(tex, "factor_green", text="G")
- sub.prop(tex, "factor_blue", text="B")
+ col = flow.column()
+ col.prop(tex, "use_clamp", text="Clamp")
+ col = flow.column(align=True)
+ col.prop(tex, "factor_red", text="Multiply R")
+ col.prop(tex, "factor_green", text="G")
+ col.prop(tex, "factor_blue", text="B")
+
+ col.separator()
+
+ col = flow.column()
col.prop(tex, "intensity")
col.prop(tex, "contrast")
col.prop(tex, "saturation")
- col.prop(tex, "use_clamp", text="Clamp")
- col.prop(tex, "use_color_ramp", text="Ramp")
- if tex.use_color_ramp:
- layout.use_property_split = False
+
+class TEXTURE_PT_colors_ramp(TextureButtonsPanel, TextureColorsPoll, Panel):
+ bl_label = "Color Ramp"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'TEXTURE_PT_colors'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ def draw_header(self, context):
+ tex = context.texture
+ self.layout.prop(tex, "use_color_ramp", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ tex = context.texture
+
+ # Note: TODO after creation of a new texture, the template_color_ramp will be blank.
+ # Possibly needs to be fixed in the template itself.
+ is_active = bool(tex and tex.use_color_ramp)
+ if is_active:
layout.template_color_ramp(tex, "color_ramp", expand=True)
+ else:
+ layout.alignment = 'RIGHT'
+ layout.label("Please enable the Color Ramp first")
class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "texture"
_property_type = Texture
@@ -792,8 +930,6 @@ classes = (
TEXTURE_PT_context,
TEXTURE_PT_node,
TEXTURE_PT_node_mapping,
- TEXTURE_PT_mapping,
- TEXTURE_PT_influence,
TEXTURE_PT_clouds,
TEXTURE_PT_wood,
TEXTURE_PT_marble,
@@ -801,13 +937,19 @@ classes = (
TEXTURE_PT_blend,
TEXTURE_PT_stucci,
TEXTURE_PT_image,
+ TEXTURE_PT_image_settings,
TEXTURE_PT_image_alpha,
- TEXTURE_PT_image_sampling,
TEXTURE_PT_image_mapping,
+ TEXTURE_PT_image_mapping_crop,
+ TEXTURE_PT_image_sampling,
TEXTURE_PT_musgrave,
TEXTURE_PT_voronoi,
+ TEXTURE_PT_voronoi_feature_weights,
TEXTURE_PT_distortednoise,
+ TEXTURE_PT_influence,
+ TEXTURE_PT_mapping,
TEXTURE_PT_colors,
+ TEXTURE_PT_colors_ramp,
TEXTURE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 05dc15216a2..f96bf041311 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -34,7 +34,7 @@ class ViewLayerButtonsPanel:
class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
bl_label = "View Layer"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index b6ea8054b0c..7395fa13d9a 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -37,7 +37,7 @@ class WorldButtonsPanel:
class WORLD_PT_context_world(WorldButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
@classmethod
def poll(cls, context):
@@ -83,14 +83,13 @@ class EEVEE_WORLD_PT_mist(WorldButtonsPanel, Panel):
class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "world"
_property_type = bpy.types.World
class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
bl_label = "Surface"
- bl_context = "world"
COMPAT_ENGINES = {'BLENDER_EEVEE'}
@classmethod
@@ -119,13 +118,29 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
else:
layout.label(text="No output node")
else:
- layout.prop(world, "horizon_color", text="Color")
+ layout.prop(world, "color")
+
+
+class WORLD_PT_viewport_display(WorldButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.world
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ world = context.world
+ layout.prop(world, "color")
classes = (
WORLD_PT_context_world,
EEVEE_WORLD_PT_surface,
EEVEE_WORLD_PT_mist,
+ WORLD_PT_viewport_display,
WORLD_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 23c3e97ac9a..1564204c613 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -24,12 +24,7 @@ from bpy.app.translations import pgettext_iface as iface_
from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
)
@@ -1154,39 +1149,10 @@ class CLIP_PT_grease_pencil(GreasePencilDataPanel, CLIP_PT_clip_view_panel, Pane
# But, this should only be visible in "clip" view
-# Grease Pencil palette colors
-class CLIP_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, CLIP_PT_clip_view_panel, Panel):
- bl_space_type = 'CLIP_EDITOR'
- bl_region_type = 'UI'
- bl_options = {'DEFAULT_CLOSED'}
-
- # NOTE: this is just a wrapper around the generic GP Panel
- # But, this should only be visible in "clip" view
-
-
# Grease Pencil drawing tools
class CLIP_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil stroke editing tools
-class CLIP_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil stroke sculpting tools
-class CLIP_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil drawing brushes
-class CLIP_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil drawing curves
-class CLIP_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'TOOLS'
class CLIP_MT_view(Menu):
@@ -1515,12 +1481,7 @@ classes = (
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,
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 9d903829bbb..a85dd591b2f 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -56,6 +56,8 @@ class FILEBROWSER_HT_header(Header):
layout.separator_spacer()
+ layout.template_running_jobs()
+
if params:
layout.prop(params, "use_filter", text="", icon='FILTER')
@@ -86,8 +88,6 @@ class FILEBROWSER_HT_header(Header):
row.separator()
row.prop(params, "filter_search", text="", icon='VIEWZOOM')
- layout.template_running_jobs()
-
class FILEBROWSER_UL_dir(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 1303e46ab6c..7a1d4117451 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -28,12 +28,7 @@ from .properties_paint_common import (
)
from .properties_grease_pencil_common import (
GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
)
from bpy.app.translations import pgettext_iface as iface_
@@ -1346,38 +1341,12 @@ class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
# NOTE: this is just a wrapper around the generic GP Panel
-
-# Grease Pencil palette colors
-class IMAGE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
# Grease Pencil drawing tools
-class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil stroke editing tools
-class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil stroke sculpting tools
-class IMAGE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-# Grease Pencil drawing brushes
-class IMAGE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil drawing curves
-class IMAGE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
+class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'TOOLS'
classes = (
@@ -1430,12 +1399,7 @@ classes = (
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.
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 9d8c14ba9c3..43a124cd48f 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -24,13 +24,8 @@ from bpy.app.translations import pgettext_iface as iface_
from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
- GreasePencilToolsPanel
+ GreasePencilToolsPanel,
)
@@ -364,7 +359,6 @@ class NODE_PT_active_node_generic(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_label = "Node"
-# bl_options = {'HIDE_HEADER'}
@classmethod
def poll(cls, context):
@@ -383,6 +377,7 @@ class NODE_PT_active_node_color(Panel):
bl_region_type = 'UI'
bl_label = "Color"
bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'NODE_PT_active_node_generic'
@classmethod
def poll(cls, context):
@@ -410,6 +405,8 @@ class NODE_PT_active_node_properties(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_label = "Properties"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'NODE_PT_active_node_generic'
@classmethod
def poll(cls, context):
@@ -453,18 +450,22 @@ class NODE_PT_backdrop(Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
snode = context.space_data
layout.active = snode.show_backdrop
- layout.prop(snode, "backdrop_channels", text="")
- layout.prop(snode, "backdrop_zoom", text="Zoom")
- col = layout.column(align=True)
- col.label(text="Offset:")
- col.prop(snode, "backdrop_offset", text="")
- col.operator("node.backimage_move", text="Move")
+ col = layout.column()
- layout.operator("node.backimage_fit", text="Fit")
+ col.prop(snode, "backdrop_channels", text="Channels")
+ col.prop(snode, "backdrop_zoom", text="Zoom")
+
+ col.prop(snode, "backdrop_offset", text="Offset")
+
+ col.separator()
+
+ col.operator("node.backimage_move", text="Move")
+ col.operator("node.backimage_fit", text="Fit")
class NODE_PT_quality(bpy.types.Panel):
@@ -479,6 +480,7 @@ class NODE_PT_quality(bpy.types.Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
snode = context.space_data
tree = snode.node_tree
@@ -522,19 +524,7 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
- @classmethod
- def poll(cls, context):
- snode = context.space_data
- return snode is not None and snode.node_tree is not None
-
-
-# Grease Pencil palette colors
-class NODE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
# NOTE: this is just a wrapper around the generic GP Panel
@@ -563,31 +553,6 @@ class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_region_type = 'TOOLS'
-# Grease Pencil stroke editing tools
-class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-
-# Grease Pencil stroke sculpting tools
-class NODE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-# Grease Pencil drawing brushes
-
-
-class NODE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-# Grease Pencil drawing curves
-
-
-class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
# -----------------------------
@@ -612,13 +577,8 @@ classes = (
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,
)
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 8f722c4d3ce..20ef5ae0c53 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -142,8 +142,15 @@ class OUTLINER_MT_collection_view_layer(Menu):
space = context.space_data
- layout.operator("outliner.collection_exclude_set", text="Exclude")
- layout.operator("outliner.collection_include_set", text="Include")
+ layout.operator("outliner.collection_exclude_set")
+ layout.operator("outliner.collection_exclude_clear")
+
+ if context.engine == 'CYCLES':
+ layout.operator("outliner.collection_indirect_only_set")
+ layout.operator("outliner.collection_indirect_only_clear")
+
+ layout.operator("outliner.collection_holdout_set")
+ layout.operator("outliner.collection_holdout_clear")
class OUTLINER_MT_collection(Menu):
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 0bdfcc39ed9..84ae59772b6 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -22,7 +22,6 @@ from bpy.types import Header, Menu, Panel
from rna_prop_ui import PropertyPanel
from .properties_grease_pencil_common import (
GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
GreasePencilToolsPanel,
)
from bpy.app.translations import pgettext_iface as iface_
@@ -343,9 +342,21 @@ class SEQUENCER_MT_add(Menu):
layout.operator("sequencer.image_strip_add", text="Image")
layout.operator("sequencer.sound_strip_add", text="Sound")
+ layout.menu("SEQUENCER_MT_add_generate")
layout.menu("SEQUENCER_MT_add_effect")
+class SEQUENCER_MT_add_generate(Menu):
+ bl_label = "Generate"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
+ layout.operator("sequencer.effect_strip_add", text="Text").type = 'TEXT'
+
+
class SEQUENCER_MT_add_effect(Menu):
bl_label = "Effect Strip"
@@ -365,10 +376,8 @@ class SEQUENCER_MT_add_effect(Menu):
layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
- layout.operator("sequencer.effect_strip_add", text="Text").type = 'TEXT'
layout.operator("sequencer.effect_strip_add", text="Color Mix").type = 'COLORMIX'
layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
- layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
@@ -1271,14 +1280,6 @@ class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Ou
# But, it should only show up when there are images in the preview region
-class SEQUENCER_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, SequencerButtonsPanel_Output, Panel):
- bl_space_type = 'SEQUENCE_EDITOR'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
- # But, it should only show up when there are images in the preview region
-
-
class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel):
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -1289,7 +1290,7 @@ class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsP
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "scene.sequence_editor.active_strip"
_property_type = (bpy.types.Sequence,)
bl_category = "Strip"
@@ -1304,6 +1305,7 @@ classes = (
SEQUENCER_MT_marker,
SEQUENCER_MT_frame,
SEQUENCER_MT_add,
+ SEQUENCER_MT_add_generate,
SEQUENCER_MT_add_effect,
SEQUENCER_MT_strip,
SEQUENCER_MT_strip_transform,
@@ -1322,7 +1324,6 @@ classes = (
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,
)
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 4c954874f0d..91ded3e4456 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -74,7 +74,7 @@ ToolDef = namedtuple(
"icon",
# An optional cursor to use when this tool is active.
"cursor",
- # An optional manipulator group to activate when the tool is set or None for no widget.
+ # An optional gizmo group to activate when the tool is set or None for no gizmo.
"widget",
# Optional keymap for tool, either:
# - A function that populates a keymaps passed in as an argument.
@@ -275,6 +275,7 @@ class ToolSelectPanelHelper:
mode = context.mode
tool = context.workspace.tools.from_space_view3d_mode(mode, create)
if tool is not None:
+ tool.refresh_from_context()
return tool
elif space_type == 'IMAGE_EDITOR':
space_data = context.space_data
@@ -282,6 +283,7 @@ class ToolSelectPanelHelper:
mode = space_data.mode
tool = context.workspace.tools.from_space_image_mode(mode, create)
if tool is not None:
+ tool.refresh_from_context()
return tool
return None
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index dbab7c7e037..e1ecba1550a 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -24,6 +24,7 @@
# For now keep this in a single file since it's an area that may change,
# so avoid making changes all over the place.
+import bpy
from bpy.types import Panel
from .space_toolsystem_common import (
@@ -41,19 +42,68 @@ def generate_from_brushes_ex(
):
# Categories
brush_categories = {}
- for brush in context.blend_data.brushes:
- if getattr(brush, brush_test_attr):
- category = getattr(brush, brush_category_attr)
- name = brush.name
- brush_categories.setdefault(category, []).append(
- ToolDef.from_dict(
- dict(
- text=name,
- icon=icon_prefix + category.lower(),
- data_block=name,
+ if context.mode != 'GPENCIL_PAINT':
+ for brush in context.blend_data.brushes:
+ if getattr(brush, brush_test_attr) and brush.gpencil_settings is None:
+ category = getattr(brush, brush_category_attr)
+ name = brush.name
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=name,
+ icon=icon_prefix + category.lower(),
+ data_block=name,
+ )
)
)
- )
+ else:
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_paint.draw_settings_common(context, layout, tool)
+
+ for brush_type in brush_category_layout:
+ for brush in context.blend_data.brushes:
+ if getattr(brush, brush_test_attr) and brush.gpencil_settings.gp_icon == brush_type[0]:
+ category = brush_type[0]
+ name = brush.name
+ text = name
+
+ # XXX, disabled since changing the brush needs to sync back to the tool.
+ """
+ # rename default brushes for tool bar
+ if name.startswith("Draw "):
+ text = name.replace("Draw ", "")
+ elif name.startswith("Eraser "):
+ text = name.replace("Eraser ", "")
+ elif name.startswith("Fill "):
+ text = name.replace(" Area", "")
+ else:
+ text = name
+ """
+ # Define icon.
+ icon_name = {
+ 'PENCIL': 'draw_pencil',
+ 'PEN': 'draw_pen',
+ 'INK': 'draw_ink',
+ 'INKNOISE': 'draw_noise',
+ 'BLOCK': 'draw_block',
+ 'MARKER': 'draw_marker',
+ 'FILL': 'draw_fill',
+ 'SOFT': 'draw.eraser_soft',
+ 'HARD': 'draw.eraser_hard',
+ 'STROKE': 'draw.eraser_stroke',
+ }[category]
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=text,
+ icon=icon_prefix + icon_name,
+ data_block=name,
+ widget=None,
+ operator="gpencil.draw",
+ draw_settings=draw_settings,
+ )
+ )
+ )
def tools_from_brush_group(groups):
assert(type(groups) is tuple)
@@ -61,6 +111,7 @@ def generate_from_brushes_ex(
tool_defs = tuple(brush_categories.pop(groups[0], ()))
else:
tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
+
if len(tool_defs) > 1:
return (tool_defs,)
else:
@@ -80,6 +131,28 @@ def generate_from_brushes_ex(
return tool_defs
+def generate_from_enum_ex(
+ context, *,
+ icon_prefix,
+ data,
+ attr,
+):
+ tool_defs = []
+ for enum in data.rna_type.properties[attr].enum_items_static:
+ name = enum.name
+ identifier = enum.identifier
+ tool_defs.append(
+ ToolDef.from_dict(
+ dict(
+ text=name,
+ icon=icon_prefix + identifier.lower(),
+ data_block=identifier,
+ )
+ )
+ )
+ return tuple(tool_defs)
+
+
class _defs_view3d_generic:
@ToolDef.from_fn
def cursor():
@@ -118,55 +191,157 @@ class _defs_view3d_generic:
return dict(
text="Ruler",
icon="ops.view3d.ruler",
- widget="VIEW3D_WGT_ruler",
+ widget="VIEW3D_GGT_ruler",
keymap=(
("view3d.ruler_add", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
),
)
+class _defs_annotate:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ts = context.tool_settings
+
+ space_type = tool.space_type
+ if space_type == 'VIEW_3D':
+ layout.separator()
+
+ row = layout.row(align=True)
+ row.prop(ts, "annotation_stroke_placement_view3d", text="Placement")
+ if ts.gpencil_stroke_placement_view3d == 'CURSOR':
+ row.prop(ts.gpencil_sculpt, "lockaxis")
+ elif ts.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
+ row.prop(ts, "use_gpencil_stroke_endpoints")
+
+ @ToolDef.from_fn
+ def scribble():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Annotate",
+ icon="ops.gpencil.draw",
+ cursor='PAINT_BRUSH',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def line():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw Line",
+ icon="ops.gpencil.draw.line",
+ cursor='CROSSHAIR',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW_STRAIGHT', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def poly():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw Polygon",
+ icon="ops.gpencil.draw.poly",
+ cursor='CROSSHAIR',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW_POLY', wait_for_input=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def eraser():
+ def draw_settings(context, layout, tool):
+ # TODO: Move this setting to toolsettings
+ user_prefs = context.user_preferences
+ layout.prop(user_prefs.edit, "grease_pencil_eraser_radius", text="Radius")
+
+ return dict(
+ text="Eraser",
+ icon="ops.gpencil.draw.eraser",
+ cursor='CROSSHAIR', # XXX: Always show brush circle when enabled
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='ERASER', wait_for_input=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
class _defs_transform:
@ToolDef.from_fn
def translate():
+ def draw_settings(context, layout, tool):
+ tool_settings = context.tool_settings
+ layout.prop(tool_settings, "use_gizmo_apron")
+
return dict(
text="Grab",
# cursor='SCROLL_XY',
icon="ops.transform.translate",
- widget="TRANSFORM_WGT_gizmo",
+ widget="TRANSFORM_GGT_gizmo",
operator="transform.translate",
# TODO, implement as optional fallback gizmo
# keymap=(
# ("transform.translate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
# ),
+ draw_settings=draw_settings,
)
@ToolDef.from_fn
def rotate():
+ def draw_settings(context, layout, tool):
+ tool_settings = context.tool_settings
+ layout.prop(tool_settings, "use_gizmo_apron")
+
return dict(
text="Rotate",
# cursor='SCROLL_XY',
icon="ops.transform.rotate",
- widget="TRANSFORM_WGT_gizmo",
+ widget="TRANSFORM_GGT_gizmo",
operator="transform.rotate",
# TODO, implement as optional fallback gizmo
# keymap=(
# ("transform.rotate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
# ),
+ draw_settings=draw_settings,
)
@ToolDef.from_fn
def scale():
+ def draw_settings(context, layout, tool):
+ tool_settings = context.tool_settings
+ layout.prop(tool_settings, "use_gizmo_apron")
+
return dict(
text="Scale",
# cursor='SCROLL_XY',
icon="ops.transform.resize",
- widget="TRANSFORM_WGT_gizmo",
+ widget="TRANSFORM_GGT_gizmo",
operator="transform.resize",
# TODO, implement as optional fallback gizmo
# keymap=(
# ("transform.resize", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
# ),
+ draw_settings=draw_settings,
)
@ToolDef.from_fn
@@ -174,7 +349,7 @@ class _defs_transform:
return dict(
text="Scale Cage",
icon="ops.transform.resize.cage",
- widget="VIEW3D_WGT_xform_cage",
+ widget="VIEW3D_GGT_xform_cage",
operator="transform.resize",
)
@@ -182,12 +357,13 @@ class _defs_transform:
def transform():
def draw_settings(context, layout, tool):
tool_settings = context.tool_settings
- layout.prop(tool_settings, "use_gizmo")
+ layout.prop(tool_settings, "use_gizmo_apron")
+ layout.prop(tool_settings, "use_gizmo_mode")
return dict(
text="Transform",
icon="ops.transform.transform",
- widget="TRANSFORM_WGT_gizmo",
+ widget="TRANSFORM_GGT_gizmo",
# No keymap default action, only for gizmo!
draw_settings=draw_settings,
)
@@ -462,7 +638,7 @@ class _defs_edit_mesh:
return dict(
text="Extrude Region",
icon="ops.mesh.extrude_region_move",
- widget="MESH_WGT_extrude",
+ widget="MESH_GGT_extrude",
operator="view3d.edit_mesh_extrude_move_normal",
keymap=(
("mesh.extrude_context_move", dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
@@ -684,6 +860,18 @@ class _defs_pose:
)
+class _defs_particle:
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_enum_ex(
+ context,
+ icon_prefix="brush.particle.",
+ data=context.tool_settings.particle_edit,
+ attr="tool",
+ )
+
+
class _defs_sculpt:
@staticmethod
@@ -866,6 +1054,331 @@ class _defs_uv_select:
)
+class _defs_gpencil_paint:
+ @classmethod
+ def draw_color_selector(cls, context, layout):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ ts = context.tool_settings
+ row = layout.row(align=True)
+ row.prop(ts, "use_gpencil_thumbnail_list", text="", icon="IMGDISPLAY")
+ if ts.use_gpencil_thumbnail_list is False:
+ row.template_ID(gp_settings, "material", live_icon=True)
+ else:
+ row.template_greasepencil_color(gp_settings, "material", rows=3, cols=8, scale=0.8)
+
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_PAINT':
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ tool_settings = context.tool_settings
+
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ row = layout.row()
+ row.prop(brush, "size", text="Radius")
+ elif gp_settings.gpencil_brush_type == 'FILL':
+ row = layout.row()
+ row.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
+ row.prop(brush, "size", text="Thickness")
+ row.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
+
+ _defs_gpencil_paint.draw_color_selector(context, layout)
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "gpencil_fill_draw_mode", text="")
+ row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
+
+ else: # bgpsettings.gpencil_brush_type == 'DRAW':
+ row = layout.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ _defs_gpencil_paint.draw_color_selector(context, layout)
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.gpencil.",
+ brush_test_attr="use_paint_grease_pencil",
+ brush_category_attr="grease_pencil_tool",
+ brush_category_layout=(
+ ('PENCIL',),
+ ('PEN',),
+ ('INK',),
+ ('INKNOISE',),
+ ('BLOCK',),
+ ('MARKER',),
+ ('FILL',),
+ ('SOFT',),
+ ('HARD',),
+ ('STROKE',),
+ )
+ )
+
+
+class _defs_gpencil_edit:
+ @ToolDef.from_fn
+ def bend():
+ return dict(
+ text="Bend",
+ icon="ops.gpencil.edit_bend",
+ widget=None,
+ keymap=(
+ ("transform.bend",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def mirror():
+ return dict(
+ text="Mirror",
+ icon="ops.gpencil.edit_mirror",
+ widget=None,
+ keymap=(
+ ("transform.mirror",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def shear():
+ return dict(
+ text="Shear",
+ icon="ops.gpencil.edit_shear",
+ widget=None,
+ keymap=(
+ ("transform.shear",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def tosphere():
+ return dict(
+ text="To Sphere",
+ icon="ops.gpencil.edit_to_sphere",
+ widget=None,
+ keymap=(
+ ("transform.tosphere",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+
+class _defs_gpencil_sculpt:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_SCULPT':
+ ts = context.tool_settings
+ settings = ts.gpencil_sculpt
+ brush = settings.brush
+
+ layout.prop(brush, "size", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+ row.separator()
+ row.prop(ts.gpencil_sculpt, "use_select_mask", text="")
+
+ @ToolDef.from_fn
+ def smooth():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Smooth",
+ icon="ops.gpencil.sculpt_smooth",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='SMOOTH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def thickness():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Thickness",
+ icon="ops.gpencil.sculpt_thickness",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='THICKNESS', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def strength():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Strength",
+ icon="ops.gpencil.sculpt_strength",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='STRENGTH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def grab():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Grab",
+ icon="ops.gpencil.sculpt_grab",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='GRAB', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def push():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Push",
+ icon="ops.gpencil.sculpt_push",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='PUSH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def twist():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Twist",
+ icon="ops.gpencil.sculpt_twist",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='TWIST', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def pinch():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Pinch",
+ icon="ops.gpencil.sculpt_pinch",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='PINCH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def randomize():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Randomize",
+ icon="ops.gpencil.sculpt_randomize",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='RANDOMIZE', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def clone():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Clone",
+ icon="ops.gpencil.sculpt_clone",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='CLONE', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
+class _defs_gpencil_weight:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_WEIGHT':
+ settings = context.tool_settings.gpencil_sculpt
+ brush = settings.brush
+
+ layout.prop(brush, "size", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+
+ @ToolDef.from_fn
+ def paint():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_weight.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw",
+ icon="ops.gpencil.sculpt_weight",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='WEIGHT', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
@@ -951,8 +1464,6 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_transform.scale,
_defs_transform.scale_cage,
),
- None,
- _defs_view3d_generic.ruler,
)
_tools_select = (
@@ -963,6 +1474,16 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
),
)
+ _tools_annotate = (
+ (
+ _defs_annotate.scribble,
+ _defs_annotate.line,
+ _defs_annotate.poly,
+ _defs_annotate.eraser,
+ ),
+ _defs_view3d_generic.ruler,
+ )
+
_tools = {
None: [
_defs_view3d_generic.cursor,
@@ -972,21 +1493,27 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
*_tools_select,
None,
*_tools_transform,
+ None,
+ *_tools_annotate,
],
'POSE': [
*_tools_select,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
(
_defs_pose.breakdown,
_defs_pose.push,
_defs_pose.relax,
- )
+ ),
],
'EDIT_ARMATURE': [
*_tools_select,
None,
*_tools_transform,
+ None,
+ *_tools_annotate,
_defs_edit_armature.roll,
(
_defs_edit_armature.bone_size,
@@ -996,13 +1523,15 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
(
_defs_edit_armature.extrude,
_defs_edit_armature.extrude_cursor,
- )
+ ),
],
'EDIT_MESH': [
*_tools_select,
None,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
_defs_edit_mesh.cube_add,
None,
(
@@ -1047,13 +1576,13 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
_defs_edit_curve.draw,
_defs_edit_curve.extrude_cursor,
],
'PARTICLE': [
- # TODO(campbell): use cursor click tool to allow paint tools to run,
- # we need to integrate particle system tools properly.
- _defs_view3d_generic.cursor_click,
+ _defs_particle.generate_from_brushes,
],
'SCULPT': [
_defs_sculpt.generate_from_brushes,
@@ -1075,6 +1604,33 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
_defs_weight_paint.gradient,
],
+ 'GPENCIL_PAINT': [
+ _defs_gpencil_paint.generate_from_brushes,
+ ],
+ 'GPENCIL_EDIT': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ None,
+ _defs_gpencil_edit.bend,
+ _defs_gpencil_edit.mirror,
+ _defs_gpencil_edit.shear,
+ _defs_gpencil_edit.tosphere,
+ ],
+ 'GPENCIL_SCULPT': [
+ _defs_gpencil_sculpt.smooth,
+ _defs_gpencil_sculpt.thickness,
+ _defs_gpencil_sculpt.strength,
+ _defs_gpencil_sculpt.grab,
+ _defs_gpencil_sculpt.push,
+ _defs_gpencil_sculpt.twist,
+ _defs_gpencil_sculpt.pinch,
+ _defs_gpencil_sculpt.randomize,
+ _defs_gpencil_sculpt.clone,
+ ],
+ 'GPENCIL_WEIGHT': [
+ _defs_gpencil_weight.paint,
+ ],
}
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 96ef2e51e60..a417ef856f9 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -128,6 +128,8 @@ class TOPBAR_HT_lower_bar(Header):
pass
elif mode == 'PARTICLE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'GPENCIL_PAINT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_paint", category="")
def draw_center(self, context):
pass
@@ -165,6 +167,15 @@ class TOPBAR_HT_lower_bar(Header):
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".particlemode", category="")
elif mode == 'OBJECT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".objectmode", category="")
+ elif mode == 'GPENCIL_PAINT':
+ layout.prop(context.tool_settings, "gpencil_stroke_placement_view3d", text='')
+ if context.tool_settings.gpencil_stroke_placement_view3d in ('ORIGIN', 'CURSOR'):
+ layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
+ layout.prop(context.tool_settings, "use_gpencil_draw_onback", text="", icon='ORTHO')
+ layout.prop(context.tool_settings, "use_gpencil_additive_drawing", text="", icon='FREEZE')
+
+ elif mode == 'GPENCIL_SCULPT':
+ layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
class _draw_left_context_mode:
@@ -213,6 +224,27 @@ class _draw_left_context_mode:
UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True, text="Radius")
UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True, text="Strength")
+ def PARTICLE(context, layout):
+ # See: 'VIEW3D_PT_tools_brush', basically a duplicate
+ settings = context.tool_settings.particle_edit
+ brush = settings.brush
+ tool = settings.tool
+ if tool != 'NONE':
+ layout.prop(brush, "size", slider=True)
+ if tool == 'ADD':
+ layout.prop(brush, "count")
+ else:
+ layout.prop(brush, "strength", slider=True)
+
+ if tool == 'ADD':
+ layout.prop(settings, "use_default_interpolate")
+ layout.prop(brush, "steps", slider=True)
+ layout.prop(settings, "default_key_count", slider=True)
+ elif tool == 'LENGTH':
+ layout.row().prop(brush, "length_mode", expand=True)
+ elif tool == 'PUFF':
+ layout.row().prop(brush, "puff_mode", expand=True)
+ layout.prop(brush, "use_puff_volume")
class INFO_MT_editor_menus(Menu):
bl_idname = "INFO_MT_editor_menus"
@@ -265,8 +297,8 @@ class INFO_MT_file(Menu):
layout.separator()
layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.link", text="Link", icon='LINK_BLEND')
- layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
+ layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
layout.menu("INFO_MT_file_previews")
layout.separator()
@@ -383,26 +415,20 @@ class INFO_MT_render(Menu):
props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
props.animation = True
props.use_viewport = True
- layout.operator("sound.mixdown", text="Render Audio", icon='PLAY_AUDIO')
layout.separator()
- layout.prop_menu_enum(rd, "display_mode", text="Display Mode")
- layout.prop(rd, "use_lock_interface", text="Lock Interface")
+ layout.operator("sound.mixdown", text="Render Audio...")
layout.separator()
- props = layout.operator("render.opengl", text="OpenGL Render Image", icon='RENDER_STILL')
- props.view_context = False
- props = layout.operator("render.opengl", text="OpenGL Render Animation", icon='RENDER_ANIMATION')
- props.view_context = False
- props.animation = True
- layout.menu("INFO_MT_opengl_render")
+ layout.operator("render.view_show", text="View Render")
+ layout.operator("render.play_rendered_anim", text="View Animation")
+ layout.prop_menu_enum(rd, "display_mode", text="Display Mode")
layout.separator()
- layout.operator("render.view_show")
- layout.operator("render.play_rendered_anim", icon='PLAY')
+ layout.prop(rd, "use_lock_interface", text="Lock Interface")
class INFO_MT_opengl_render(Menu):
@@ -495,12 +521,25 @@ class INFO_MT_help(Menu):
def draw(self, context):
layout = self.layout
+ show_developer = context.user_preferences.view.show_developer_ui
+
layout.operator(
"wm.url_open", text="Manual", icon='HELP',
).url = "https://docs.blender.org/manual/en/dev/"
+
layout.operator(
- "wm.url_open", text="Release Log", icon='URL',
- ).url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
+ "wm.url_open", text="Report a Bug", icon='URL',
+ ).url = "https://developer.blender.org/maniphest/task/edit/form/1"
+
+ layout.separator()
+
+ layout.operator(
+ "wm.url_open", text="User Communities", icon='URL',
+ ).url = "https://www.blender.org/community/"
+ layout.operator(
+ "wm.url_open", text="Developer Community", icon='URL',
+ ).url = "https://www.blender.org/get-involved/developers/"
+
layout.separator()
layout.operator(
@@ -509,24 +548,22 @@ class INFO_MT_help(Menu):
layout.operator(
"wm.url_open", text="Blender Store", icon='URL',
).url = "https://store.blender.org"
+
layout.operator(
- "wm.url_open", text="Developer Community", icon='URL',
- ).url = "https://www.blender.org/get-involved/"
- layout.operator(
- "wm.url_open", text="User Community", icon='URL',
- ).url = "https://www.blender.org/support/user-community"
- layout.separator()
- layout.operator(
- "wm.url_open", text="Report a Bug", icon='URL',
- ).url = "https://developer.blender.org/maniphest/task/edit/form/1"
+ "wm.url_open", text="Release Notes", icon='URL',
+ ).url = "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
+
layout.separator()
- layout.operator(
- "wm.url_open", text="Python API Reference", icon='URL',
- ).url = bpy.types.WM_OT_doc_view._prefix
+ if show_developer:
+ layout.operator(
+ "wm.url_open", text="Python API Reference", icon='URL',
+ ).url = bpy.types.WM_OT_doc_view._prefix
+
+ layout.operator("wm.operator_cheat_sheet", icon='TEXT')
+
+ layout.operator("wm.sysinfo")
- layout.operator("wm.operator_cheat_sheet", icon='TEXT')
- layout.operator("wm.sysinfo", icon='TEXT')
layout.separator()
layout.operator("wm.splash", icon='BLENDER')
@@ -539,8 +576,13 @@ class TOPBAR_MT_file_specials(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.link", text="Link", icon='LINK_BLEND')
- layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.operator("wm.read_homefile", text="New", icon='NEW')
+ layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
+
+ layout.separator()
+
+ layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
+ layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
layout.separator()
@@ -589,7 +631,6 @@ classes = (
INFO_MT_edit,
INFO_MT_game,
INFO_MT_render,
- INFO_MT_opengl_render,
INFO_MT_window,
INFO_MT_help,
)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index e2bca0b6b33..52d4640806d 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -28,25 +28,6 @@ from bpy.app.translations import pgettext_iface as iface_
from bpy.app.translations import contexts as i18n_contexts
-def opengl_light_buttons(column, light):
- split = column.row()
-
- split.prop(light, "use", text="", icon='OUTLINER_OB_LIGHT' if light.use else 'LIGHT_DATA')
-
- col = split.column()
- col.active = light.use
- row = col.row()
- row.label(text="Diffuse:")
- row.prop(light, "diffuse_color", text="")
- row = col.row()
- row.label(text="Specular:")
- row.prop(light, "specular_color", text="")
-
- col = split.column()
- col.active = light.use
- col.prop(light, "direction", text="")
-
-
class USERPREF_HT_header(Header):
bl_space_type = 'USER_PREFERENCES'
@@ -380,14 +361,16 @@ class USERPREF_PT_edit(Panel):
row.separator()
col = row.column()
- col.label(text="Grease Pencil:")
+ col.label(text="Annotations:")
+ sub = col.row()
+ sub.prop(edit, "grease_pencil_default_color", text="Default Color")
col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
col.separator()
+ col.label(text="Grease Pencil/Annotations:")
+ col.separator()
col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
col.separator()
- col.prop(edit, "grease_pencil_default_color", text="Default Color")
- col.separator()
col.prop(edit, "use_grease_pencil_simplify_stroke", text="Simplify Stroke")
col.separator()
col.separator()
@@ -546,47 +529,34 @@ class USERPREF_PT_system(Panel):
col.prop(system, "gpu_viewport_quality")
col.separator()
+ col.label(text="Grease Pencil Options:")
+ col.prop(system, "gpencil_multi_sample", text="")
+ col.separator()
col.label(text="Text Draw Options:")
col.prop(system, "use_text_antialiasing")
-
- col.separator()
-
- col.label(text="Textures:")
- col.prop(system, "gl_texture_limit", text="Limit Size")
- col.prop(system, "texture_time_out", text="Time Out")
- col.prop(system, "texture_collection_rate", text="Collection Rate")
-
- col.separator()
-
- col.label(text="Images Draw Method:")
- col.prop(system, "image_draw_method", text="")
-
- col.separator()
-
- col.label(text="Sequencer/Clip Editor:")
- # currently disabled in the code
- # col.prop(system, "prefetch_frames")
- col.prop(system, "memory_cache_limit")
+ if system.use_text_antialiasing:
+ col.prop(system, "use_text_hinting")
# 3. Column
column = split.column()
- column.label(text="Solid OpenGL Lights:")
+ column.label(text="Textures:")
+ column.prop(system, "gl_texture_limit", text="Limit Size")
+ column.prop(system, "texture_time_out", text="Time Out")
+ column.prop(system, "texture_collection_rate", text="Collection Rate")
- split = column.split(percentage=0.1)
- split.label()
- split.label(text="Colors:")
- split.label(text="Direction:")
+ column.separator()
- light = system.solid_lights[0]
- opengl_light_buttons(column, light)
+ column.label(text="Images Draw Method:")
+ column.prop(system, "image_draw_method", text="")
- light = system.solid_lights[1]
- opengl_light_buttons(column, light)
+ column.separator()
- light = system.solid_lights[2]
- opengl_light_buttons(column, light)
+ column.label(text="Sequencer/Clip Editor:")
+ # currently disabled in the code
+ # column.prop(system, "prefetch_frames")
+ column.prop(system, "memory_cache_limit")
column.separator()
@@ -1596,13 +1566,6 @@ class StudioLightPanelMixin():
def _get_lights(self, userpref):
return [light for light in userpref.studio_lights if light.is_user_defined and light.orientation == self.sl_orientation]
- def draw_header(self, context):
- layout = self.layout
- row = layout.row()
- userpref = context.user_preferences
- lights = self._get_lights(userpref)
- row.label("({})".format(len(lights)))
-
def draw(self, context):
layout = self.layout
userpref = context.user_preferences
@@ -1640,6 +1603,48 @@ class USERPREF_PT_studiolight_camera(Panel, StudioLightPanelMixin):
sl_orientation = 'CAMERA'
+class USERPREF_PT_studiolight_specular(Panel, StudioLightPanelMixin):
+ bl_label = "Specular Lights"
+ sl_orientation = 'CAMERA'
+
+ @classmethod
+ def poll(cls, context):
+ userpref = context.user_preferences
+ return (userpref.active_section == 'LIGHTS')
+
+ def opengl_light_buttons(self, column, light):
+ split = column.split()
+
+ col = split.column()
+ col.prop(light, "use", text="Use", icon='OUTLINER_OB_LIGHT' if light.use else 'LIGHT_DATA')
+
+ sub = col.column()
+ sub.active = light.use
+ sub.prop(light, "specular_color")
+
+ col = split.column()
+ col.active = light.use
+ col.prop(light, "direction", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ column = layout.split()
+
+ userpref = context.user_preferences
+ system = userpref.system
+
+ light = system.solid_lights[0]
+ colsplit = column.split(percentage=0.85)
+ self.opengl_light_buttons(colsplit, light)
+
+ light = system.solid_lights[1]
+ colsplit = column.split(percentage=0.85)
+ self.opengl_light_buttons(colsplit, light)
+
+ light = system.solid_lights[2]
+ self.opengl_light_buttons(column, light)
+
+
classes = (
USERPREF_HT_header,
USERPREF_PT_tabs,
@@ -1663,6 +1668,7 @@ classes = (
USERPREF_PT_studiolight_matcaps,
USERPREF_PT_studiolight_world,
USERPREF_PT_studiolight_camera,
+ USERPREF_PT_studiolight_specular,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 682af76500b..a26d99e9ae9 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -19,11 +19,8 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-from .properties_grease_pencil_common import (
- GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
-)
from .properties_paint_common import UnifiedPaintPanel
+from .properties_grease_pencil_common import GreasePencilDataPanel
from bpy.app.translations import contexts as i18n_contexts
@@ -51,7 +48,7 @@ class VIEW3D_HT_header(Header):
layout.template_header_3D_mode()
- # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
+ # Contains buttons like Mode, Pivot, Layer, Mesh Select Mode...
shading_type = view.shading.type
shading_item = bpy.types.View3DShading.bl_rna.properties["type"].enum_items[shading_type]
@@ -80,18 +77,40 @@ class VIEW3D_HT_header(Header):
row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
- # GPencil
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.operator("gpencil.copy", text="", icon='COPYDOWN')
- row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+ # Grease Pencil
+ if obj and obj.type == 'GPENCIL' and context.gpencil_data:
+ gpd = context.gpencil_data
- # XXX: icon
- layout.prop(context.gpencil_data, "use_onion_skinning", text="Onion Skins", icon='PARTICLE_PATH')
+ if gpd.is_stroke_paint_mode:
+ row = layout.row(align=True)
+ row.popover(
+ panel="VIEW3D_PT_tools_grease_pencil_shapes",
+ text="Shapes"
+ )
- row = layout.row(align=True)
- row.prop(tool_settings.gpencil_sculpt, "use_select_mask")
- row.prop(tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
+ row = layout.row(align=True)
+ row.prop(gpd, "use_multiedit", text="", icon="FORCE_HARMONIC")
+
+ sub = row.row(align=True)
+ sub.active = gpd.use_multiedit
+ sub.popover(
+ panel="VIEW3D_PT_gpencil_multi_frame",
+ text="Multiframe"
+ )
+
+ if gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.operator("gpencil.copy", text="", icon='COPYDOWN')
+ row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+
+ row = layout.row(align=True)
+ row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="")
+
+ row.popover(
+ panel="VIEW3D_PT_tools_grease_pencil_interpolate",
+ text="Interpolate"
+ )
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
@@ -101,7 +120,7 @@ class VIEW3D_HT_header(Header):
scene = context.scene
# Orientation
- if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT'}:
orientation = scene.transform_orientation
current_orientation = scene.current_orientation
@@ -126,7 +145,8 @@ class VIEW3D_HT_header(Header):
if obj is None:
show_snap = True
else:
- if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
+ if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
+ 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
show_snap = True
else:
@@ -160,13 +180,15 @@ class VIEW3D_HT_header(Header):
# Proportional editing
if obj:
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.prop(tool_settings, "proportional_edit", icon_only=True)
+ gpd = context.gpencil_data
+ if gpd is not None and obj.type == 'GPENCIL':
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "proportional_edit", icon_only=True)
- sub = row.row(align=True)
- sub.active = tool_settings.proportional_edit != 'DISABLED'
- sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = tool_settings.proportional_edit != 'DISABLED'
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
elif object_mode in {'EDIT', 'PARTICLE_EDIT'}:
row = layout.row(align=True)
@@ -190,7 +212,7 @@ class VIEW3D_HT_header(Header):
sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
# Pivot
- if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT', 'GPENCIL_SCULPT'}:
pivot_point = tool_settings.transform_pivot_point
act_pivot_point = bpy.types.ToolSettings.bl_rna.properties["transform_pivot_point"].enum_items[pivot_point]
row = layout.row(align=True)
@@ -234,13 +256,14 @@ class VIEW3D_MT_editor_menus(Menu):
obj = context.active_object
mode_string = context.mode
edit_object = context.edit_object
- gp_edit = context.gpencil_data and context.gpencil_data.use_stroke_edit_mode
+ gp_edit = obj and obj.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
layout.menu("VIEW3D_MT_view")
# Select Menu
if gp_edit:
- layout.menu("VIEW3D_MT_select_gpencil")
+ if mode_string not in {'GPENCIL_PAINT', 'GPENCIL_WEIGHT'}:
+ layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
mesh = obj.data
if mesh.use_paint_mask:
@@ -266,7 +289,15 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("INFO_MT_edit_armature_add", text="Add")
if gp_edit:
- layout.menu("VIEW3D_MT_edit_gpencil")
+ if obj and obj.mode == 'GPENCIL_PAINT':
+ layout.menu("VIEW3D_MT_paint_gpencil")
+ elif obj and obj.mode == 'GPENCIL_EDIT':
+ layout.menu("VIEW3D_MT_edit_gpencil")
+ elif obj and obj.mode == 'GPENCIL_SCULPT':
+ layout.menu("VIEW3D_MT_sculpt_gpencil")
+ elif obj and obj.mode == 'GPENCIL_WEIGHT':
+ layout.menu("VIEW3D_MT_weight_gpencil")
+
elif edit_object:
layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
@@ -453,7 +484,7 @@ class VIEW3D_MT_snap(Menu):
layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid")
layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False
- layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True
+ layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_active", text="Selection to Active")
layout.separator()
@@ -642,9 +673,12 @@ class VIEW3D_MT_view_align(Menu):
layout.separator()
- layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
layout.operator("view3d.camera_to_view", text="Align Active Camera to View")
layout.operator("view3d.camera_to_view_selected", text="Align Active Camera to Selected")
+
+ layout.separator()
+
+ layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
layout.operator("view3d.view_center_cursor")
layout.separator()
@@ -667,6 +701,8 @@ class VIEW3D_MT_view_align_selected(Menu):
props.align_active = True
props.type = 'BOTTOM'
+ layout.separator()
+
props = layout.operator("view3d.view_axis", text="Front")
props.align_active = True
props.type = 'FRONT'
@@ -675,6 +711,8 @@ class VIEW3D_MT_view_align_selected(Menu):
props.align_active = True
props.type = 'BACK'
+ layout.separator()
+
props = layout.operator("view3d.view_axis", text="Right")
props.align_active = True
props.type = 'RIGHT'
@@ -1187,6 +1225,7 @@ class VIEW3D_MT_select_gpencil(Menu):
layout.separator()
layout.operator("gpencil.select_linked", text="Linked")
+ layout.operator("gpencil.select_alternate")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
layout.separator()
@@ -1442,6 +1481,7 @@ class INFO_MT_add(Menu):
layout.menu("INFO_MT_surface_add", icon='OUTLINER_OB_SURFACE')
layout.menu("INFO_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
+ layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
layout.separator()
layout.menu("INFO_MT_armature_add", icon='OUTLINER_OB_ARMATURE')
@@ -1541,8 +1581,8 @@ class VIEW3D_MT_object(Menu):
layout.separator()
- layout.operator("object.shade_smooth", text="Smooth Shading")
- layout.operator("object.shade_flat", text="Flat Shading")
+ layout.operator("object.shade_smooth")
+ layout.operator("object.shade_flat")
layout.separator()
@@ -2655,6 +2695,9 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.menu("VIEW3D_MT_edit_mesh_showhide")
layout.operator_menu_enum("mesh.separate", "type")
layout.menu("VIEW3D_MT_edit_mesh_clean")
+
+ layout.separator()
+
layout.menu("VIEW3D_MT_edit_mesh_delete")
@@ -2879,14 +2922,11 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
props.use_verts = True
props.clear = True
- layout.separator()
-
- layout.separator()
-
if with_freestyle:
+ layout.separator()
+
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
- layout.separator()
class VIEW3D_MT_edit_mesh_edges(Menu):
@@ -3011,6 +3051,30 @@ class VIEW3D_MT_edit_mesh_normals(Menu):
layout.operator("mesh.flip_normals")
layout.operator("mesh.set_normals_from_faces", text="Set From Faces")
+ layout.operator("transform.rotate_normal", text="Rotate Normal")
+ layout.operator("mesh.point_normals", text="Point normals to target")
+
+ layout.operator("mesh.merge_normals", text="Merge")
+ layout.operator("mesh.split_normals", text="Split")
+
+ layout.operator("mesh.average_normals", text="Average Normals")
+
+ layout.label(text="Normal Vector")
+
+ layout.operator("mesh.normals_tools", text="Copy").mode = 'COPY'
+ layout.operator("mesh.normals_tools", text="Paste").mode = 'PASTE'
+
+ layout.operator("mesh.normals_tools", text="Multiply").mode = 'MULTIPLY'
+ layout.operator("mesh.normals_tools", text="Add").mode = 'ADD'
+
+ layout.operator("mesh.normals_tools", text="Reset").mode = 'RESET'
+
+ layout.operator("mesh.smoothen_normals", text="Smoothen")
+
+ layout.label(text="Face Strength")
+ layout.operator("mesh.mod_weighted_strength", text="Face select", icon = "FACESEL").set = False
+ layout.operator("mesh.mod_weighted_strength", text="Set Strength", icon = "ZOOMIN").set = True
+
class VIEW3D_MT_edit_mesh_shading(Menu):
bl_label = "Shading"
@@ -3103,12 +3167,17 @@ class VIEW3D_MT_edit_gpencil_delete(Menu):
layout.separator()
- layout.operator("gpencil.dissolve")
+ layout.operator_enum("gpencil.dissolve", "type")
layout.separator()
layout.operator("gpencil.active_frames_delete_all")
+ layout.separator()
+
+ layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes").mode = 'ACTIVE'
+ layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes all Frames").mode = 'ALL'
+
# Edit Curve
# draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
@@ -3469,11 +3538,46 @@ class VIEW3D_MT_edit_armature_delete(Menu):
layout.operator("armature.dissolve", text="Dissolve")
-# ********** GPencil Stroke Edit menu **********
+# ********** Grease Pencil Stroke menus **********
+class VIEW3D_MT_gpencil_simplify(Menu):
+ bl_label = "Simplify"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("gpencil.stroke_simplify_fixed", text="Fixed")
+ layout.operator("gpencil.stroke_simplify", text="Adaptative")
+
+
+class VIEW3D_MT_paint_gpencil(Menu):
+ bl_label = "Strokes"
+
+ def draw(self, context):
+
+ layout = self.layout
+
+ layout.menu("VIEW3D_MT_gpencil_animation")
+ layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
+
+ layout.separator()
+
+ layout.operator("gpencil.delete", text="Delete Frame").type = 'FRAME'
+ layout.operator("gpencil.active_frames_delete_all")
+
+
+class VIEW3D_MT_assign_material(Menu):
+ bl_label = "Assign Material"
+
+ def draw(self, context):
+ layout = self.layout
+ ob = context.active_object
+
+ for slot in ob.material_slots:
+ mat = slot.material
+ layout.operator("gpencil.stroke_change_color", text=mat.name).material = mat.name
class VIEW3D_MT_edit_gpencil(Menu):
- bl_label = "GPencil"
+ bl_label = "Strokes"
def draw(self, context):
tool_settings = context.tool_settings
@@ -3481,53 +3585,126 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout = self.layout
layout.menu("VIEW3D_MT_edit_gpencil_transform")
- layout.operator("transform.mirror", text="Mirror")
+
+ layout.separator()
layout.menu("GPENCIL_MT_snap")
layout.separator()
- layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
- layout.prop_menu_enum(tool_settings.gpencil_sculpt, "tool", text="Sculpt Brush")
+ layout.menu("VIEW3D_MT_gpencil_animation")
layout.separator()
- layout.menu("VIEW3D_MT_object_animation") # NOTE: provides keyingset access...
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
layout.separator()
layout.operator("gpencil.duplicate_move", text="Duplicate")
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.menu("VIEW3D_MT_gpencil_simplify")
layout.separator()
+ layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
+ layout.operator("gpencil.stroke_split", text="Split")
layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
layout.operator("gpencil.stroke_flip", text="Flip Direction")
layout.separator()
layout.operator("gpencil.copy", text="Copy")
- layout.operator("gpencil.paste", text="Paste")
+ layout.operator("gpencil.paste", text="Paste").type = 'COPY'
+ layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
+ layout.menu("VIEW3D_MT_assign_material")
+ layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_gpencil_delete")
+ layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
+
+
+class VIEW3D_MT_sculpt_gpencil(Menu):
+ bl_label = "Strokes"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.menu("VIEW3D_MT_edit_gpencil_transform")
+
+ layout.separator()
+ layout.menu("GPENCIL_MT_snap")
+
+ layout.separator()
+
+ layout.operator("gpencil.duplicate_move", text="Duplicate")
+ layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.menu("VIEW3D_MT_gpencil_simplify")
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
+ layout.operator("gpencil.stroke_split", text="Split")
+ layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
+ layout.operator("gpencil.stroke_flip", text="Flip Direction")
layout.separator()
- layout.operator("gpencil.reveal")
- layout.operator("gpencil.hide", text="Show Active Layer Only").unselected = True
- layout.operator("gpencil.hide", text="Hide Active Layer").unselected = False
+ layout.operator("gpencil.copy", text="Copy")
+ layout.operator("gpencil.paste", text="Paste").type = 'COPY'
+ layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
layout.separator()
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
- layout.operator("gpencil.stroke_change_color", text="Move to Color")
+ layout.menu("VIEW3D_MT_assign_material")
layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
layout.separator()
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
- layout.separator()
- layout.menu("VIEW3D_MT_edit_gpencil_delete")
+class VIEW3D_MT_weight_gpencil(Menu):
+ bl_label = "Weights"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.vertex_group_invert", text="Invert")
+ layout.operator("gpencil.vertex_group_smooth", text="Smooth")
+
+
+class VIEW3D_MT_gpencil_animation(Menu):
+ bl_label = "Animation"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL' and ob.mode != 'OBJECT'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.blank_frame_add")
+ layout.operator("gpencil.active_frames_delete_all", text="Delete Frame(s)")
+
+ layout.separator()
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers").mode = 'ALL'
class VIEW3D_MT_edit_gpencil_transform(Menu):
@@ -3588,20 +3765,6 @@ class VIEW3D_MT_view_pie(Menu):
# ********** Panel **********
-class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
-class VIEW3D_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
class VIEW3D_PT_view3d_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -3713,8 +3876,9 @@ class VIEW3D_PT_object_type_visibility(Panel):
"armature",
"lattice",
"empty",
+ "grease_pencil",
"camera",
- "lamp",
+ "light",
"light_probe",
"speaker",
)
@@ -3741,6 +3905,15 @@ class VIEW3D_PT_shading(Panel):
bl_label = "Shading"
bl_ui_units_x = 11
+ @classmethod
+ def get_shading(cls, context):
+ # Get settings from 3D viewport or OpenGL render engine
+ view = context.space_data
+ if view.type == 'VIEW_3D':
+ return view.shading
+ else:
+ return context.scene.display.shading
+
def draw(self, context):
pass
@@ -3753,9 +3926,7 @@ class VIEW3D_PT_shading_lighting(Panel):
def draw(self, context):
layout = self.layout
-
- view = context.space_data
- shading = view.shading
+ shading = VIEW3D_PT_shading.get_shading(context)
col = layout.column()
split = col.split(0.9)
@@ -3767,10 +3938,10 @@ class VIEW3D_PT_shading_lighting(Panel):
split = layout.split(0.9)
col = split.column()
sub = col.row()
- sub.scale_y = 0.6 # smaller matcap/hdri preview
+ sub.scale_y = 0.6 # smaller matcap/hdri preview
if shading.light == 'STUDIO':
- sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+ sub.template_icon_view(shading, "studio_light", scale=3)
if shading.selected_studio_light.orientation == 'WORLD':
col.prop(shading, "studiolight_rotate_z", text="Rotation")
@@ -3779,7 +3950,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
elif shading.light == 'MATCAP':
- sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+ sub.template_icon_view(shading, "studio_light", scale=3)
col = split.column()
col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
@@ -3796,7 +3967,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col = split.column()
sub = col.row()
sub.scale_y = 0.6
- sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+ sub.template_icon_view(shading, "studio_light", scale=3)
col = split.column()
col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
@@ -3806,7 +3977,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col = split.column()
col.prop(shading, "studiolight_rotate_z", text="Rotation")
col.prop(shading, "studiolight_background_alpha")
- col = split.column() # to align properly with above
+ col = split.column() # to align properly with above
class VIEW3D_PT_shading_color(Panel):
@@ -3817,20 +3988,22 @@ class VIEW3D_PT_shading_color(Panel):
@classmethod
def poll(cls, context):
- view = context.space_data
- shading = view.shading
+ shading = VIEW3D_PT_shading.get_shading(context)
return shading.type == 'SOLID'
def draw(self, context):
layout = self.layout
- view = context.space_data
- shading = view.shading
-
- layout.row().prop(shading, "color_type", expand=True)
+ shading = VIEW3D_PT_shading.get_shading(context)
+ layout.row().prop(shading, 'color_type', expand=True)
if shading.color_type == 'SINGLE':
- layout.row().prop(shading, "single_color", text="")
+ layout.row().prop(shading, 'single_color', text="")
+
+ layout.row().label("Background")
+ layout.row().prop(shading, 'background_type', expand=True)
+ if shading.background_type == 'VIEWPORT':
+ layout.row().prop(shading, "background_color", text="")
class VIEW3D_PT_shading_options(Panel):
@@ -3841,15 +4014,13 @@ class VIEW3D_PT_shading_options(Panel):
@classmethod
def poll(cls, context):
- view = context.space_data
- shading = view.shading
+ shading = VIEW3D_PT_shading.get_shading(context)
return shading.type == 'SOLID'
def draw(self, context):
layout = self.layout
- view = context.space_data
- shading = view.shading
+ shading = VIEW3D_PT_shading.get_shading(context)
col = layout.column()
@@ -3902,8 +4073,6 @@ class VIEW3D_PT_shading_options(Panel):
if not shading.light == 'MATCAP':
col.prop(shading, "show_specular_highlight")
- col.prop(view, "show_world")
-
class VIEW3D_PT_shading_options_shadow(Panel):
bl_label = "Shadow Settings"
@@ -4028,6 +4197,8 @@ class VIEW3D_PT_overlay_guides(Panel):
if shading.type == 'MATERIAL':
col.prop(overlay, "show_look_dev")
+ col.prop(overlay, "show_annotation", text="Annotations")
+
class VIEW3D_PT_overlay_object(Panel):
bl_space_type = 'VIEW_3D'
@@ -4348,7 +4519,7 @@ class VIEW3D_PT_overlay_edit_curve(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_parent_id = 'VIEW3D_PT_overlay'
- bl_label = "Edit Curve"
+ bl_label = "Curve Edit Mode"
@classmethod
def poll(cls, context):
@@ -4423,7 +4594,7 @@ class VIEW3D_PT_overlay_edit_armature(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_parent_id = 'VIEW3D_PT_overlay'
- bl_label = "Edit Armature"
+ bl_label = "Armature Edit Mode"
@classmethod
def poll(cls, context):
@@ -4493,9 +4664,9 @@ class VIEW3D_PT_pivot_point(Panel):
col.label("Pivot Point")
col.prop(toolsettings, "transform_pivot_point", expand=True)
- col.separator()
-
if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}):
+ col.separator()
+
col.prop(
toolsettings,
"use_transform_pivot_point_align",
@@ -4566,6 +4737,60 @@ class VIEW3D_PT_transform_orientations(Panel):
row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
+class VIEW3D_PT_overlay_gpencil_options(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = ""
+
+ @classmethod
+ def poll(cls, context):
+ return context.object and context.object.type == 'GPENCIL'
+
+ def draw_header(self, context):
+ layout = self.layout
+ layout.label(text={
+ 'GPENCIL_PAINT': "Draw Grease Pencil",
+ 'GPENCIL_EDIT': "Edit Grease Pencil",
+ 'GPENCIL_SCULPT': "Sculpt Grease Pencil",
+ 'GPENCIL_WEIGHT': "Weight Grease Pencil",
+ 'OBJECT': "Grease Pencil",
+ }[context.mode])
+
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
+ overlay = view.overlay
+
+ layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
+
+ col = layout.column()
+ row = col.row()
+ row.prop(overlay, "use_gpencil_paper", text="")
+ sub = row.row()
+ sub.active = overlay.use_gpencil_paper
+ sub.prop(overlay, "gpencil_paper_opacity", text="Fade 3D Objects", slider=True)
+
+ col = layout.column()
+ row = col.row()
+ row.prop(overlay, "use_gpencil_grid", text="")
+ sub = row.row()
+ sub.active = overlay.use_gpencil_grid
+ sub.prop(overlay, "gpencil_grid_opacity", text="Canvas Grid", slider=True)
+
+ if overlay.use_gpencil_grid:
+ row = layout.row(align=True)
+ row.prop(overlay, "gpencil_grid_scale")
+ col = row.column()
+ col.prop(overlay, "gpencil_grid_lines", text="Subdivisions")
+ col.prop(overlay, "gpencil_grid_axis")
+
+ if context.object.mode in {'GPENCIL_EDIT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
+ layout.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
+ layout.prop(overlay, "use_gpencil_multiedit_line_only", text="Show Edit Lines only in multiframe")
+ layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
+
+
class VIEW3D_PT_quad_view(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -4593,6 +4818,14 @@ class VIEW3D_PT_quad_view(Panel):
row.prop(region, "use_box_clip")
+# Annotation properties
+class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+
class VIEW3D_PT_view3d_stereo(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -4672,6 +4905,84 @@ class VIEW3D_PT_context_properties(Panel):
rna_prop_ui.draw(self.layout, context, member, object, False)
+# Grease Pencil Object - Multiframe falloff tools
+class VIEW3D_PT_gpencil_multi_frame(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Multi Frame"
+
+ @staticmethod
+ def draw(self, context):
+ gpd = context.gpencil_data
+ settings = context.tool_settings.gpencil_sculpt
+
+ layout = self.layout
+ col = layout.column(align=True)
+ col.prop(settings, "use_multiframe_falloff")
+
+ # Falloff curve
+ if gpd.use_multiedit and settings.use_multiframe_falloff:
+ layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
+
+
+class VIEW3D_MT_gpencil_edit_specials(Menu):
+ bl_label = "Grease Pencil Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+
+ layout.menu("VIEW3D_MT_assign_material")
+ layout.separator()
+
+ layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ layout.operator("gpencil.stroke_simplify", text="Simplify Adaptative")
+
+ layout.separator()
+ layout.menu("GPENCIL_MT_separate", text="Separate")
+
+ layout.separator()
+ layout.operator("gpencil.stroke_split", text="Split")
+
+ layout.separator()
+
+ layout.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
+ layout.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
+ layout.operator("gpencil.stroke_flip", text="Flip Direction")
+
+ layout.separator()
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
+
+ if is_3d_view:
+ layout.separator()
+ layout.operator("gpencil.reproject")
+
+
+class VIEW3D_MT_gpencil_sculpt_specials(Menu):
+ bl_label = "Grease Pencil Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.menu("VIEW3D_MT_assign_material")
+ layout.separator()
+
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
+
+ layout.separator()
+
+ layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ layout.operator("gpencil.stroke_simplify", text="Simplify Adaptative")
+
+
classes = (
VIEW3D_HT_header,
VIEW3D_MT_editor_menus,
@@ -4779,8 +5090,14 @@ classes = (
VIEW3D_MT_edit_mesh_clean,
VIEW3D_MT_edit_mesh_delete,
VIEW3D_MT_edit_mesh_showhide,
+ VIEW3D_MT_paint_gpencil,
+ VIEW3D_MT_assign_material,
VIEW3D_MT_edit_gpencil,
VIEW3D_MT_edit_gpencil_delete,
+ VIEW3D_MT_sculpt_gpencil,
+ VIEW3D_MT_weight_gpencil,
+ VIEW3D_MT_gpencil_animation,
+ VIEW3D_MT_gpencil_simplify,
VIEW3D_MT_edit_curve,
VIEW3D_MT_edit_curve_ctrlpoints,
VIEW3D_MT_edit_curve_segments,
@@ -4803,12 +5120,14 @@ classes = (
VIEW3D_MT_edit_gpencil_interpolate,
VIEW3D_MT_object_mode_pie,
VIEW3D_MT_view_pie,
- VIEW3D_PT_grease_pencil,
- VIEW3D_PT_grease_pencil_palettecolor,
VIEW3D_PT_view3d_properties,
VIEW3D_PT_view3d_camera_lock,
VIEW3D_PT_view3d_cursor,
VIEW3D_PT_object_type_visibility,
+ VIEW3D_PT_grease_pencil,
+ VIEW3D_PT_gpencil_multi_frame,
+ VIEW3D_MT_gpencil_edit_specials,
+ VIEW3D_MT_gpencil_sculpt_specials,
VIEW3D_PT_quad_view,
VIEW3D_PT_view3d_stereo,
VIEW3D_PT_shading,
@@ -4837,6 +5156,7 @@ classes = (
VIEW3D_PT_pivot_point,
VIEW3D_PT_snapping,
VIEW3D_PT_transform_orientations,
+ VIEW3D_PT_overlay_gpencil_options,
VIEW3D_PT_context_properties,
)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 8d1b124578c..febe95c5522 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -20,12 +20,9 @@
import bpy
from bpy.types import Menu, Panel, UIList
from .properties_grease_pencil_common import (
- GreasePencilDrawingToolsPanel,
GreasePencilStrokeEditPanel,
- GreasePencilInterpolatePanel,
GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel
+ GreasePencilAppearancePanel,
)
from .properties_paint_common import (
UnifiedPaintPanel,
@@ -33,6 +30,7 @@ from .properties_paint_common import (
brush_texpaint_common,
brush_mask_texture_settings,
)
+from bl_operators.presets import PresetMenu
class View3DPanel:
@@ -70,6 +68,16 @@ def draw_vpaint_symmetry(layout, vpaint):
col.use_property_split = True
col.prop(vpaint, "radial_symmetry", text="Radial")
+# Most of these panels should not be visible in GP edit modes
+
+
+def is_not_gpencil_edit_mode(context):
+ is_gpmode = (
+ context.active_object and
+ context.active_object.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
+ )
+ return not is_gpmode
+
# ********** default tools for editmode_mesh ****************
@@ -280,16 +288,16 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
if context.particle_edit_object:
tool = settings.tool
- layout.column().prop(settings, "tool", expand=True)
-
if tool != 'NONE':
+ layout.column().prop(settings, "tool")
col = layout.column()
col.prop(brush, "size", slider=True)
- if tool != 'ADD':
+ if tool == 'ADD':
+ col.prop(brush, "count")
+ else:
col.prop(brush, "strength", slider=True)
if tool == 'ADD':
- col.prop(brush, "count")
col = layout.column()
col.prop(settings, "use_default_interpolate")
col.prop(brush, "steps", slider=True)
@@ -1340,9 +1348,295 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
sub.prop(pe, "fade_frames", slider=True)
-# Grease Pencil drawing tools
-class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+class VIEW3D_PT_tools_normal(View3DPanel, Panel):
+ bl_category = ""
+ bl_context = ".mesh_edit"
+ bl_label = "Normal Tools"
+
+ def draw(self, context):
+ layout = self.layout
+ toolsettings = context.tool_settings
+
+ col = layout.column(align=True)
+ col.label(text="Normal Vector")
+ col.prop(toolsettings, "normal_vector", text="")
+
+ layout.separator()
+ layout.label(text="Face Strength")
+ layout.prop(toolsettings, "face_strength", text="")
+
+ col = layout.column(align=True)
+
+
+# ********** grease pencil object tool panels ****************
+
+# Grease Pencil drawing brushes
+class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Brush"
+
+ @classmethod
+ def poll(cls, context):
+ is_3d_view = context.space_data.type == 'VIEW_3D'
+ if is_3d_view:
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(gpd.is_stroke_paint_mode)
+ else:
+ return True
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ ts = context.scene.tool_settings
+ settings = ts.gpencil_paint
+
+ row = layout.row()
+ col = row.column()
+ col.template_ID_preview(settings, "brush", new="brush.add_gpencil", rows=3, cols=8)
+
+ col = row.column()
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.brush_presets_create", icon='HELP', text="")
+
+ if brush is not None:
+ # XXX: Items in "sub" currently show up beside the brush selector in a separate column
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ sub.prop(gp_settings, "default_eraser", text="")
+
+ # Brush details
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ col = layout.column(align=True)
+ col.prop(brush, "size", text="Radius")
+
+ col.separator()
+ row = col.row()
+ row.prop(gp_settings, "eraser_mode", expand=True)
+ elif gp_settings.gpencil_brush_type == 'FILL':
+ col = layout.column(align=True)
+ col.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
+ col.prop(brush, "size", text="Thickness")
+ col.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
+
+ col = layout.row(align=True)
+ col.template_ID(gp_settings, "material")
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "gpencil_fill_draw_mode", text="Boundary Draw Mode")
+ row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
+
+ col = layout.column(align=True)
+ col.enabled = gp_settings.gpencil_fill_draw_mode != "STROKE"
+ col.prop(gp_settings, "gpencil_fill_hide", text="Hide Transparent Lines")
+ sub = col.row(align=True)
+ sub.enabled = gp_settings.gpencil_fill_hide
+ sub.prop(gp_settings, "gpencil_fill_threshold", text="Threshold")
+ else: # bgpsettings.gpencil_brush_type == 'DRAW':
+ row = layout.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ row = layout.row(align=True)
+ row.template_ID(gp_settings, "material")
+
+
+# Grease Pencil drawing brushes options
+class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Options"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header_preset(self, context):
+ VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ if brush is not None:
+ col = layout.column(align=True)
+ col.prop(gp_settings, "input_samples")
+ col.separator()
+
+ col.prop(gp_settings, "active_smooth_factor")
+ col.separator()
+
+ col.prop(gp_settings, "angle", slider=True)
+ col.prop(gp_settings, "angle_factor", text="Factor", slider=True)
+ col.separator()
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Stabilizer"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ return brush is not None and gp_settings.gpencil_brush_type == 'DRAW'
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "use_stabilizer", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.use_stabilizer
+
+ layout.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ layout.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Post-processing Settings"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+
+ return brush is not None
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "enable_settings", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.enable_settings
+
+ col = layout.column(align=True)
+ col.prop(gp_settings, "pen_smooth_factor")
+ col.prop(gp_settings, "pen_thick_smooth_factor")
+
+ col = layout.column(align=True)
+ col.prop(gp_settings, "pen_smooth_steps")
+ col.prop(gp_settings, "pen_thick_smooth_steps")
+
+ col = layout.column(align=True)
+ col.prop(gp_settings, "pen_subdivision_steps")
+ col.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Random Settings"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+
+ return brush is not None
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "enable_random", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.enable_random
+
+ layout.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
+ layout.prop(gp_settings, "random_strength", text="Strength", slider=True)
+ layout.prop(gp_settings, "uv_random", text="UV", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_jitter", slider=True)
+ row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
+
+
+# Grease Pencil drawingcurves
+class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Curves"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ # Brush
+ layout.label("Sensitivity")
+ layout.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True)
+
+ layout.label("Strength")
+ layout.template_curve_mapping(gp_settings, "curve_strength", brush=True)
+
+ layout.label("Jitter")
+ layout.template_curve_mapping(gp_settings, "curve_jitter", brush=True)
+
+
+# Grease Pencil create shapes
+class VIEW3D_PT_tools_grease_pencil_shapes(View3DPanel, Panel):
bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Shapes"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ col = layout.column(align=True)
+ col.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE'
+ col.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX'
+ col.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE'
+
+ layout.operator("object.gpencil_add", text="Monkey", icon='MONKEY').type = 'MONKEY'
# Grease Pencil stroke editing tools
@@ -1351,24 +1645,109 @@ class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
# Grease Pencil stroke interpolation tools
-class VIEW3D_PT_tools_grease_pencil_interpolate(GreasePencilInterpolatePanel, Panel):
+class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Interpolate"
+
+ @classmethod
+ def poll(cls, context):
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ settings = context.tool_settings.gpencil_interpolate
+
+ col = layout.column(align=True)
+ col.label("Interpolate Strokes")
+ col.operator("gpencil.interpolate", text="Interpolate")
+ col.operator("gpencil.interpolate_sequence", text="Sequence")
+ col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
+
+ col = layout.column(align=True)
+ col.label(text="Options:")
+ col.prop(settings, "interpolate_all_layers")
+ col.prop(settings, "interpolate_selected_only")
+
+ col = layout.column(align=True)
+ col.label(text="Sequence Options:")
+ col.prop(settings, "type")
+ if settings.type == 'CUSTOM':
+ # TODO: Options for loading/saving curve presets?
+ col.template_curve_mapping(settings, "interpolation_curve", brush=True)
+ elif settings.type != 'LINEAR':
+ col.prop(settings, "easing")
+
+ if settings.type == 'BACK':
+ layout.prop(settings, "back")
+ elif setting.type == 'ELASTIC':
+ sub = layout.column(align=True)
+ sub.prop(settings, "amplitude")
+ sub.prop(settings, "period")
# Grease Pencil stroke sculpting tools
-class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'VIEW_3D'
+class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_sculpt"
+ bl_category = "Tools"
+ bl_label = "Sculpt Strokes"
-# Grease Pencil drawing brushes
-class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'VIEW_3D'
+# Grease Pencil weight painting tools
+class VIEW3D_PT_tools_grease_pencil_weight_paint(View3DPanel, Panel):
+ bl_context = ".greasepencil_weight"
+ bl_category = "Tools"
+ bl_label = "Weight Paint"
-# Grease Pencil drawingcurves
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ gpd = context.gpencil_data
+ settings = context.tool_settings.gpencil_sculpt
+ tool = settings.tool
+ brush = settings.brush
-class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'VIEW_3D'
+ layout.template_icon_view(settings, "weight_tool", show_labels=True)
+
+ col = layout.column()
+ col.prop(brush, "size", slider=True)
+ row = col.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+
+ col.prop(brush, "use_falloff")
+
+
+# Grease Pencil Brush Appeareance (one for each mode)
+class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_sculpt"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_weight"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_gpencil_brush_presets(PresetMenu):
+ """Brush settings"""
+ bl_label = "Brush Presets"
+ preset_subdir = "gpencil_brush"
+ preset_operator = "script.execute_preset"
+ preset_add_operator = "scene.gpencil_brush_preset_add"
classes = (
@@ -1400,12 +1779,22 @@ classes = (
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_gpencil_brush_presets,
VIEW3D_PT_tools_grease_pencil_brush,
+ VIEW3D_PT_tools_grease_pencil_brush_option,
+ VIEW3D_PT_tools_grease_pencil_brush_settings,
+ VIEW3D_PT_tools_grease_pencil_brush_stabilizer,
+ VIEW3D_PT_tools_grease_pencil_brush_random,
VIEW3D_PT_tools_grease_pencil_brushcurves,
+ VIEW3D_PT_tools_grease_pencil_shapes,
+ VIEW3D_PT_tools_grease_pencil_sculpt,
+ VIEW3D_PT_tools_grease_pencil_weight_paint,
+ VIEW3D_PT_tools_grease_pencil_paint_appearance,
+ VIEW3D_PT_tools_grease_pencil_sculpt_appearance,
+ VIEW3D_PT_tools_grease_pencil_weight_appearance,
+ VIEW3D_PT_tools_grease_pencil_interpolate,
+ VIEW3D_PT_tools_normal,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index e6500b7c2c0..a70d78c16c6 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -216,6 +216,7 @@ shader_node_categories = [
NodeItem("ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumePrincipled"),
NodeItem("ShaderNodeEeveeSpecular", poll=object_eevee_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfHairPrincipled", poll=object_shader_nodes_poll)
]),
ShaderNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
NodeItem("ShaderNodeTexImage"),
@@ -365,6 +366,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeChromaMatte"),
NodeItem("CompositorNodeColorMatte"),
NodeItem("CompositorNodeDoubleEdgeMask"),
+ NodeItem("CompositorNodeCryptomatte"),
]),
CompositorNodeCategory("CMP_DISTORT", "Distort", items=[
NodeItem("CompositorNodeScale"),
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py
index 1463915886a..a07491742ec 100644
--- a/release/scripts/templates_py/batch_export.py
+++ b/release/scripts/templates_py/batch_export.py
@@ -9,9 +9,9 @@ basedir = os.path.dirname(bpy.data.filepath)
if not basedir:
raise Exception("Blend file is not saved")
-scene = bpy.context.scene
+view_layer = bpy.context.view_layer
-obj_active = scene.objects.active
+obj_active = view_layer.objects.active
selection = bpy.context.selected_objects
bpy.ops.object.select_all(action='DESELECT')
@@ -21,7 +21,7 @@ for obj in selection:
obj.select_set(action='SELECT')
# some exporters only use the active object
- scene.objects.active = obj
+ view_layer.objects.active = obj
name = bpy.path.clean_name(obj.name)
fn = os.path.join(basedir, name)
@@ -36,7 +36,7 @@ for obj in selection:
print("written:", fn)
-scene.objects.active = obj_active
+view_layer.objects.active = obj_active
for obj in selection:
obj.select_set(action='SELECT')
diff --git a/release/scripts/templates_py/gizmo_custom_geometry.py b/release/scripts/templates_py/gizmo_custom_geometry.py
index f71237f52f7..8125498fa85 100644
--- a/release/scripts/templates_py/gizmo_custom_geometry.py
+++ b/release/scripts/templates_py/gizmo_custom_geometry.py
@@ -63,7 +63,7 @@ custom_shape_verts = (
class MyCustomShapeWidget(Gizmo):
- bl_idname = "VIEW3D_WT_auto_facemap"
+ bl_idname = "VIEW3D_GT_auto_facemap"
bl_target_properties = (
{"id": "offset", "type": 'FLOAT', "array_length": 1},
)
@@ -113,7 +113,7 @@ class MyCustomShapeWidget(Gizmo):
class MyCustomShapeWidgetGroup(GizmoGroup):
- bl_idname = "OBJECT_WGT_light_test"
+ bl_idname = "OBJECT_GGT_light_test"
bl_label = "Test Light Widget"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
diff --git a/release/scripts/templates_py/gizmo_operator.py b/release/scripts/templates_py/gizmo_operator.py
index 3cbb0801e9c..bdc1bc9893c 100644
--- a/release/scripts/templates_py/gizmo_operator.py
+++ b/release/scripts/templates_py/gizmo_operator.py
@@ -80,7 +80,7 @@ class SelectSideOfPlane(Operator):
# Gizmos for plane_co, plane_no
class SelectSideOfPlaneGizmoGroup(GizmoGroup):
- bl_idname = "MESH_WGT_select_side_of_plane"
+ bl_idname = "MESH_GGT_select_side_of_plane"
bl_label = "Side of Plane Gizmo"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
@@ -126,7 +126,7 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
# XXX, this may change!
op.execute(context)
- mpr = self.gizmos.new("GIZMO_WT_grab_3d")
+ mpr = self.gizmos.new("GIZMO_GT_grab_3d")
mpr.target_set_handler("offset", get=grab_get_cb, set=grab_set_cb)
mpr.use_draw_value = True
@@ -161,7 +161,7 @@ class SelectSideOfPlaneGizmoGroup(GizmoGroup):
op.plane_no = no
op.execute(context)
- mpr = self.gizmos.new("GIZMO_WT_dial_3d")
+ mpr = self.gizmos.new("GIZMO_GT_dial_3d")
mpr.target_set_handler("offset", get=direction_get_cb, set=direction_set_cb)
mpr.draw_options = {'ANGLE_START_Y'}
diff --git a/release/scripts/templates_py/gizmo_operator_target.py b/release/scripts/templates_py/gizmo_operator_target.py
index 08fe63ef0b7..606aa6749d0 100644
--- a/release/scripts/templates_py/gizmo_operator_target.py
+++ b/release/scripts/templates_py/gizmo_operator_target.py
@@ -10,7 +10,7 @@ from bpy.types import (
class MyCameraWidgetGroup(GizmoGroup):
- bl_idname = "OBJECT_WGT_test_camera"
+ bl_idname = "OBJECT_GGT_test_camera"
bl_label = "Object Camera Test Widget"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
@@ -24,7 +24,7 @@ class MyCameraWidgetGroup(GizmoGroup):
def setup(self, context):
# Run an operator using the dial gizmo
ob = context.object
- mpr = self.gizmos.new("GIZMO_WT_dial_3d")
+ mpr = self.gizmos.new("GIZMO_GT_dial_3d")
props = mpr.target_set_operator("transform.rotate")
props.constraint_axis = False, False, True
props.constraint_orientation = 'LOCAL'
diff --git a/release/scripts/templates_py/gizmo_simple.py b/release/scripts/templates_py/gizmo_simple.py
index 0fd1e0b386b..396378da04c 100644
--- a/release/scripts/templates_py/gizmo_simple.py
+++ b/release/scripts/templates_py/gizmo_simple.py
@@ -11,7 +11,7 @@ from bpy.types import (
class MyLightWidgetGroup(GizmoGroup):
- bl_idname = "OBJECT_WGT_light_test"
+ bl_idname = "OBJECT_GGT_light_test"
bl_label = "Test Light Widget"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
@@ -25,7 +25,7 @@ class MyLightWidgetGroup(GizmoGroup):
def setup(self, context):
# Arrow gizmo has one 'offset' property we can assign to the light energy.
ob = context.object
- mpr = self.gizmos.new("GIZMO_WT_arrow_3d")
+ mpr = self.gizmos.new("GIZMO_GT_arrow_3d")
mpr.target_set_prop("offset", ob.data, "energy")
mpr.matrix_basis = ob.matrix_world.normalized()
mpr.draw_style = 'BOX'
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index e3b63813fc4..613501143f7 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -68,7 +68,7 @@ def main(context, event):
# we could do lots of stuff but for the example just select.
if best_obj is not None:
best_obj.select_set(action='SELECT')
- context.scene.objects.active = best_obj
+ context.view_layer.objects.active = best_obj
class ViewOperatorRayCast(bpy.types.Operator):
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index c3b15845cf7..f46283aced5 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -44,7 +44,9 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fileglobal_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_shader_fx_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_group_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_hair_types.h
@@ -113,6 +115,8 @@ add_subdirectory(gpu)
add_subdirectory(imbuf)
add_subdirectory(nodes)
add_subdirectory(modifiers)
+add_subdirectory(gpencil_modifiers)
+add_subdirectory(shader_fx)
add_subdirectory(makesdna)
add_subdirectory(makesrna)
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index 87545007870..f2ae1c831d1 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -26,14 +26,7 @@
#include <Alembic/AbcGeom/All.h>
#include <algorithm>
-
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
#include <unordered_map>
-typedef std::unordered_map<uint64_t, int> uv_index_map;
-#else
-#include <map>
-typedef std::map<uint64_t, int> uv_index_map;
-#endif
extern "C" {
#include "DNA_customdata_types.h"
@@ -60,6 +53,8 @@ using Alembic::AbcGeom::OV2fGeomParam;
using Alembic::AbcGeom::OC4fGeomParam;
+typedef std::unordered_map<uint64_t, int> uv_index_map;
+
static inline uint64_t uv_to_hash_key(Imath::V2f v)
{
/* Convert -0.0f to 0.0f, so bitwise comparison works. */
diff --git a/source/blender/alembic/intern/abc_mball.cc b/source/blender/alembic/intern/abc_mball.cc
index d6e54407922..62ab561274a 100644
--- a/source/blender/alembic/intern/abc_mball.cc
+++ b/source/blender/alembic/intern/abc_mball.cc
@@ -52,7 +52,7 @@ AbcMBallWriter::AbcMBallWriter(
m_is_animated = isAnimated();
m_mesh_ob = BKE_object_copy(bmain, ob);
- m_mesh_ob->curve_cache = (CurveCache *)MEM_callocN(
+ m_mesh_ob->runtime.curve_cache = (CurveCache *)MEM_callocN(
sizeof(CurveCache),
"CurveCache for AbcMBallWriter");
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc
index 95d06fc5efe..bf41b44e418 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_nurbs.cc
@@ -130,8 +130,8 @@ void AbcNurbsWriter::do_write()
Curve *curve = static_cast<Curve *>(m_object->data);
ListBase *nulb;
- if (m_object->curve_cache->deformed_nurbs.first != NULL) {
- nulb = &m_object->curve_cache->deformed_nurbs;
+ if (m_object->runtime.curve_cache->deformed_nurbs.first != NULL) {
+ nulb = &m_object->runtime.curve_cache->deformed_nurbs;
}
else {
nulb = BKE_curve_nurbs_get(curve);
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 90c0016d0ed..f9ad1de8015 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -49,9 +49,6 @@ void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
void BLF_batch_reset(void); /* call when changing opengl context. */
-void BLF_antialias_set(bool enabled);
-bool BLF_antialias_get(void);
-
void BLF_cache_clear(void);
int BLF_load(const char *name) ATTR_NONNULL();
@@ -232,6 +229,7 @@ void BLF_state_print(int fontid);
#define BLF_ASPECT (1 << 5)
#define BLF_HINTING (1 << 6)
#define BLF_WORD_WRAP (1 << 7)
+#define BLF_MONOCHROME (1 << 8) /* no-AA */
#define BLF_DRAW_STR_DUMMY_MAX 1024
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 5dd692d3855..8e3f42e4d27 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -85,7 +85,6 @@ static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
static int global_font_default = -1;
static int global_font_points = 11;
static int global_font_dpi = 72;
-static bool global_use_antialias = true;
/* XXX, should these be made into global_font_'s too? */
int blf_mono_font = -1;
@@ -190,16 +189,6 @@ int BLF_default(void)
return global_font_default;
}
-void BLF_antialias_set(bool enabled)
-{
- global_use_antialias = enabled;
-}
-
-bool BLF_antialias_get(void)
-{
- return global_use_antialias;
-}
-
int BLF_load(const char *name)
{
FontBLF *font;
@@ -594,24 +583,24 @@ static void blf_draw_gl__start(FontBLF *font)
if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
return; /* glyphs will be translated individually and batched. */
- gpuPushMatrix();
+ GPU_matrix_push();
if (font->flags & BLF_MATRIX)
- gpuMultMatrix(font->m);
+ GPU_matrix_mul(font->m);
- gpuTranslate3fv(font->pos);
+ GPU_matrix_translate_3fv(font->pos);
if (font->flags & BLF_ASPECT)
- gpuScale3fv(font->aspect);
+ GPU_matrix_scale_3fv(font->aspect);
if (font->flags & BLF_ROTATION)
- gpuRotate2D(RAD2DEG(font->angle));
+ GPU_matrix_rotate_2d(RAD2DEG(font->angle));
}
static void blf_draw_gl__end(FontBLF *font)
{
if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
- gpuPopMatrix();
+ GPU_matrix_pop();
}
void BLF_draw_ex(
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index b3ab36f7bcc..f7a926275a9 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -91,31 +91,31 @@ static SpinLock ft_lib_mutex;
**/
static void blf_batch_draw_init(void)
{
- Gwn_VertFormat format = {0};
- g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat format = {0};
+ g_batch.pos_loc = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ g_batch.tex_loc = GPU_vertformat_attr_add(&format, "tex", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ g_batch.col_loc = GPU_vertformat_attr_add(&format, "col", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
- GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
+ g_batch.verts = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
+ GPU_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
g_batch.glyph_len = 0;
- g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
+ g_batch.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, g_batch.verts, NULL, GPU_BATCH_OWNS_VBO);
}
static void blf_batch_draw_exit(void)
{
- GWN_BATCH_DISCARD_SAFE(g_batch.batch);
+ GPU_BATCH_DISCARD_SAFE(g_batch.batch);
}
void blf_batch_draw_vao_clear(void)
{
if (g_batch.batch) {
- gwn_batch_vao_cache_clear(g_batch.batch);
+ GPU_batch_vao_cache_clear(g_batch.batch);
}
}
@@ -133,7 +133,8 @@ void blf_batch_draw_begin(FontBLF *font)
if (simple_shader) {
/* Offset is applied to each glyph. */
- copy_v2_v2(g_batch.ofs, font->pos);
+ g_batch.ofs[0] = floorf(font->pos[0]);
+ g_batch.ofs[1] = floorf(font->pos[1]);
}
else {
/* Offset is baked in modelview mat. */
@@ -142,15 +143,15 @@ void blf_batch_draw_begin(FontBLF *font)
if (g_batch.active) {
float gpumat[4][4];
- gpuGetModelViewMatrix(gpumat);
+ GPU_matrix_model_view_get(gpumat);
bool mat_changed = (memcmp(gpumat, g_batch.mat, sizeof(g_batch.mat)) != 0);
if (mat_changed) {
/* Modelviewmat is no longer the same.
* Flush cache but with the previous mat. */
- gpuPushMatrix();
- gpuLoadMatrix(g_batch.mat);
+ GPU_matrix_push();
+ GPU_matrix_set(g_batch.mat);
}
/* flush cache if config is not the same. */
@@ -165,7 +166,7 @@ void blf_batch_draw_begin(FontBLF *font)
}
if (mat_changed) {
- gpuPopMatrix();
+ GPU_matrix_pop();
/* Save for next memcmp. */
memcpy(g_batch.mat, gpumat, sizeof(g_batch.mat));
}
@@ -190,20 +191,20 @@ void blf_batch_draw(void)
UI_widgetbase_draw_cache_flush();
GPU_texture_bind(g_batch.tex_bind_state, 0);
- GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len);
- GWN_vertbuf_use(g_batch.verts); /* send data */
+ GPU_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len);
+ GPU_vertbuf_use(g_batch.verts); /* send data */
GPUBuiltinShader shader = (g_batch.simple_shader) ? GPU_SHADER_TEXT_SIMPLE : GPU_SHADER_TEXT;
- GWN_batch_program_set_builtin(g_batch.batch, shader);
- GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
- GWN_batch_draw(g_batch.batch);
+ GPU_batch_program_set_builtin(g_batch.batch, shader);
+ GPU_batch_uniform_1i(g_batch.batch, "glyph", 0);
+ GPU_batch_draw(g_batch.batch);
GPU_blend(false);
/* restart to 1st vertex data pointers */
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
- GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
g_batch.glyph_len = 0;
}
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 8dc11443124..5b1a382e368 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -269,7 +269,6 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
GlyphBLF *g;
FT_Error err;
FT_Bitmap bitmap, tempbitmap;
- const bool is_sharp = !BLF_antialias_get();
int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
FT_BBox bbox;
unsigned int key;
@@ -294,10 +293,12 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
if (font->flags & BLF_HINTING)
flags &= ~FT_LOAD_NO_HINTING;
- if (is_sharp)
+ if (font->flags & BLF_MONOCHROME) {
err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
- else
+ }
+ else {
err = FT_Load_Glyph(font->face, (FT_UInt)index, flags);
+ }
if (err) {
BLI_spin_unlock(font->ft_lib_mutex);
@@ -307,7 +308,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
/* get the glyph. */
slot = font->face->glyph;
- if (is_sharp) {
+ if (font->flags & BLF_MONOCHROME) {
err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
/* Convert result from 1 bit per pixel to 8 bit per pixel */
@@ -336,7 +337,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
g->height = (int)bitmap.rows;
if (g->width && g->height) {
- if (is_sharp) {
+ if (font->flags & BLF_MONOCHROME) {
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
int i;
for (i = 0; i < (g->width * g->height); i++) {
@@ -382,10 +383,10 @@ static void blf_texture_draw(const unsigned char color[4], const float uv[2][2],
{
/* Only one vertex per glyph, geometry shader expand it into a quad. */
/* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
- copy_v4_fl4(GWN_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1],
+ copy_v4_fl4(GPU_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1],
x2 + g_batch.ofs[0], y2 + g_batch.ofs[1]);
- copy_v4_v4(GWN_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
- copy_v4_v4_uchar(GWN_vertbuf_raw_step(&g_batch.col_step), color);
+ copy_v4_v4(GPU_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
+ copy_v4_v4_uchar(GPU_vertbuf_raw_step(&g_batch.col_step), color);
g_batch.glyph_len++;
/* Flush cache if it's full. */
if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) {
@@ -427,8 +428,8 @@ static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
{
rect->xmin = floorf(x + g->pos_x);
rect->xmax = rect->xmin + (float)g->width;
- rect->ymin = y + g->pos_y;
- rect->ymax = y + g->pos_y - (float)g->height;
+ rect->ymin = floorf(y + g->pos_y);
+ rect->ymax = rect->ymin - (float)g->height;
}
void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 999773d0212..265835f4c75 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -31,16 +31,16 @@
#ifndef __BLF_INTERNAL_TYPES_H__
#define __BLF_INTERNAL_TYPES_H__
-#include "../../../intern/gawain/gawain/gwn_vertex_buffer.h"
+#include "GPU_vertex_buffer.h"
#include "GPU_texture.h"
#define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */
typedef struct BatchBLF {
struct FontBLF *font; /* can only batch glyph from the same font */
- struct Gwn_Batch *batch;
- struct Gwn_VertBuf *verts;
- struct Gwn_VertBufRaw pos_step, tex_step, col_step;
+ struct GPUBatch *batch;
+ struct GPUVertBuf *verts;
+ struct GPUVertBufRaw pos_step, tex_step, col_step;
unsigned int pos_loc, tex_loc, col_loc;
unsigned int glyph_len;
float ofs[2]; /* copy of font->pos */
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 106866aff0a..263a54eab4e 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -201,6 +201,7 @@ void BKE_pose_remove_group_index(struct bPose *pose, const int index);
void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
/* for proxy */
+void BKE_pose_copyesult_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom);
bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void BKE_pose_rest(struct bPose *pose);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index b16e8c17a12..9e8e7f7b724 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -153,7 +153,7 @@ char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr,
char *base_path);
/* ************************************* */
-/* Gwn_Batch AnimData API */
+/* GPUBatch AnimData API */
/* Define for callback looper used in BKE_animdata_main_cb */
typedef void (*ID_AnimData_Edit_Callback)(struct ID *id, struct AnimData *adt, void *user_data);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index e1bfb05fb59..17329beb325 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -100,7 +100,7 @@ void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
-void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
+void BKE_pose_rebuild(struct Main *bmain, struct Object *ob, struct bArmature *arm, const bool do_id_user);
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
@@ -231,9 +231,16 @@ void BKE_pose_eval_flush(
struct Scene *scene,
struct Object *ob);
-void BKE_pose_eval_proxy_copy(
+void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph,
+ struct Object *object);
+
+void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph,
+ struct Object *object);
+
+void BKE_pose_eval_proxy_copy_bone(
struct Depsgraph *depsgraph,
- struct Object *ob);
+ struct Object *object,
+ int pchan_index);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 8707fe3e11b..79ae904c73d 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 20
+#define BLENDER_SUBVERSION 21
/* Several breakages with 280, e.g. collections vs layers */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index eda1c51bbc2..42399835b53 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -28,11 +28,14 @@
*/
enum eCurveMappingPreset;
+struct bContext;
struct Brush;
+struct Paint;
struct ImBuf;
struct ImagePool;
struct Main;
struct Scene;
+struct ToolSettings;
struct UnifiedPaintSettings;
// enum eCurveMappingPreset;
@@ -45,14 +48,18 @@ void BKE_brush_system_exit(void);
/* datablock functions */
void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode);
+struct Brush *BKE_brush_add_gpencil(struct Main *bmain, struct ToolSettings *ts, const char *name);
+void BKE_brush_init_gpencil_settings(struct Brush *brush);
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode);
void BKE_brush_copy_data(struct Main *bmain, struct Brush *brush_dst, const struct Brush *brush_src, const int flag);
struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
-void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
void BKE_brush_sculpt_reset(struct Brush *brush);
+void BKE_brush_gpencil_presets(struct bContext *C);
+struct Brush *BKE_brush_getactive_gpencil(struct ToolSettings *ts);
+struct Paint *BKE_brush_get_gpencil_paint(struct ToolSettings *ts);
/* image icon function */
struct ImBuf *get_brush_icon(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index d79a7eae53e..a0780a5be54 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -102,7 +102,7 @@ typedef struct BVHTreeFromMesh {
*/
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, struct BMEditMesh *em,
- float epsilon, int tree_type, int axis);
+ float epsilon, int tree_type, int axis, BVHCache **bvh_cache);
BVHTree *bvhtree_from_editmesh_verts_ex(
BVHTreeFromEditMesh *data, struct BMEditMesh *em,
const BLI_bitmap *mask, int verts_num_active,
@@ -115,7 +115,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, struct BMEditMesh *em,
- float epsilon, int tree_type, int axis);
+ float epsilon, int tree_type, int axis, BVHCache **bvh_cache);
BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTreeFromEditMesh *data, struct BMEditMesh *em,
const BLI_bitmap *edges_mask, int edges_num_active,
@@ -190,7 +190,9 @@ enum {
BVHTREE_FROM_LOOSEVERTS = 4,
BVHTREE_FROM_LOOSEEDGES = 5,
- BVHTREE_FROM_EM_LOOPTRI = 6,
+ BVHTREE_FROM_EM_VERTS = 6,
+ BVHTREE_FROM_EM_EDGES = 7,
+ BVHTREE_FROM_EM_LOOPTRI = 8,
};
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 6703d828bf0..28dcf9cb127 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -65,9 +65,7 @@ struct bPoseChannel;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
-struct bGPDpalette;
-struct bGPDpalettecolor;
-struct bGPDbrush;
+struct Brush;
struct wmWindow;
struct wmWindowManager;
struct RenderEngineType;
@@ -120,6 +118,10 @@ enum {
CTX_MODE_PAINT_TEXTURE,
CTX_MODE_PARTICLE,
CTX_MODE_OBJECT,
+ CTX_MODE_GPENCIL_PAINT,
+ CTX_MODE_GPENCIL_EDIT,
+ CTX_MODE_GPENCIL_SCULPT,
+ CTX_MODE_GPENCIL_WEIGHT,
CTX_MODE_NUM /* must be last */
};
@@ -185,7 +187,7 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */
void CTX_wm_area_set(bContext *C, struct ScrArea *sa);
void CTX_wm_region_set(bContext *C, struct ARegion *region);
void CTX_wm_menu_set(bContext *C, struct ARegion *menu);
-void CTX_wm_gizmo_group_set(bContext *C, struct wmGizmoGroup *mgroup);
+void CTX_wm_gizmo_group_set(bContext *C, struct wmGizmoGroup *gzgroup);
const char *CTX_wm_operator_poll_msg_get(struct bContext *C);
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg);
@@ -313,9 +315,7 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
struct bGPdata *CTX_data_gpencil_data(const bContext *C);
struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
-struct bGPDpalette *CTX_data_active_gpencil_palette(const bContext *C);
-struct bGPDpalettecolor *CTX_data_active_gpencil_palettecolor(const bContext *C);
-struct bGPDbrush *CTX_data_active_gpencil_brush(const bContext *C);
+struct Brush *CTX_data_active_gpencil_brush(const bContext *C);
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);
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 14a754b708e..690a42894f2 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -93,6 +93,7 @@ void BKE_editmesh_free(BMEditMesh *em);
void BKE_editmesh_color_free(BMEditMesh *em);
void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3];
+void BKE_editmesh_lnorspace_update(BMEditMesh *em);
/* editderivedmesh.c */
/* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3a951b7860d..b7bef9bbf4e 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -31,25 +31,45 @@
* \author Joshua Leung
*/
+struct CurveMapping;
+struct Depsgraph;
+struct GpencilModifierData;
struct ToolSettings;
struct ListBase;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
+struct bGPDspoint;
struct bGPDstroke;
+struct Material;
struct bGPDpalette;
struct bGPDpalettecolor;
struct Main;
+struct BoundBox;
+struct Brush;
+struct Object;
+struct bDeformGroup;
+struct SimplifyGpencilModifierData;
+struct InstanceGpencilModifierData;
+struct LatticeGpencilModifierData;
+
+struct MDeformVert;
+struct MDeformWeight;
/* ------------ Grease-Pencil API ------------------ */
+void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
+void BKE_gpencil_free_stroke_weights(struct bGPDstroke *gps);
void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
void BKE_gpencil_free_layers(struct ListBase *list);
-void BKE_gpencil_free_brushes(struct ListBase *list);
-void BKE_gpencil_free_palettes(struct ListBase *list);
-void BKE_gpencil_free(struct bGPdata *gpd, bool free_palettes);
+bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *derived_gpf);
+void BKE_gpencil_free_derived_frames(struct bGPdata *gpd);
+void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
+
+void BKE_gpencil_batch_cache_dirty(struct bGPdata *gpd);
+void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
void BKE_gpencil_stroke_sync_selection(struct bGPDstroke *gps);
@@ -60,21 +80,37 @@ struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[])
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src);
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src);
-void BKE_gpencil_copy_data(struct Main *bmain, struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag);
+void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
+struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src);
+
+void BKE_gpencil_copy_data(struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag);
+struct bGPdata *BKE_gpencil_copy(struct Main *bmain, const struct bGPdata *gpd);
struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy);
void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local);
void BKE_gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
-struct bGPDpalette *BKE_gpencil_palette_addnew(struct bGPdata *gpd, const char *name, bool setactive);
-struct bGPDpalette *BKE_gpencil_palette_duplicate(const struct bGPDpalette *palette_src);
-struct bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(struct bGPDpalette *palette, const char *name, bool setactive);
+/* materials */
+void BKE_gpencil_material_index_remove(struct bGPdata *gpd, int index);
+void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len);
+int BKE_gpencil_get_material_index(struct Object *ob, struct Material *ma);
-struct bGPDbrush *BKE_gpencil_brush_addnew(struct ToolSettings *ts, const char *name, bool setactive);
-struct bGPDbrush *BKE_gpencil_brush_duplicate(const struct bGPDbrush *brush_src);
-void BKE_gpencil_brush_init_presets(struct ToolSettings *ts);
+/* statistics functions */
+void BKE_gpencil_stats_update(struct bGPdata *gpd);
+/* Utilities for creating and populating GP strokes */
+/* - Number of values defining each point in the built-in data
+ * buffers for primitives (e.g. 2D Monkey)
+ */
+#define GP_PRIM_DATABUF_SIZE 5
+
+void BKE_gpencil_stroke_add_points(
+ struct bGPDstroke *gps,
+ const float *array, const int totpoints,
+ const float mat[4][4]);
+
+struct bGPDstroke *BKE_gpencil_add_stroke(struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness);
/* Stroke and Fill - Alpha Visibility Threshold */
#define GPENCIL_ALPHA_OPACITY_THRESH 0.001f
@@ -103,20 +139,40 @@ struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd);
void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
-struct bGPDbrush *BKE_gpencil_brush_getactive(struct ToolSettings *ts);
-void BKE_gpencil_brush_setactive(struct ToolSettings *ts, struct bGPDbrush *active);
-void BKE_gpencil_brush_delete(struct ToolSettings *ts, struct bGPDbrush *brush);
-
-struct bGPDpalette *BKE_gpencil_palette_getactive(struct bGPdata *gpd);
-void BKE_gpencil_palette_setactive(struct bGPdata *gpd, struct bGPDpalette *active);
-void BKE_gpencil_palette_delete(struct bGPdata *gpd, struct bGPDpalette *palette);
-void BKE_gpencil_palette_change_strokes(struct bGPdata *gpd);
-
-struct bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(struct bGPDpalette *palette);
-void BKE_gpencil_palettecolor_setactive(struct bGPDpalette *palette, struct bGPDpalettecolor *active);
-void BKE_gpencil_palettecolor_delete(struct bGPDpalette *palette, struct bGPDpalettecolor *palcolor);
-struct bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(struct bGPDpalette *palette, char *name);
-void BKE_gpencil_palettecolor_changename(struct bGPdata *gpd, char *oldname, const char *newname);
-void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name);
+struct Material *BKE_gpencil_get_material_from_brush(struct Brush *brush);
+struct Material *BKE_gpencil_material_ensure(struct Main *bmain, struct Object *ob);
+
+/* object boundbox */
+bool BKE_gpencil_stroke_minmax(
+ const struct bGPDstroke *gps, const bool use_select,
+ float r_min[3], float r_max[3]);
+
+struct BoundBox *BKE_gpencil_boundbox_get(struct Object *ob);
+void BKE_gpencil_centroid_3D(struct bGPdata *gpd, float r_centroid[3]);
+
+/* vertex groups */
+float BKE_gpencil_vgroup_use_index(struct MDeformVert *dvert, int index);
+void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+struct MDeformWeight *BKE_gpencil_vgroup_add_point_weight(struct MDeformVert *dvert, int index, float weight);
+bool BKE_gpencil_vgroup_remove_point_weight(struct MDeformVert *dvert, int index);
+void BKE_gpencil_stroke_weights_duplicate(struct bGPDstroke *gps_src, struct bGPDstroke *gps_dst);
+
+/* GPencil geometry evaluation */
+void BKE_gpencil_eval_geometry(struct Depsgraph *depsgraph, struct bGPdata *gpd);
+
+/* stroke geometry utilities */
+void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
+void BKE_gpencil_simplify_stroke(struct bGPDstroke *gps, float factor);
+void BKE_gpencil_simplify_fixed(struct bGPDstroke *gps);
+
+void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]);
+
+bool BKE_gpencil_smooth_stroke(struct bGPDstroke *gps, int i, float inf);
+bool BKE_gpencil_smooth_stroke_strength(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_smooth_stroke_thickness(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_smooth_stroke_uv(struct bGPDstroke *gps, int point_index, float influence);
+
+void BKE_gpencil_get_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
+float BKE_gpencil_multiframe_falloff_calc(struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff);
#endif /* __BKE_GPENCIL_H__ */
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
new file mode 100644
index 00000000000..be27560bbf2
--- /dev/null
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -0,0 +1,256 @@
+/*
+ * ***** 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: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_GPENCIL_MODIFIER_H__
+#define __BKE_GPENCIL_MODIFIER_H__
+
+/** \file BKE_gpencil_modifier.h
+ * \ingroup bke
+ */
+
+#include "DNA_gpencil_modifier_types.h" /* needed for all enum typdefs */
+#include "BLI_compiler_attrs.h"
+#include "BKE_customdata.h"
+
+struct ID;
+struct Depsgraph;
+struct DerivedMesh;
+struct bContext; /* NOTE: bakeModifier() - called from UI - needs to create new datablocks, hence the need for this */
+struct Mesh;
+struct Object;
+struct Scene;
+struct ViewLayer;
+struct ListBase;
+struct bArmature;
+struct Main;
+struct GpencilModifierData;
+struct BMEditMesh;
+struct DepsNodeHandle;
+struct bGPDlayer;
+struct bGPDframe;
+struct bGPDstroke;
+struct ModifierUpdateDepsgraphContext;
+
+#define GPENCIL_MODIFIER_ACTIVE(_md, _is_render) (((_md->mode & eGpencilModifierMode_Realtime) && (_is_render == false)) || \
+ ((_md->mode & eGpencilModifierMode_Render) && (_is_render == true)))
+#define GPENCIL_MODIFIER_EDIT(_md, _is_edit) (((_md->mode & eGpencilModifierMode_Editmode) == 0) && (_is_edit))
+
+typedef enum {
+ /* Should not be used, only for None modifier type */
+ eGpencilModifierTypeType_None,
+
+ /* grease pencil modifiers */
+ eGpencilModifierTypeType_Gpencil,
+} GpencilModifierTypeType;
+
+typedef enum {
+ eGpencilModifierTypeFlag_SupportsMapping = (1 << 0),
+ eGpencilModifierTypeFlag_SupportsEditmode = (1 << 1),
+
+ /* For modifiers that support editmode this determines if the
+ * modifier should be enabled by default in editmode. This should
+ * only be used by modifiers that are relatively speedy and
+ * also generally used in editmode, otherwise let the user enable
+ * it by hand.
+ */
+ eGpencilModifierTypeFlag_EnableInEditmode = (1 << 2),
+
+ /* For modifiers that require original data and so cannot
+ * be placed after any non-deformative modifier.
+ */
+ eGpencilModifierTypeFlag_RequiresOriginalData = (1 << 3),
+
+ /* max one per type */
+ eGpencilModifierTypeFlag_Single = (1 << 4),
+
+ /* can't be added manually by user */
+ eGpencilModifierTypeFlag_NoUserAdd = (1 << 5),
+} GpencilModifierTypeFlag;
+
+/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
+typedef void(*GreasePencilObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
+typedef void(*GreasePencilIDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
+typedef void(*GreasePencilTexWalkFunc)(void *userData, struct Object *ob, struct GpencilModifierData *md, const char *propname);
+
+typedef struct GpencilModifierTypeInfo {
+ /* The user visible name for this modifier */
+ char name[32];
+
+ /* The DNA struct name for the modifier data type, used to
+ * write the DNA data out.
+ */
+ char struct_name[32];
+
+ /* The size of the modifier data type, used by allocation. */
+ int struct_size;
+
+ GpencilModifierType type;
+ GpencilModifierTypeFlag flags;
+
+
+ /********************* Non-optional functions *********************/
+
+ /* Copy instance data for this modifier type. Should copy all user
+ * level settings to the target modifier.
+ */
+ void (*copyData)(const struct GpencilModifierData *md, struct GpencilModifierData *target);
+
+ /* Callback for GP "stroke" modifiers that operate on the
+ * shape and parameters of the provided strokes (e.g. Thickness, Noise, etc.)
+ *
+ * The gpl parameter contains the GP layer that the strokes come from.
+ * While access is provided to this data, you should not directly access
+ * the gpl->frames data from the modifier. Instead, use the gpf parameter
+ * instead.
+ *
+ * The gps parameter contains the GP stroke to operate on. This is usually a copy
+ * of the original (unmodified and saved to files) stroke data.
+ */
+ void (*deformStroke)(struct GpencilModifierData *md, struct Depsgraph *depsgraph,
+ struct Object *ob, struct bGPDlayer *gpl, struct bGPDstroke *gps);
+
+ /* Callback for GP "geometry" modifiers that create extra geometry
+ * in the frame (e.g. Array)
+ *
+ * The gpf parameter contains the GP frame/strokes to operate on. This is
+ * usually a copy of the original (unmodified and saved to files) stroke data.
+ * Modifiers should only add any generated strokes to this frame (and not one accessed
+ * via the gpl parameter).
+ *
+ * The modifier_index parameter indicates where the modifier is
+ * in the modifier stack in relation to other modifiers.
+ */
+ void (*generateStrokes)(struct GpencilModifierData *md, struct Depsgraph *depsgraph,
+ struct Object *ob, struct bGPDlayer *gpl, struct bGPDframe *gpf);
+
+ /* Bake-down GP modifier's effects into the GP datablock.
+ *
+ * This gets called when the user clicks the "Apply" button in the UI.
+ * As such, this callback needs to go through all layers/frames in the
+ * datablock, mutating the geometry and/or creating new datablocks/objects
+ */
+ void (*bakeModifier)(struct Main *bmain, struct Depsgraph *depsgraph,
+ struct GpencilModifierData *md, struct Object *ob);
+
+ /********************* Optional functions *********************/
+
+ /* Initialize new instance data for this modifier type, this function
+ * should set modifier variables to their default values.
+ *
+ * This function is optional.
+ */
+ void (*initData)(struct GpencilModifierData *md);
+
+ /* Free internal modifier data variables, this function should
+ * not free the md variable itself.
+ *
+ * This function is optional.
+ */
+ void (*freeData)(struct GpencilModifierData *md);
+
+ /* Return a boolean value indicating if this modifier is able to be
+ * calculated based on the modifier data. This is *not* regarding the
+ * md->flag, that is tested by the system, this is just if the data
+ * validates (for example, a lattice will return false if the lattice
+ * object is not defined).
+ *
+ * This function is optional (assumes never disabled if not present).
+ */
+ bool (*isDisabled)(struct GpencilModifierData *md, int userRenderParams);
+
+ /* Add the appropriate relations to the dependency graph.
+ *
+ * This function is optional.
+ */
+ void (*updateDepsgraph)(struct GpencilModifierData *md,
+ const struct ModifierUpdateDepsgraphContext *ctx);
+
+ /* Should return true if the modifier needs to be recalculated on time
+ * changes.
+ *
+ * This function is optional (assumes false if not present).
+ */
+ bool (*dependsOnTime)(struct GpencilModifierData *md);
+
+
+ /* Should call the given walk function on with a pointer to each Object
+ * pointer that the modifier data stores. This is used for linking on file
+ * load and for unlinking objects or forwarding object references.
+ *
+ * This function is optional.
+ */
+ void (*foreachObjectLink)(struct GpencilModifierData *md, struct Object *ob,
+ GreasePencilObjectWalkFunc walk, void *userData);
+
+ /* Should call the given walk function with a pointer to each ID
+ * pointer (i.e. each datablock pointer) that the modifier data
+ * stores. This is used for linking on file load and for
+ * unlinking datablocks or forwarding datablock references.
+ *
+ * This function is optional. If it is not present, foreachObjectLink
+ * will be used.
+ */
+ void (*foreachIDLink)(struct GpencilModifierData *md, struct Object *ob,
+ GreasePencilIDWalkFunc walk, void *userData);
+
+ /* Should call the given walk function for each texture that the
+ * modifier data stores. This is used for finding all textures in
+ * the context for the UI.
+ *
+ * This function is optional. If it is not present, it will be
+ * assumed the modifier has no textures.
+ */
+ void (*foreachTexLink)(struct GpencilModifierData *md, struct Object *ob,
+ GreasePencilTexWalkFunc walk, void *userData);
+} GpencilModifierTypeInfo;
+
+void BKE_gpencil_instance_modifier_instance_tfm(struct InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4]);
+
+/* Initialize modifier's global data (type info and some common global storages). */
+void BKE_gpencil_modifier_init(void);
+
+const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type);
+struct GpencilModifierData *BKE_gpencil_modifier_new(int type);
+void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag);
+void BKE_gpencil_modifier_free(struct GpencilModifierData *md);
+bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd);
+bool BKE_gpencil_modifier_dependsOnTime(struct GpencilModifierData *md);
+struct GpencilModifierData *BKE_gpencil_modifiers_findByType(struct Object *ob, GpencilModifierType type);
+struct GpencilModifierData *BKE_gpencil_modifiers_findByName(struct Object *ob, const char *name);
+void BKE_gpencil_modifier_copyData_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst);
+void BKE_gpencil_modifier_copyData(struct GpencilModifierData *md, struct GpencilModifierData *target);
+void BKE_gpencil_modifier_copyData_ex(struct GpencilModifierData *md, struct GpencilModifierData *target, const int flag);
+void BKE_gpencil_modifiers_foreachIDLink(struct Object *ob, GreasePencilIDWalkFunc walk, void *userData);
+void BKE_gpencil_modifiers_foreachTexLink(struct Object *ob, GreasePencilTexWalkFunc walk, void *userData);
+
+bool BKE_gpencil_has_geometry_modifiers(struct Object *ob);
+
+void BKE_gpencil_stroke_modifiers(
+ struct Depsgraph *depsgraph, struct Object *ob,
+ struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps, bool is_render);
+void BKE_gpencil_geometry_modifiers(
+ struct Depsgraph *depsgraph, struct Object *ob,
+ struct bGPDlayer *gpl, struct bGPDframe *gpf, bool is_render);
+
+void BKE_gpencil_lattice_init(struct Object *ob);
+void BKE_gpencil_lattice_clear(struct Object *ob);
+
+#endif /* __BKE_GPENCIL_MODIFIER_H__ */
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 22897d2ea80..7a5262e0a14 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -43,7 +43,10 @@ enum {
ICON_DATA_PREVIEW,
/** 2D triangles: obj is #Icon_Geom */
ICON_DATA_GEOM,
+ /** Studiolight */
ICON_DATA_STUDIOLIGHT,
+ /** GPencil Layer color preview (annotations): obj is #bGPDlayer */
+ ICON_DATA_GPLAYER,
};
struct Icon {
@@ -79,6 +82,7 @@ struct ImBuf;
struct PreviewImage;
struct ID;
struct StudioLight;
+struct bGPDlayer;
enum eIconSizes;
@@ -87,6 +91,9 @@ void BKE_icons_init(int first_dyn_id);
/* return icon id for library object or create new icon if not found */
int BKE_icon_id_ensure(struct ID *id);
+/* return icon id for Grease Pencil layer (color preview) or create new icon if not found */
+int BKE_icon_gplayer_color_ensure(struct bGPDlayer *gpl);
+
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
/* retrieve icon for id */
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index c2ac5e98f76..67e6a32edfd 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -54,7 +54,6 @@ void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
-struct LatticeDeformData;
struct LatticeDeformData *init_latt_deform(struct Object *oblatt, struct Object *ob) ATTR_WARN_UNUSED_RESULT;
void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index aaf53a2396b..16e05cd136a 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -79,12 +79,14 @@ enum {
LIB_ID_COPY_NO_PROXY_CLEAR = 1 << 16, /* Object only, needed by make_local code. */
LIB_ID_COPY_NO_PREVIEW = 1 << 17, /* Do not copy preview data, when supported. */
LIB_ID_COPY_CACHES = 1 << 18, /* Copy runtime data caches. */
- /* XXX TODO Do we want to keep that? would rather try to get rid of it... */
- LIB_ID_COPY_ACTIONS = 1 << 19, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */
- LIB_ID_COPY_KEEP_LIB = 1 << 20, /* Keep the library pointer when copying datablock outside of bmain. */
- LIB_ID_COPY_NO_ANIMDATA = 1 << 21, /* Don't copy id->adt, used by ID datablock localization routines. */
- LIB_ID_COPY_SHAPEKEY = 1 << 22, /* EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
- LIB_ID_COPY_CD_REFERENCE = 1 << 23,
+ LIB_ID_COPY_NO_ANIMDATA = 1 << 19, /* Don't copy id->adt, used by ID datablock localization routines. */
+ LIB_ID_COPY_CD_REFERENCE = 1 << 20, /* Mesh: Reference CD data layers instead of doing real copy. */
+
+ /* XXX Hackish/not-so-nice specific behaviors needed for some corner cases.
+ * Ideally we should not have those, but we need them for now... */
+ LIB_ID_COPY_ACTIONS = 1 << 24, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */
+ LIB_ID_COPY_KEEP_LIB = 1 << 25, /* Keep the library pointer when copying datablock outside of bmain. */
+ LIB_ID_COPY_SHAPEKEY = 1 << 26, /* EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
};
void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index c85017a2216..1ca8928c61d 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -54,11 +54,13 @@ void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
+struct Material *BKE_material_add_gpencil(struct Main *bmain, const char *name);
void BKE_material_copy_data(struct Main *bmain, struct Material *ma_dst, const struct Material *ma_src, const int flag);
struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
struct Material *BKE_material_localize(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
+void BKE_material_init_gpencil_settings(struct Material *ma);
/* UNUSED */
// void automatname(struct Material *);
@@ -87,6 +89,8 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma
bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob);
bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
+struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act);
+
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 104dd2b5cbb..66b0b550744 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -270,6 +270,8 @@ typedef struct MLoopNorSpace {
* - BMLoop pointers. */
struct LinkNode *loops;
char flags;
+
+ void *user_data; /* To be used for extended processing related to loop normal spaces (aka smooth fans). */
} MLoopNorSpace;
/**
* MLoopNorSpace.flags
@@ -285,6 +287,7 @@ typedef struct MLoopNorSpaceArray {
MLoopNorSpace **lspacearr; /* MLoop aligned array */
struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
+ int num_spaces; /* Number of clnors spaces defined in this array. */
struct MemArena *mem;
} MLoopNorSpaceArray;
/**
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index b5b5443574c..1005a50a214 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -50,8 +50,12 @@ typedef struct UvVertMap {
typedef struct UvMapVert {
struct UvMapVert *next;
- unsigned int f;
- unsigned char tfindex, separate, flag;
+ unsigned int poly_index;
+ unsigned short loop_of_poly_index;
+ bool separate;
+ /* Zero-ed by map creation, left for use by specific areas. Is not
+ * initialized to anything. */
+ unsigned char flag;
} UvMapVert;
/* UvElement stores per uv information so that we can quickly access information for a uv.
@@ -63,9 +67,9 @@ typedef struct UvElement {
/* Face the element belongs to */
struct BMLoop *l;
/* index in loop. */
- unsigned short tfindex;
+ unsigned short loop_of_poly_index;
/* Whether this element is the first of coincident elements */
- unsigned char separate;
+ bool separate;
/* general use flag */
unsigned char flag;
/* If generating element map with island sorting, this stores the island index */
@@ -100,9 +104,9 @@ typedef struct MeshElemMap {
/* mapping */
UvVertMap *BKE_mesh_uv_vert_map_create(
- struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert,
- const float limit[2], const bool selected, const bool use_winding);
+ const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopUV *mloopuv,
+ unsigned int totpoly, unsigned int totvert, const float limit[2],
+ const bool selected, const bool use_winding);
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e72c6c14bfb..901822583cb 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -796,6 +796,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c
#define SH_NODE_DISPLACEMENT 198
#define SH_NODE_VECTOR_DISPLACEMENT 199
#define SH_NODE_VOLUME_PRINCIPLED 200
+/* 201..700 occupied by other node types, continue from 701 */
+#define SH_NODE_BSDF_HAIR_PRINCIPLED 701
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -809,7 +811,7 @@ void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
bool ntreeShaderExecTree(struct bNodeTree *ntree, int thread);
struct bNode *ntreeShaderOutputNode(struct bNodeTree *ntree, int target);
-void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat,
+void ntreeGPUMaterialNodes(struct bNodeTree *localtree, struct GPUMaterial *mat,
bool *has_surface_output, bool *has_volume_output);
/** \} */
@@ -944,6 +946,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_PLANETRACKDEFORM 320
#define CMP_NODE_CORNERPIN 321
#define CMP_NODE_SWITCH_VIEW 322
+#define CMP_NODE_CRYPTOMATTE 323
/* channel toggles */
#define CMP_CHAN_RGB 1
@@ -996,6 +999,11 @@ void ntreeCompositOutputFileUniqueLayer(struct ListBase *list, struct bNodeSocke
void ntreeCompositColorBalanceSyncFromLGG(bNodeTree *ntree, bNode *node);
void ntreeCompositColorBalanceSyncFromCDL(bNodeTree *ntree, bNode *node);
+void ntreeCompositCryptomatteSyncFromAdd(bNodeTree *ntree, bNode *node);
+void ntreeCompositCryptomatteSyncFromRemove(bNodeTree *ntree, bNode *node);
+struct bNodeSocket *ntreeCompositCryptomatteAddSocket(struct bNodeTree *ntree, struct bNode *node);
+int ntreeCompositCryptomatteRemoveSocket(struct bNodeTree *ntree, struct bNode *node);
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 0122185fd2a..7d795c25a04 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -37,8 +37,11 @@ extern "C" {
struct Base;
struct Depsgraph;
+struct GpencilModifierData;
struct Scene;
+struct ShaderFxData;
struct ViewLayer;
+struct ID;
struct Object;
struct BoundBox;
struct View3D;
@@ -49,6 +52,7 @@ struct Mesh;
struct RigidBodyWorld;
struct HookModifierData;
struct ModifierData;
+struct HookGpencilModifierData;
#include "DNA_object_enums.h"
@@ -69,13 +73,18 @@ void BKE_object_free_derived_mesh_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
+void BKE_object_modifier_gpencil_hook_reset(struct Object *ob, struct HookGpencilModifierData *hmd);
+bool BKE_object_modifier_gpencil_use_time(struct Object *ob, struct GpencilModifierData *md);
+
+bool BKE_object_shaderfx_use_time(struct Object *ob, struct ShaderFxData *md);
bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
void BKE_object_link_modifiers(struct Scene *scene, struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_modifiers(struct Object *ob, const int flag);
+void BKE_object_free_shaderfx(struct Object *ob, const int flag);
-void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
+void BKE_object_make_proxy(struct Main *bmain, struct Object *ob, struct Object *target, struct Object *gob);
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
@@ -108,6 +117,9 @@ struct Object *BKE_object_add_from(
struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
int type, const char *name, struct Object *ob_src)
ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add_for_data(
+ struct Main *bmain, struct ViewLayer *view_layer,
+ int type, const char *name, struct ID *data, bool do_id_user) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 6ade14b275c..c440a634c9f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -77,7 +77,8 @@ typedef enum ePaintMode {
ePaintTextureProjective = 3,
ePaintTexture2D = 4,
ePaintSculptUV = 5,
- ePaintInvalid = 6
+ ePaintInvalid = 6,
+ ePaintGpencil = 7
} ePaintMode;
/* overlay invalidation */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 78c766f6115..095f442ca50 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -30,7 +30,7 @@
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
-struct Gwn_Batch;
+struct GPUBatch;
struct CCGElem;
struct CCGKey;
struct CCGDerivedMesh;
@@ -131,7 +131,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(
void BKE_pbvh_draw_cb(
PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
- void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data);
+ void (*draw_fn)(void *user_data, struct GPUBatch *batch), void *user_data);
/* PBVH Access */
typedef enum {
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 270ab60c02b..e7a26afadf5 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -130,6 +130,8 @@ int BKE_scene_camera_switch_update(struct Scene *scene);
char *BKE_scene_find_marker_name(struct Scene *scene, int frame);
char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame);
+int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int cfra);
+
/* checks for cycle, returns 1 if it's all OK */
bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce);
@@ -145,6 +147,9 @@ void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph,
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph,
struct Main *bmain);
+void BKE_scene_view_layer_graph_evaluated_ensure(
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer);
+
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
@@ -156,6 +161,7 @@ bool BKE_scene_use_shading_nodes_custom(struct Scene *scene);
bool BKE_scene_use_spherical_stereo(struct Scene *scene);
bool BKE_scene_uses_blender_eevee(const struct Scene *scene);
+bool BKE_scene_uses_blender_opengl(const struct Scene *scene);
bool BKE_scene_uses_cycles(const struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 60981c6e76e..c74170becb4 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -45,6 +45,7 @@ struct ScrVert;
struct SpaceType;
struct TransformOrientation;
struct View3D;
+struct View3DShading;
struct bContext;
struct bContextDataResult;
struct bScreen;
@@ -355,6 +356,8 @@ bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT AT
float BKE_screen_view3d_zoom_to_fac(float camzoom);
float BKE_screen_view3d_zoom_from_fac(float zoomfac);
+void BKE_screen_view3d_shading_init(struct View3DShading *shading);
+
/* screen */
void BKE_screen_free(struct bScreen *sc);
void BKE_screen_area_map_free(struct ScrAreaMap *area_map) ATTR_NONNULL();
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 51f61c8352c..00fd4ded8c6 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -395,7 +395,7 @@ typedef struct SeqLoadInfo {
/* seq_dupli' flags */
-#define SEQ_DUPE_UNIQUE_NAME (1 << 0)
+#define SEQ_DUPE_UNIQUE_NAME (1 << 0) /* WARNING: does NOT work when duplicating Meta strips! */
#define SEQ_DUPE_CONTEXT (1 << 1)
#define SEQ_DUPE_ANIM (1 << 2)
#define SEQ_DUPE_ALL (1 << 3) /* otherwise only selected are copied */
diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h
new file mode 100644
index 00000000000..d2c8cfb457c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_shader_fx.h
@@ -0,0 +1,180 @@
+/*
+ * ***** 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: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_SHADER_FX_H__
+#define __BKE_SHADER_FX_H__
+
+/** \file BKE_shader_fx.h
+ * \ingroup bke
+ */
+
+#include "DNA_shader_fx_types.h" /* needed for all enum typdefs */
+#include "BLI_compiler_attrs.h"
+#include "BKE_customdata.h"
+
+struct ID;
+struct Depsgraph;
+struct DerivedMesh;
+struct Mesh;
+struct Object;
+struct Scene;
+struct ViewLayer;
+struct ListBase;
+struct bArmature;
+struct Main;
+struct ShaderFxData;
+struct DepsNodeHandle;
+struct bGPDlayer;
+struct bGPDframe;
+struct bGPDstroke;
+struct ModifierUpdateDepsgraphContext;
+
+#define SHADER_FX_ACTIVE(_fx, _is_render) (((_fx->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \
+ ((_fx->mode & eShaderFxMode_Render) && (_is_render == true)))
+#define SHADER_FX_EDIT(_fx, _is_edit) (((_fx->mode & eShaderFxMode_Editmode) == 0) && (_is_edit))
+
+typedef enum {
+ /* Should not be used, only for None type */
+ eShaderFxType_NoneType,
+
+ /* grease pencil effects */
+ eShaderFxType_GpencilType,
+} ShaderFxTypeType;
+
+typedef enum {
+ eShaderFxTypeFlag_SupportsEditmode = (1 << 0),
+
+ /* For effects that support editmode this determines if the
+ * effect should be enabled by default in editmode.
+ */
+ eShaderFxTypeFlag_EnableInEditmode = (1 << 2),
+
+ /* max one per type */
+ eShaderFxTypeFlag_Single = (1 << 4),
+
+ /* can't be added manually by user */
+ eShaderFxTypeFlag_NoUserAdd = (1 << 5),
+} ShaderFxTypeFlag;
+
+/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
+typedef void(*ShaderFxObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
+typedef void(*ShaderFxIDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
+typedef void(*ShaderFxTexWalkFunc)(void *userData, struct Object *ob, struct ShaderFxData *fx, const char *propname);
+
+typedef struct ShaderFxTypeInfo {
+ /* The user visible name for this effect */
+ char name[32];
+
+ /* The DNA struct name for the effect data type, used to
+ * write the DNA data out.
+ */
+ char struct_name[32];
+
+ /* The size of the effect data type, used by allocation. */
+ int struct_size;
+
+ ShaderFxTypeType type;
+ ShaderFxTypeFlag flags;
+
+ /* Copy instance data for this effect type. Should copy all user
+ * level settings to the target effect.
+ */
+ void(*copyData)(const struct ShaderFxData *fx, struct ShaderFxData *target);
+
+ /* Initialize new instance data for this effect type, this function
+ * should set effect variables to their default values.
+ *
+ * This function is optional.
+ */
+ void (*initData)(struct ShaderFxData *fx);
+
+ /* Free internal effect data variables, this function should
+ * not free the fx variable itself.
+ *
+ * This function is optional.
+ */
+ void (*freeData)(struct ShaderFxData *fx);
+
+ /* Return a boolean value indicating if this effect is able to be
+ * calculated based on the effect data. This is *not* regarding the
+ * fx->flag, that is tested by the system, this is just if the data
+ * validates (for example, a lattice will return false if the lattice
+ * object is not defined).
+ *
+ * This function is optional (assumes never disabled if not present).
+ */
+ bool (*isDisabled)(struct ShaderFxData *fx, int userRenderParams);
+
+ /* Add the appropriate relations to the dependency graph.
+ *
+ * This function is optional.
+ */
+ void (*updateDepsgraph)(struct ShaderFxData *fx,
+ const struct ModifierUpdateDepsgraphContext *ctx);
+
+ /* Should return true if the effect needs to be recalculated on time
+ * changes.
+ *
+ * This function is optional (assumes false if not present).
+ */
+ bool (*dependsOnTime)(struct ShaderFxData *fx);
+
+
+ /* Should call the given walk function on with a pointer to each Object
+ * pointer that the effect data stores. This is used for linking on file
+ * load and for unlinking objects or forwarding object references.
+ *
+ * This function is optional.
+ */
+ void (*foreachObjectLink)(struct ShaderFxData *fx, struct Object *ob,
+ ShaderFxObjectWalkFunc walk, void *userData);
+
+ /* Should call the given walk function with a pointer to each ID
+ * pointer (i.e. each datablock pointer) that the effect data
+ * stores. This is used for linking on file load and for
+ * unlinking datablocks or forwarding datablock references.
+ *
+ * This function is optional. If it is not present, foreachObjectLink
+ * will be used.
+ */
+ void (*foreachIDLink)(struct ShaderFxData *fx, struct Object *ob,
+ ShaderFxIDWalkFunc walk, void *userData);
+} ShaderFxTypeInfo;
+
+/* Initialize global data (type info and some common global storages). */
+void BKE_shaderfx_init(void);
+
+const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type);
+struct ShaderFxData *BKE_shaderfx_new(int type);
+void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag);
+void BKE_shaderfx_free(struct ShaderFxData *fx);
+bool BKE_shaderfx_unique_name(struct ListBase *shaderfx, struct ShaderFxData *fx);
+bool BKE_shaderfx_dependsOnTime(struct ShaderFxData *fx);
+struct ShaderFxData *BKE_shaderfx_findByType(struct Object *ob, ShaderFxType type);
+struct ShaderFxData *BKE_shaderfx_findByName(struct Object *ob, const char *name);
+void BKE_shaderfx_copyData_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst);
+void BKE_shaderfx_copyData(struct ShaderFxData *fx, struct ShaderFxData *target);
+void BKE_shaderfx_copyData_ex(struct ShaderFxData *fx, struct ShaderFxData *target, const int flag);
+void BKE_shaderfx_foreachIDLink(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData);
+
+bool BKE_shaderfx_has_gpencil(struct Object *ob);
+
+#endif /* __BKE_SHADER_FX_H__ */
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index fee01fa8abb..4a7f29d7190 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -99,7 +99,7 @@ enum StudioLightFlag {
STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE = (1 << 10),
STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 11),
STUDIOLIGHT_UI_EXPANDED = (1 << 13),
-} StudioLightFlag;
+};
#define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE)
#define STUDIOLIGHT_FLAG_ORIENTATIONS (STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_VIEWNORMAL)
diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h
new file mode 100644
index 00000000000..cd1e3adbc21
--- /dev/null
+++ b/source/blender/blenkernel/BKE_subdiv.h
@@ -0,0 +1,214 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_SUBDIV_H__
+#define __BKE_SUBDIV_H__
+
+#include "BLI_sys_types.h"
+
+struct Mesh;
+struct OpenSubdiv_Converter;
+struct OpenSubdiv_Evaluator;
+struct OpenSubdiv_TopologyRefiner;
+
+/** \file BKE_subdiv.h
+ * \ingroup bke
+ * \since July 2018
+ * \author Sergey Sharybin
+ */
+
+typedef enum {
+ SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
+ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
+ SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
+ SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL,
+} eSubdivFVarLinearInterpolation;
+
+typedef struct SubdivSettings {
+ bool is_simple;
+ bool is_adaptive;
+ int level;
+ eSubdivFVarLinearInterpolation fvar_linear_interpolation;
+} SubdivSettings;
+
+/* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
+typedef enum eSubdivStatsValue {
+ SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
+ SUBDIV_STATS_SUBDIV_TO_MESH,
+ SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
+ SUBDIV_STATS_EVALUATOR_CREATE,
+ SUBDIV_STATS_EVALUATOR_REFINE,
+
+ NUM_SUBDIV_STATS_VALUES,
+} eSubdivStatsValue;
+
+typedef struct SubdivStats {
+ union {
+ struct {
+ /* Time spend on creating topology refiner, which includes time
+ * spend on conversion from Blender data to OpenSubdiv data, and
+ * time spend on topology orientation on OpenSubdiv C-API side.
+ */
+ double topology_refiner_creation_time;
+ /* Total time spent in BKE_subdiv_to_mesh(). */
+ double subdiv_to_mesh_time;
+ /* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
+ double subdiv_to_mesh_geometry_time;
+ /* Time spent on evaluator creation from topology refiner. */
+ double evaluator_creation_time;
+ /* Time spent on evaluator->refine(). */
+ double evaluator_refine_time;
+ };
+ double values_[NUM_SUBDIV_STATS_VALUES];
+ };
+
+ /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
+ * called.
+ */
+ double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
+} SubdivStats;
+
+typedef struct Subdiv {
+ /* Settings this subdivision surface is created for.
+ *
+ * It is read-only after assignment in BKE_subdiv_new_from_FOO().
+ */
+ SubdivSettings settings;
+
+ /* Topology refiner includes all the glue logic to feed Blender side
+ * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
+ * drawer.
+ */
+ struct OpenSubdiv_TopologyRefiner *topology_refiner;
+
+ /* CPU side evaluator. */
+ struct OpenSubdiv_Evaluator *evaluator;
+
+ SubdivStats stats;
+} Subdiv;
+
+/* =============================== STATISTICS =============================== */
+
+void BKE_subdiv_stats_init(SubdivStats *stats);
+
+void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
+void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
+
+void BKE_subdiv_stats_print(const SubdivStats *stats);
+
+/* ============================== CONSTRUCTION ============================== */
+
+Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
+ struct OpenSubdiv_Converter *converter);
+
+Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
+ struct Mesh *mesh);
+
+void BKE_subdiv_free(Subdiv *subdiv);
+
+/* ============================= EVALUATION API ============================= */
+
+void BKE_subdiv_eval_begin(Subdiv *subdiv);
+void BKE_subdiv_eval_update_from_mesh(Subdiv *subdiv, const struct Mesh *mesh);
+
+/* Single point queries. */
+
+void BKE_subdiv_eval_limit_point(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3]);
+void BKE_subdiv_eval_limit_point_and_derivatives(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], float dPdu[3], float dPdv[3]);
+void BKE_subdiv_eval_limit_point_and_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], float N[3]);
+void BKE_subdiv_eval_limit_point_and_short_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], short N[3]);
+
+void BKE_subdiv_eval_face_varying(
+ Subdiv *subdiv,
+ const int face_varying_channel,
+ const int ptex_face_index,
+ const float u, const float v,
+ float varying[2]);
+
+/* Patch queries at given resolution.
+ *
+ * Will evaluate patch at uniformly distributed (u, v) coordinates on a grid
+ * of given resolution, producing resolution^2 evaluation points. The order
+ * goes as u in rows, v in columns.
+ */
+
+void BKE_subdiv_eval_limit_patch_resolution_point(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *buffer, const int offset, const int stride);
+void BKE_subdiv_eval_limit_patch_resolution_point_and_derivatives(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *du_buffer, const int du_offset, const int du_stride,
+ void *dv_buffer, const int dv_offset, const int dv_stride);
+void BKE_subdiv_eval_limit_patch_resolution_point_and_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *normal_buffer, const int normal_offset, const int normal_stride);
+void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *normal_buffer, const int normal_offset, const int normal_stride);
+
+/* =========================== SUBDIV TO MESH API =========================== */
+
+typedef struct SubdivToMeshSettings {
+ /* Resolution at which ptex are being evaluated.
+ * This defines how many vertices final mesh will have: every ptex has
+ * resolution^2 vertices.
+ */
+ int resolution;
+} SubdivToMeshSettings;
+
+/* Create real hi-res mesh from subdivision, all geometry is "real". */
+struct Mesh *BKE_subdiv_to_mesh(
+ Subdiv *subdiv,
+ const SubdivToMeshSettings *settings,
+ const struct Mesh *coarse_mesh);
+
+#endif /* __BKE_SUBDIV_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index f532ad9bae3..2640abab15b 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -38,6 +38,8 @@ set(INC
../makesrna
../bmesh
../modifiers
+ ../gpencil_modifiers
+ ../shader_fx
../nodes
../physics
../render/extern/include
@@ -115,6 +117,7 @@ set(SRC
intern/font.c
intern/freestyle.c
intern/gpencil.c
+ intern/gpencil_modifier.c
intern/hair.c
intern/hair_draw.c
intern/icons.c
@@ -183,12 +186,19 @@ set(SRC
intern/seqeffects.c
intern/seqmodifier.c
intern/sequencer.c
+ intern/shader_fx.c
intern/shrinkwrap.c
intern/smoke.c
intern/softbody.c
intern/sound.c
intern/speaker.c
intern/studiolight.c
+ intern/subdiv.c
+ intern/subdiv_converter.c
+ intern/subdiv_converter_mesh.c
+ intern/subdiv_eval.c
+ intern/subdiv_mesh.c
+ intern/subdiv_stats.c
intern/subsurf_ccg.c
intern/suggestions.c
intern/text.c
@@ -256,6 +266,7 @@ set(SRC
BKE_freestyle.h
BKE_global.h
BKE_gpencil.h
+ BKE_gpencil_modifier.h
BKE_hair.h
BKE_icons.h
BKE_idcode.h
@@ -305,12 +316,14 @@ set(SRC
BKE_scene.h
BKE_screen.h
BKE_sequencer.h
+ BKE_shader_fx.h
BKE_shrinkwrap.h
BKE_smoke.h
BKE_softbody.h
BKE_sound.h
BKE_speaker.h
BKE_studiolight.h
+ BKE_subdiv.h
BKE_subsurf.h
BKE_suggestions.h
BKE_text.h
@@ -328,8 +341,9 @@ set(SRC
intern/CCGSubSurf.h
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h
- intern/pbvh_intern.h
intern/data_transfer_intern.h
+ intern/pbvh_intern.h
+ intern/subdiv_converter.h
)
if(WITH_BINRELOC)
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 81b1afa3621..dd5a87a445d 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -40,6 +40,8 @@
#ifdef WITH_OPENSUBDIV
# include "opensubdiv_capi.h"
# include "opensubdiv_converter_capi.h"
+# include "opensubdiv_evaluator_capi.h"
+# include "opensubdiv_topology_refiner_capi.h"
#endif
#include "GPU_glew.h"
@@ -329,7 +331,7 @@ void ccgSubSurf_free(CCGSubSurf *ss)
CCGAllocatorHDL allocator = ss->allocator;
#ifdef WITH_OPENSUBDIV
if (ss->osd_evaluator != NULL) {
- openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+ openSubdiv_deleteEvaluator(ss->osd_evaluator);
}
if (ss->osd_mesh != NULL) {
ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
@@ -341,7 +343,7 @@ void ccgSubSurf_free(CCGSubSurf *ss)
MEM_freeN(ss->osd_coarse_coords);
}
if (ss->osd_topology_refiner != NULL) {
- openSubdiv_deleteTopologyRefinerDescr(ss->osd_topology_refiner);
+ openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner);
}
#endif
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
index 9df1c9021ef..29e327d8973 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_intern.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
@@ -236,7 +236,7 @@ struct CCGSubSurf {
* Refiner is created from the modifier stack and used later from the main
* thread to construct GL mesh to avoid threaded access to GL.
*/
- struct OpenSubdiv_TopologyRefinerDescr *osd_topology_refiner; /* Only used at synchronization stage. */
+ struct OpenSubdiv_TopologyRefiner *osd_topology_refiner; /* Only used at synchronization stage. */
/* Denotes whether osd_mesh is invalid now due to topology changes and needs
* to be reconstructed.
*
@@ -249,7 +249,7 @@ struct CCGSubSurf {
/* ** CPU backend. ** */
/* Limit evaluator, used to evaluate CCG. */
- struct OpenSubdiv_EvaluatorDescr *osd_evaluator;
+ struct OpenSubdiv_Evaluator *osd_evaluator;
/* Next PTex face index, used while CCG synchronization
* to fill in PTex index of CCGFace.
*/
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index 46204898709..98a17ad8009 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -42,6 +42,9 @@
#include "opensubdiv_capi.h"
#include "opensubdiv_converter_capi.h"
+#include "opensubdiv_evaluator_capi.h"
+#include "opensubdiv_gl_mesh_capi.h"
+#include "opensubdiv_topology_refiner_capi.h"
#include "GPU_glew.h"
#include "GPU_extensions.h"
@@ -131,7 +134,6 @@ static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
{
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
OpenSubdiv_Converter converter;
bool result;
if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) {
@@ -140,15 +142,10 @@ static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
/* TODO(sergey): De-duplicate with topology counter at the bottom of
* the file.
*/
- if (ss->osd_topology_refiner != NULL) {
- topology_refiner = ss->osd_topology_refiner;
- }
- else {
- topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
- }
ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
- result = openSubdiv_topologyRefnerCompareConverter(topology_refiner,
- &converter);
+ result = openSubdiv_topologyRefinerCompareWithConverter(
+ ss->osd_topology_refiner,
+ &converter);
ccgSubSurf_converter_free(&converter);
return result;
}
@@ -159,22 +156,13 @@ static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm)
return true;
}
if (ss->osd_topology_refiner != NULL) {
- int levels = openSubdiv_topologyRefinerGetSubdivLevel(
+ const int levels = ss->osd_topology_refiner->getSubdivisionLevel(
ss->osd_topology_refiner);
BLI_assert(ss->osd_mesh_invalid == true);
if (levels != ss->subdivLevels) {
return true;
}
}
- if (ss->osd_mesh != NULL && ss->osd_mesh_invalid == false) {
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner =
- openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
- int levels = openSubdiv_topologyRefinerGetSubdivLevel(topology_refiner);
- BLI_assert(ss->osd_topology_refiner == NULL);
- if (levels != ss->subdivLevels) {
- return true;
- }
- }
if (ss->skip_grids == false) {
return compare_ccg_derivedmesh_topology(ss, dm) == false;
}
@@ -194,13 +182,13 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
/* Reset GPU part. */
ss->osd_mesh_invalid = true;
if (ss->osd_topology_refiner != NULL) {
- openSubdiv_deleteTopologyRefinerDescr(ss->osd_topology_refiner);
+ openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner);
ss->osd_topology_refiner = NULL;
}
/* Reset CPU side. */
if (ss->osd_evaluator != NULL) {
- openSubdiv_deleteEvaluatorDescr(ss->osd_evaluator);
+ openSubdiv_deleteEvaluator(ss->osd_evaluator);
ss->osd_evaluator = NULL;
}
}
@@ -209,10 +197,10 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
{
BLI_assert(ss->meshIFC.numLayers == 3);
- openSubdiv_osdGLMeshUpdateVertexBuffer(ss->osd_mesh,
- (float *) ss->osd_coarse_coords,
- 0,
- ss->osd_num_coarse_coords);
+ ss->osd_mesh->setCoarsePositions(ss->osd_mesh,
+ (float *) ss->osd_coarse_coords,
+ 0,
+ ss->osd_num_coarse_coords);
}
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
@@ -259,9 +247,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
ss->osd_topology_refiner,
- compute_type,
- ss->subdivLevels);
- ss->osd_topology_refiner = NULL;
+ compute_type);
if (UNLIKELY(ss->osd_mesh == NULL)) {
/* Most likely compute device is not available. */
@@ -269,13 +255,12 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
}
ccgSubSurf__updateGLMeshCoords(ss);
- openSubdiv_osdGLMeshRefine(ss->osd_mesh);
- openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+ ss->osd_mesh->refine(ss->osd_mesh);
+ ss->osd_mesh->synchronize(ss->osd_mesh);
ss->osd_coarse_coords_invalid = false;
glBindVertexArray(ss->osd_vao);
- glBindBuffer(GL_ARRAY_BUFFER,
- openSubdiv_getOsdGLMeshVertexBuffer(ss->osd_mesh));
+ ss->osd_mesh->bindVertexBuffer(ss->osd_mesh);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
@@ -289,12 +274,12 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
}
else if (ss->osd_coarse_coords_invalid) {
ccgSubSurf__updateGLMeshCoords(ss);
- openSubdiv_osdGLMeshRefine(ss->osd_mesh);
- openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
+ ss->osd_mesh->refine(ss->osd_mesh);
+ ss->osd_mesh->synchronize(ss->osd_mesh);
ss->osd_coarse_coords_invalid = false;
}
- openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, active_uv_index);
+ ss->osd_mesh->prepareDraw(ss->osd_mesh, use_osd_glsl, active_uv_index);
return true;
}
@@ -305,12 +290,12 @@ void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
if (LIKELY(ss->osd_mesh != NULL)) {
glBindVertexArray(ss->osd_vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
- openSubdiv_getOsdGLMeshPatchIndexBuffer(ss->osd_mesh));
+ ss->osd_mesh->getPatchIndexBuffer(ss->osd_mesh));
- openSubdiv_osdGLMeshBindVertexBuffer(ss->osd_mesh);
+ ss->osd_mesh->bindVertexBuffer(ss->osd_mesh);
glBindVertexArray(ss->osd_vao);
- openSubdiv_osdGLMeshDisplay(ss->osd_mesh, fill_quads,
- start_partition, num_partitions);
+ ss->osd_mesh->drawPatches(ss->osd_mesh, fill_quads,
+ start_partition, num_partitions);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -319,33 +304,21 @@ void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
{
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
if (ss->osd_topology_refiner != NULL) {
- topology_refiner = ss->osd_topology_refiner;
- }
- else if (ss->osd_mesh != NULL) {
- topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
- }
- else {
- return 0;
+ return ss->osd_topology_refiner->getNumFaces(
+ ss->osd_topology_refiner);
}
- return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
+ return 0;
}
/* Get number of vertices in base faces in a particular GL mesh. */
int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
{
- const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
if (ss->osd_topology_refiner != NULL) {
- topology_refiner = ss->osd_topology_refiner;
- }
- else if (ss->osd_mesh != NULL) {
- topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
- }
- else {
- return 0;
+ return ss->osd_topology_refiner->getNumFaceVertices(
+ ss->osd_topology_refiner, face);
}
- return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
+ return 0;
}
void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
@@ -453,17 +426,21 @@ void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss,
static bool opensubdiv_createEvaluator(CCGSubSurf *ss)
{
OpenSubdiv_Converter converter;
- OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_TopologyRefiner *topology_refiner;
if (ss->fMap->numEntries == 0) {
/* OpenSubdiv doesn't support meshes without faces. */
return false;
}
ccgSubSurf_converter_setup_from_ccg(ss, &converter);
- topology_refiner = openSubdiv_createTopologyRefinerDescr(&converter);
+ OpenSubdiv_TopologyRefinerSettings settings;
+ settings.level = ss->subdivLevels;
+ settings.is_adaptive = false;
+ topology_refiner =
+ openSubdiv_createTopologyRefinerFromConverter(
+ &converter, &settings);
ccgSubSurf_converter_free(&converter);
ss->osd_evaluator =
- openSubdiv_createEvaluatorDescr(topology_refiner,
- ss->subdivLevels);
+ openSubdiv_createEvaluatorFromTopologyRefiner(topology_refiner);
if (ss->osd_evaluator == NULL) {
BLI_assert(!"OpenSubdiv initialization failed, should not happen.");
return false;
@@ -519,11 +496,11 @@ static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss)
}
}
- openSubdiv_setEvaluatorCoarsePositions(ss->osd_evaluator,
- (float *)positions,
- 0,
- num_basis_verts);
- openSubdiv_refineEvaluator(ss->osd_evaluator);
+ ss->osd_evaluator->setCoarsePositions(ss->osd_evaluator,
+ (float *)positions,
+ 0,
+ num_basis_verts);
+ ss->osd_evaluator->refine(ss->osd_evaluator);
MEM_freeN(positions);
}
@@ -558,11 +535,12 @@ static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v);
/* TODO(sergey): Need proper port. */
- openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index,
- face_u, face_v,
- P,
- do_normals ? dPdu : NULL,
- do_normals ? dPdv : NULL);
+ ss->osd_evaluator->evaluateLimit(
+ ss->osd_evaluator, osd_face_index,
+ face_u, face_v,
+ P,
+ do_normals ? dPdu : NULL,
+ do_normals ? dPdv : NULL);
OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n",
osd_face_index, S, grid_u, grid_v, face_u, face_v, P[0], P[1], P[2]);
@@ -636,7 +614,11 @@ static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
* let's just re-evaluate for simplicity.
*/
/* TODO(sergey): Need proper port. */
- openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index, u, v, P, dPdu, dPdv);
+ ss->osd_evaluator->evaluateLimit(
+ ss->osd_evaluator,
+ osd_face_index,
+ u, v,
+ P, dPdu, dPdv);
VertDataCopy(co, P, ss);
if (do_normals) {
cross_v3_v3v3(no, dPdu, dPdv);
@@ -700,7 +682,11 @@ static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss,
float P[3], dPdu[3], dPdv[3];
/* TODO(sergey): Need proper port. */
- openSubdiv_evaluateLimit(ss->osd_evaluator, osd_face_index + S, u, v, P, dPdu, dPdv);
+ ss->osd_evaluator->evaluateLimit(
+ ss->osd_evaluator,
+ osd_face_index + S,
+ u, v,
+ P, dPdu, dPdv);
OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n",
osd_face_index + S, S, u, v, P[0], P[1], P[2]);
@@ -838,7 +824,12 @@ void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, DerivedMesh *dm)
OpenSubdiv_Converter converter;
ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
/* TODO(sergey): Remove possibly previously allocated refiner. */
- ss->osd_topology_refiner = openSubdiv_createTopologyRefinerDescr(&converter);
+ OpenSubdiv_TopologyRefinerSettings settings;
+ settings.level = ss->subdivLevels;
+ settings.is_adaptive = false;
+ ss->osd_topology_refiner =
+ openSubdiv_createTopologyRefinerFromConverter(
+ &converter, &settings);
ccgSubSurf_converter_free(&converter);
}
}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
index 8c1ba0c3782..649b7c7fa4c 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
@@ -389,12 +389,6 @@ static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter)
return storage->num_uvs;
}
-static void conv_dm_get_uvs(const OpenSubdiv_Converter *converter, float *uvs)
-{
- ConvDMStorage *storage = converter->user_data;
- memcpy(uvs, storage->uvs, sizeof(float) * 2 * storage->num_uvs);
-}
-
static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
int face,
int corner)
@@ -432,35 +426,34 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
{
ConvDMStorage *user_data;
- converter->get_scheme_type = conv_dm_get_type;
+ converter->getSchemeType = conv_dm_get_type;
- converter->get_fvar_linear_interpolation =
+ converter->getFVarLinearInterpolation =
conv_dm_get_fvar_linear_interpolation;
- converter->get_num_faces = conv_dm_get_num_faces;
- converter->get_num_edges = conv_dm_get_num_edges;
- converter->get_num_verts = conv_dm_get_num_verts;
+ converter->getNumFaces = conv_dm_get_num_faces;
+ converter->getNumEdges = conv_dm_get_num_edges;
+ converter->getNumVertices = conv_dm_get_num_verts;
- converter->get_num_face_verts = conv_dm_get_num_face_verts;
- converter->get_face_verts = conv_dm_get_face_verts;
- converter->get_face_edges = conv_dm_get_face_edges;
+ converter->getNumFaceVertices = conv_dm_get_num_face_verts;
+ converter->getFaceVertices = conv_dm_get_face_verts;
+ converter->getFaceEdges = conv_dm_get_face_edges;
- converter->get_edge_verts = conv_dm_get_edge_verts;
- converter->get_num_edge_faces = conv_dm_get_num_edge_faces;
- converter->get_edge_faces = conv_dm_get_edge_faces;
- converter->get_edge_sharpness = conv_dm_get_edge_sharpness;
+ converter->getEdgeVertices = conv_dm_get_edge_verts;
+ converter->getNumEdgeFaces = conv_dm_get_num_edge_faces;
+ converter->getEdgeFaces = conv_dm_get_edge_faces;
+ converter->getEdgeSharpness = conv_dm_get_edge_sharpness;
- converter->get_num_vert_edges = conv_dm_get_num_vert_edges;
- converter->get_vert_edges = conv_dm_get_vert_edges;
- converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
- converter->get_vert_faces = conv_dm_get_vert_faces;
+ converter->getNumVertexEdges = conv_dm_get_num_vert_edges;
+ converter->getVertexEdges = conv_dm_get_vert_edges;
+ converter->getNumVertexFaces = conv_dm_get_num_vert_faces;
+ converter->getVertexFaces = conv_dm_get_vert_faces;
- converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
- converter->precalc_uv_layer = conv_dm_precalc_uv_layer;
- converter->finish_uv_layer = conv_dm_finish_uv_layer;
- converter->get_num_uvs = conv_dm_get_num_uvs;
- converter->get_uvs = conv_dm_get_uvs;
- converter->get_face_corner_uv_index = conv_dm_get_face_corner_uv_index;
+ converter->getNumUVLayers = conv_dm_get_num_uv_layers;
+ converter->precalcUVLayer = conv_dm_precalc_uv_layer;
+ converter->finishUVLayer = conv_dm_finish_uv_layer;
+ converter->getNumUVCoordinates = conv_dm_get_num_uvs;
+ converter->getFaceCornerUVIndex = conv_dm_get_face_corner_uv_index;
user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
user_data->ss = ss;
@@ -476,7 +469,7 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
user_data->uvs = NULL;
user_data->face_uvs = NULL;
- converter->free_user_data = conv_dm_free_user_data;
+ converter->freeUserData = conv_dm_free_user_data;
converter->user_data = user_data;
#ifdef USE_MESH_ELEMENT_MAPPING
@@ -702,11 +695,6 @@ static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter))
return 0;
}
-static void conv_ccg_get_uvs(const OpenSubdiv_Converter * UNUSED(converter),
- float *UNUSED(uvs))
-{
-}
-
static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter),
int UNUSED(face),
int UNUSED(corner_))
@@ -717,45 +705,44 @@ static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(
void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
OpenSubdiv_Converter *converter)
{
- converter->get_scheme_type = conv_ccg_get_bilinear_type;
+ converter->getSchemeType = conv_ccg_get_bilinear_type;
- converter->get_fvar_linear_interpolation =
+ converter->getFVarLinearInterpolation =
conv_ccg_get_fvar_linear_interpolation;
- converter->get_num_faces = conv_ccg_get_num_faces;
- converter->get_num_edges = conv_ccg_get_num_edges;
- converter->get_num_verts = conv_ccg_get_num_verts;
+ converter->getNumFaces = conv_ccg_get_num_faces;
+ converter->getNumEdges = conv_ccg_get_num_edges;
+ converter->getNumVertices = conv_ccg_get_num_verts;
- converter->get_num_face_verts = conv_ccg_get_num_face_verts;
- converter->get_face_verts = conv_ccg_get_face_verts;
- converter->get_face_edges = conv_ccg_get_face_edges;
+ converter->getNumFaceVertices = conv_ccg_get_num_face_verts;
+ converter->getFaceVertices = conv_ccg_get_face_verts;
+ converter->getFaceEdges = conv_ccg_get_face_edges;
- converter->get_edge_verts = conv_ccg_get_edge_verts;
- converter->get_num_edge_faces = conv_ccg_get_num_edge_faces;
- converter->get_edge_faces = conv_ccg_get_edge_faces;
- converter->get_edge_sharpness = conv_ccg_get_edge_sharpness;
+ converter->getEdgeVertices = conv_ccg_get_edge_verts;
+ converter->getNumEdgeFaces = conv_ccg_get_num_edge_faces;
+ converter->getEdgeFaces = conv_ccg_get_edge_faces;
+ converter->getEdgeSharpness = conv_ccg_get_edge_sharpness;
- converter->get_num_vert_edges = conv_ccg_get_num_vert_edges;
- converter->get_vert_edges = conv_ccg_get_vert_edges;
- converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
- converter->get_vert_faces = conv_ccg_get_vert_faces;
+ converter->getNumVertexEdges = conv_ccg_get_num_vert_edges;
+ converter->getVertexEdges = conv_ccg_get_vert_edges;
+ converter->getNumVertexFaces = conv_ccg_get_num_vert_faces;
+ converter->getVertexFaces = conv_ccg_get_vert_faces;
- converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
- converter->precalc_uv_layer = conv_ccg_precalc_uv_layer;
- converter->finish_uv_layer = conv_ccg_finish_uv_layer;
- converter->get_num_uvs = conv_ccg_get_num_uvs;
- converter->get_uvs = conv_ccg_get_uvs;
- converter->get_face_corner_uv_index = conv_ccg_get_face_corner_uv_index;
+ converter->getNumUVLayers = conv_ccg_get_num_uv_layers;
+ converter->precalcUVLayer = conv_ccg_precalc_uv_layer;
+ converter->finishUVLayer = conv_ccg_finish_uv_layer;
+ converter->getNumUVCoordinates = conv_ccg_get_num_uvs;
+ converter->getFaceCornerUVIndex = conv_ccg_get_face_corner_uv_index;
- converter->free_user_data = NULL;
+ converter->freeUserData = NULL;
converter->user_data = ss;
}
void ccgSubSurf_converter_free(
struct OpenSubdiv_Converter *converter)
{
- if (converter->free_user_data) {
- converter->free_user_data(converter);
+ if (converter->freeUserData) {
+ converter->freeUserData(converter);
}
}
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 9c4aae7cda5..05253f7962a 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2098,6 +2098,7 @@ static void mesh_calc_modifiers(
/* XXX: Is build_shapekey_layers ever even true? This should have crashed long ago... */
BLI_assert(!build_shapekey_layers);
+ UNUSED_VARS_NDEBUG(build_shapekey_layers);
//if (build_shapekey_layers)
// add_shapekey_layers(*r_deform_mesh, me, ob);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index cbdabe2c440..6f97187f1e3 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1328,6 +1328,37 @@ void BKE_pose_rest(bPose *pose)
}
}
+void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
+{
+ copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
+ copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
+
+ /* used for local constraints */
+ copy_v3_v3(pchanto->loc, pchanfrom->loc);
+ copy_qt_qt(pchanto->quat, pchanfrom->quat);
+ copy_v3_v3(pchanto->eul, pchanfrom->eul);
+ copy_v3_v3(pchanto->size, pchanfrom->size);
+
+ copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
+ copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
+
+ pchanto->roll1 = pchanfrom->roll1;
+ pchanto->roll2 = pchanfrom->roll2;
+ pchanto->curveInX = pchanfrom->curveInX;
+ pchanto->curveInY = pchanfrom->curveInY;
+ pchanto->curveOutX = pchanfrom->curveOutX;
+ pchanto->curveOutY = pchanfrom->curveOutY;
+ pchanto->ease1 = pchanfrom->ease1;
+ pchanto->ease2 = pchanfrom->ease2;
+ pchanto->scaleIn = pchanfrom->scaleIn;
+ pchanto->scaleOut = pchanfrom->scaleOut;
+
+ pchanto->rotmode = pchanfrom->rotmode;
+ pchanto->flag = pchanfrom->flag;
+ pchanto->protectflag = pchanfrom->protectflag;
+ pchanto->bboneflag = pchanfrom->bboneflag;
+}
+
/* both poses should be in sync */
bool BKE_pose_copy_result(bPose *to, bPose *from)
{
@@ -1346,34 +1377,8 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
- if (pchanto) {
- copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
- copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
-
- /* used for local constraints */
- copy_v3_v3(pchanto->loc, pchanfrom->loc);
- copy_qt_qt(pchanto->quat, pchanfrom->quat);
- copy_v3_v3(pchanto->eul, pchanfrom->eul);
- copy_v3_v3(pchanto->size, pchanfrom->size);
-
- copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
- copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
-
- pchanto->roll1 = pchanfrom->roll1;
- pchanto->roll2 = pchanfrom->roll2;
- pchanto->curveInX = pchanfrom->curveInX;
- pchanto->curveInY = pchanfrom->curveInY;
- pchanto->curveOutX = pchanfrom->curveOutX;
- pchanto->curveOutY = pchanfrom->curveOutY;
- pchanto->ease1 = pchanfrom->ease1;
- pchanto->ease2 = pchanfrom->ease2;
- pchanto->scaleIn = pchanfrom->scaleIn;
- pchanto->scaleOut = pchanfrom->scaleOut;
-
- pchanto->rotmode = pchanfrom->rotmode;
- pchanto->flag = pchanfrom->flag;
- pchanto->protectflag = pchanfrom->protectflag;
- pchanto->bboneflag = pchanfrom->bboneflag;
+ if (pchanto != NULL) {
+ BKE_pose_copyesult_pchan_result(pchanto, pchanfrom);
}
}
return true;
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 07b8b69bc70..7df889d22b2 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -99,6 +99,8 @@ void animviz_settings_init(bAnimVizSettings *avs)
avs->path_viewflag = (MOTIONPATH_VIEW_KFRAS | MOTIONPATH_VIEW_KFNOS);
avs->path_step = 1;
+
+ avs->path_bakeflag |= MOTIONPATH_BAKE_HEADS;
}
/* ------------------- */
@@ -114,9 +116,9 @@ void animviz_free_motionpath_cache(bMotionPath *mpath)
if (mpath->points)
MEM_freeN(mpath->points);
- GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
- GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
- GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
+ GPU_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_line);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_points);
/* reset the relevant parameters */
mpath->points = NULL;
@@ -495,9 +497,9 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
BLI_dlrbTree_free(&mpt->keys);
/* Free previous batches to force update. */
- GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
- GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
- GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
+ GPU_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_line);
+ GPU_BATCH_DISCARD_SAFE(mpath->batch_points);
}
}
@@ -535,18 +537,18 @@ void calc_curvepath(Object *ob, ListBase *nurbs)
return;
}
- if (ob->curve_cache->path) free_path(ob->curve_cache->path);
- ob->curve_cache->path = NULL;
+ if (ob->runtime.curve_cache->path) free_path(ob->runtime.curve_cache->path);
+ ob->runtime.curve_cache->path = NULL;
/* weak! can only use first curve */
- bl = ob->curve_cache->bev.first;
+ bl = ob->runtime.curve_cache->bev.first;
if (bl == NULL || !bl->nr) {
return;
}
nu = nurbs->first;
- ob->curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
+ ob->runtime.curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
/* if POLY: last vertice != first vertice */
cycl = (bl->poly != -1);
@@ -663,15 +665,15 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
if (ob == NULL || ob->type != OB_CURVE) return 0;
cu = ob->data;
- if (ob->curve_cache == NULL || ob->curve_cache->path == NULL || ob->curve_cache->path->data == NULL) {
+ if (ob->runtime.curve_cache == NULL || ob->runtime.curve_cache->path == NULL || ob->runtime.curve_cache->path->data == NULL) {
printf("no path!\n");
return 0;
}
- path = ob->curve_cache->path;
+ path = ob->runtime.curve_cache->path;
pp = path->data;
/* test for cyclic */
- bl = ob->curve_cache->bev.first;
+ bl = ob->runtime.curve_cache->bev.first;
if (!bl) return 0;
if (!bl->nr) return 0;
if (bl->poly > -1) cycl = 1;
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index fd7497f9ba1..b02b6b6ce15 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1150,6 +1150,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
/* grease pencil */
ANIMDATA_IDS_CB(bmain->gpencil.first);
+ /* palettes */
+ ANIMDATA_IDS_CB(bmain->palettes.first);
+
/* cache files */
ANIMDATA_IDS_CB(bmain->cachefiles.first);
}
@@ -2925,6 +2928,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, Scene
/* grease pencil */
EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
+ /* palettes */
+ EVAL_ANIM_IDS(main->palettes.first, ADT_RECALC_ANIM);
+
/* cache files */
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index bd9ee7c9e5f..cea81a82f4b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -71,6 +71,8 @@
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph_build.h"
+
#include "BIK_api.h"
/* **************** Generic Functions, data level *************** */
@@ -1951,9 +1953,14 @@ void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
BLI_ghash_free(bone_hash, NULL, NULL);
}
-/* only after leave editmode, duplicating, validating older files, library syncing */
-/* NOTE: pose->flag is set for it */
-void BKE_pose_rebuild(Object *ob, bArmature *arm)
+/**
+ * Only after leave editmode, duplicating, validating older files, library syncing.
+ *
+ * \note pose->flag is set for it.
+ *
+ * \param bmain May be NULL, only used to tag depsgraph as being dirty...
+ */
+void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
{
Bone *bone;
bPose *pose;
@@ -1982,7 +1989,7 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
for (pchan = pose->chanbase.first; pchan; pchan = next) {
next = pchan->next;
if (pchan->bone == NULL) {
- BKE_pose_channel_free(pchan);
+ BKE_pose_channel_free_ex(pchan, do_id_user);
BKE_pose_channels_hash_free(pose);
BLI_freelinkN(&pose->chanbase, pchan);
}
@@ -1998,12 +2005,17 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
}
- BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
+ BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
+
+ pose->flag &= ~POSE_RECALC;
+ pose->flag |= POSE_WAS_REBUILT;
- ob->pose->flag &= ~POSE_RECALC;
- ob->pose->flag |= POSE_WAS_REBUILT;
+ BKE_pose_channels_hash_make(pose);
- BKE_pose_channels_hash_make(ob->pose);
+ /* Rebuilding poses forces us to also rebuild the dependency graph, since there is one node per pose/bone... */
+ if (bmain != NULL) {
+ DEG_relations_tag_update(bmain);
+ }
}
/* ********************** THE POSE SOLVER ******************* */
@@ -2277,8 +2289,10 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
if (ELEM(NULL, arm, scene))
return;
- if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC))
- BKE_pose_rebuild(ob, arm);
+ if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) {
+ /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - hopefully this is OK. */
+ BKE_pose_rebuild(NULL, ob, arm, true);
+ }
ctime = BKE_scene_frame_get(scene); /* not accurate... */
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 628f92c7803..d53c61255fe 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -201,7 +201,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
/* get the current length of the curve */
/* NOTE: this is assumed to be correct even after the curve was resized */
- splineLen = ikData->tar->curve_cache->path->totdist;
+ splineLen = ikData->tar->runtime.curve_cache->path->totdist;
/* calculate the scale factor to multiply all the path values by so that the
* bone chain retains its current length, such that
@@ -558,6 +558,17 @@ void BKE_splineik_execute_tree(
/* *************** Depsgraph evaluation callbacks ************ */
+static void pose_pchan_index_create(bPose *pose)
+{
+ const int num_channels = BLI_listbase_count(&pose->chanbase);
+ pose->chan_array = MEM_malloc_arrayN(
+ num_channels, sizeof(bPoseChannel *), "pose->chan_array");
+ int pchan_index = 0;
+ for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ pose->chan_array[pchan_index++] = pchan;
+ }
+}
+
BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index)
{
bPose *pose = ob->pose;
@@ -585,16 +596,12 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph,
/* imat is needed for solvers. */
invert_m4_m4(ob->imat, ob->obmat);
- const int num_channels = BLI_listbase_count(&pose->chanbase);
- pose->chan_array = MEM_malloc_arrayN(
- num_channels, sizeof(bPoseChannel *), "pose->chan_array");
-
/* clear flags */
- int pchan_index = 0;
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
- pose->chan_array[pchan_index++] = pchan;
}
+
+ pose_pchan_index_create(pose);
}
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph,
@@ -688,7 +695,8 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph,
invert_m4_m4(imat, pchan->bone->arm_mat);
mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
}
- if (DEG_is_active(depsgraph)) {
+ bArmature *arm = (bArmature *)ob->data;
+ if (DEG_is_active(depsgraph) && arm->edbo == NULL) {
bPoseChannel *pchan_orig = pchan->orig_pchan;
copy_m4_m4(pchan_orig->pose_mat, pchan->pose_mat);
copy_m4_m4(pchan_orig->chan_mat, pchan->chan_mat);
@@ -751,12 +759,44 @@ void BKE_pose_eval_flush(struct Depsgraph *depsgraph,
pose->chan_array = NULL;
}
-void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, Object *ob)
+void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph, Object *object)
{
- BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
- if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
- printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
- ob->id.name + 2, ob->proxy_from->id.name + 2);
- }
+ BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
+ DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
+
+ pose_pchan_index_create(object->pose);
+}
+
+void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph, Object *object)
+{
+ BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
+ DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
+
+ bPose *pose = object->pose;
+ BLI_assert(pose->chan_array != NULL);
+ MEM_freeN(pose->chan_array);
+ pose->chan_array = NULL;
+}
+
+void BKE_pose_eval_proxy_copy_bone(
+ struct Depsgraph *depsgraph,
+ Object *object,
+ int pchan_index)
+{
+ BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
+ DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
+ bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
+ /* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept
+ * around for the time while proxies are evaluating.
+ */
+#if 0
+ bPoseChannel *pchan_from = pose_pchan_get_indexed(
+ object->proxy_from, pchan_index);
+#else
+ bPoseChannel *pchan_from = BKE_pose_channel_find_name(
+ object->proxy_from->pose, pchan->name);
+#endif
+ BLI_assert(pchan != NULL);
+ BLI_assert(pchan_from != NULL);
+ BKE_pose_copyesult_pchan_result(pchan, pchan_from);
}
diff --git a/source/blender/blenkernel/intern/blender_user_menu.c b/source/blender/blenkernel/intern/blender_user_menu.c
index 3ec46e23cd1..2c18de70e6d 100644
--- a/source/blender/blenkernel/intern/blender_user_menu.c
+++ b/source/blender/blenkernel/intern/blender_user_menu.c
@@ -89,6 +89,7 @@ bUserMenuItem *BKE_blender_user_menu_item_add(ListBase *lb, int type)
size = sizeof(bUserMenuItem_Prop);
}
else {
+ size = sizeof(bUserMenuItem);
BLI_assert(0);
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 42cd7968321..e1cc3984601 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -29,6 +29,7 @@
#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -36,6 +37,7 @@
#include "BKE_brush.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -129,6 +131,7 @@ static void brush_defaults(Brush *brush)
brush->stencil_dimension[0] = 256;
brush->stencil_dimension[1] = 256;
+
}
/* Datablock add/copy/free/make_local */
@@ -164,6 +167,376 @@ Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
return brush;
}
+/* add grese pencil settings */
+void BKE_brush_init_gpencil_settings(Brush *brush)
+{
+ if (brush->gpencil_settings == NULL) {
+ brush->gpencil_settings = MEM_callocN(sizeof(BrushGpencilSettings), "BrushGpencilSettings");
+ }
+
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->flag = 0;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
+
+ /* curves */
+ brush->gpencil_settings->curve_sensitivity = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ brush->gpencil_settings->curve_strength = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ brush->gpencil_settings->curve_jitter = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+/* add a new gp-brush */
+Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name)
+{
+ Brush *brush;
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ brush = BKE_brush_add(bmain, name, OB_MODE_GPENCIL_PAINT);
+
+ BKE_paint_brush_set(paint, brush);
+ id_us_min(&brush->id);
+
+ brush->size = 3;
+
+ /* grease pencil basic settings */
+ BKE_brush_init_gpencil_settings(brush);
+
+ /* return brush */
+ return brush;
+}
+
+Paint *BKE_brush_get_gpencil_paint(ToolSettings *ts)
+{
+ /* alloc paint session */
+ if (ts->gp_paint == NULL) {
+ ts->gp_paint = MEM_callocN(sizeof(GpPaint), "GpPaint");
+ }
+
+ return &ts->gp_paint->paint;
+}
+
+/* grease pencil cumapping->preset */
+typedef enum eGPCurveMappingPreset {
+ GPCURVE_PRESET_PENCIL = 0,
+ GPCURVE_PRESET_INK = 1,
+ GPCURVE_PRESET_INKNOISE = 2,
+} eGPCurveMappingPreset;
+
+static void brush_gpencil_curvemap_reset(CurveMap *cuma, int preset)
+{
+ if (cuma->curve)
+ MEM_freeN(cuma->curve);
+
+ cuma->totpoint = 3;
+ cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), __func__);
+
+ switch (preset) {
+ case GPCURVE_PRESET_PENCIL:
+ cuma->curve[0].x = 0.0f;
+ cuma->curve[0].y = 0.0f;
+ cuma->curve[1].x = 0.75115f;
+ cuma->curve[1].y = 0.25f;
+ cuma->curve[2].x = 1.0f;
+ cuma->curve[2].y = 1.0f;
+ break;
+ case GPCURVE_PRESET_INK:
+ cuma->curve[0].x = 0.0f;
+ cuma->curve[0].y = 0.0f;
+ cuma->curve[1].x = 0.63448f;
+ cuma->curve[1].y = 0.375f;
+ cuma->curve[2].x = 1.0f;
+ cuma->curve[2].y = 1.0f;
+ break;
+ case GPCURVE_PRESET_INKNOISE:
+ cuma->curve[0].x = 0.0f;
+ cuma->curve[0].y = 0.0f;
+ cuma->curve[1].x = 0.63134f;
+ cuma->curve[1].y = 0.3625f;
+ cuma->curve[2].x = 1.0f;
+ cuma->curve[2].y = 1.0f;
+ break;
+ }
+
+ if (cuma->table) {
+ MEM_freeN(cuma->table);
+ cuma->table = NULL;
+ }
+}
+
+/* create a set of grease pencil presets */
+void BKE_brush_gpencil_presets(bContext *C)
+{
+#define SMOOTH_STROKE_RADIUS 40
+#define SMOOTH_STROKE_FACTOR 0.9f
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ Main *bmain = CTX_data_main(C);
+
+ Brush *brush, *deft;
+ CurveMapping *custom_curve;
+
+ /* Pencil brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Pencil");
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 0.6f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Pen brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Pen");
+ deft = brush; /* save default brush */
+ brush->size = 30.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Ink brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Ink");
+ brush->size = 60.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.6f;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Curve */
+ custom_curve = brush->gpencil_settings->curve_sensitivity;
+ curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+ curvemapping_initialize(custom_curve);
+ brush_gpencil_curvemap_reset(custom_curve->cm, GPCURVE_PRESET_INK);
+
+ /* Ink Noise brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Noise");
+ brush->size = 60.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
+ brush->gpencil_settings->draw_random_press = 0.7f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 2;
+ brush->gpencil_settings->thick_smoothfac = 0.5f;
+ brush->gpencil_settings->thick_smoothlvl = 2;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Curve */
+ custom_curve = brush->gpencil_settings->curve_sensitivity;
+ curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+ curvemapping_initialize(custom_curve);
+ brush_gpencil_curvemap_reset(custom_curve->cm, GPCURVE_PRESET_INKNOISE);
+
+ /* Block Basic brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Block");
+ brush->size = 150.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 0.7f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->draw_random_sub = 0;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_BLOCK;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Marker brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Marker");
+ brush->size = 80.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
+ brush->gpencil_settings->draw_random_press = 0.374f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = M_PI_4; /* 45 degrees */
+ brush->gpencil_settings->draw_angle_factor = 1.0f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ /* Fill brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
+ brush->size = 1.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->fill_leak = 3;
+ brush->gpencil_settings->fill_threshold = 0.1f;
+ brush->gpencil_settings->fill_simplylvl = 1;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_FILL;
+
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_subdivide = 1;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ /* Soft Eraser brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft");
+ brush->size = 30.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
+
+ /* Hard Eraser brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Hard");
+ brush->size = 30.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
+
+ /* Stroke Eraser brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Stroke");
+ brush->size = 30.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
+ brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
+
+ /* set defaut brush */
+ BKE_paint_brush_set(paint, deft);
+
+}
+
+/* get the active gp-brush for editing */
+Brush *BKE_brush_getactive_gpencil(ToolSettings *ts)
+{
+ /* error checking */
+ if (ELEM(NULL, ts, ts->gp_paint)) {
+ return NULL;
+ }
+ Paint *paint = &ts->gp_paint->paint;
+
+ return paint->brush;
+}
+
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
{
Brush *brush;
@@ -197,6 +570,12 @@ void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *bru
}
brush_dst->curve = curvemapping_copy(brush_src->curve);
+ if (brush_src->gpencil_settings != NULL) {
+ brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings);
+ brush_dst->gpencil_settings->curve_sensitivity = curvemapping_copy(brush_src->gpencil_settings->curve_sensitivity);
+ brush_dst->gpencil_settings->curve_strength = curvemapping_copy(brush_src->gpencil_settings->curve_strength);
+ brush_dst->gpencil_settings->curve_jitter = curvemapping_copy(brush_src->gpencil_settings->curve_jitter);
+ }
/* enable fake user by default */
id_fake_user_set(&brush_dst->id);
@@ -215,11 +594,18 @@ void BKE_brush_free(Brush *brush)
if (brush->icon_imbuf) {
IMB_freeImBuf(brush->icon_imbuf);
}
-
curvemapping_free(brush->curve);
+ if (brush->gpencil_settings != NULL) {
+ curvemapping_free(brush->gpencil_settings->curve_sensitivity);
+ curvemapping_free(brush->gpencil_settings->curve_strength);
+ curvemapping_free(brush->gpencil_settings->curve_jitter);
+ MEM_SAFE_FREE(brush->gpencil_settings);
+ }
+
MEM_SAFE_FREE(brush->gradient);
+
BKE_previewimg_free(&(brush->preview));
}
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 1a7c4e2a4a0..19ac81b4bb7 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -495,12 +495,39 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em,
- float epsilon, int tree_type, int axis)
+ float epsilon, int tree_type, int axis, BVHCache **bvh_cache)
{
- return bvhtree_from_editmesh_verts_ex(
- data, em,
- NULL, -1,
- epsilon, tree_type, axis);
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+
+ if (data->cached == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ data->cached = bvhcache_find(
+ *bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree);
+ if (data->cached == false) {
+ data->tree = bvhtree_from_editmesh_verts_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(
+ bvh_cache, data->tree, BVHTREE_FROM_EM_VERTS);
+ }
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ else {
+ data->tree = bvhtree_from_editmesh_verts_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+ }
+
+ return data->tree;
}
/**
@@ -649,12 +676,39 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em,
- float epsilon, int tree_type, int axis)
+ float epsilon, int tree_type, int axis, BVHCache **bvh_cache)
{
- return bvhtree_from_editmesh_edges_ex(
- data, em,
- NULL, -1,
- epsilon, tree_type, axis);
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+
+ if (data->cached == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ data->cached = bvhcache_find(
+ *bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree);
+ if (data->cached == false) {
+ data->tree = bvhtree_from_editmesh_edges_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(
+ bvh_cache, data->tree, BVHTREE_FROM_EM_EDGES);
+ }
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ else {
+ data->tree = bvhtree_from_editmesh_edges_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+ }
+
+ return data->tree;
}
/**
@@ -1407,6 +1461,11 @@ BVHTree *BKE_bvhtree_from_mesh_get(
BLI_rw_mutex_unlock(&cache_rwlock);
}
break;
+ case BVHTREE_FROM_EM_VERTS:
+ case BVHTREE_FROM_EM_EDGES:
+ case BVHTREE_FROM_EM_LOOPTRI:
+ BLI_assert(false);
+ break;
}
if (data_cp.tree != NULL) {
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 4203e0455f8..6e50b6e41fa 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -70,12 +70,15 @@ void BKE_camera_init(Camera *cam)
cam->sensor_x = DEFAULT_SENSOR_WIDTH;
cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
cam->clipsta = 0.1f;
- cam->clipend = 100.0f;
+ cam->clipend = 1000.0f;
cam->drawsize = 0.5f;
cam->ortho_scale = 6.0;
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
+ cam->gpu_dof.fstop = 128.0f;
+ cam->gpu_dof.ratio = 1.0f;
+
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
@@ -102,19 +105,9 @@ void *BKE_camera_add(Main *bmain, const char *name)
*
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *cam_dst, const Camera *cam_src, const int flag)
+void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *cam_dst, const Camera *cam_src, const int UNUSED(flag))
{
BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
- if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
- for (CameraBGImage *bgpic = cam_dst->bg_images.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
- id_us_plus((ID *)bgpic->ima);
- }
- else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
- id_us_plus((ID *)bgpic->clip);
- }
- }
- }
}
Camera *BKE_camera_copy(Main *bmain, const Camera *cam)
@@ -132,14 +125,6 @@ void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local)
/** Free (or release) any data used by this camera (does not free the camera itself). */
void BKE_camera_free(Camera *ca)
{
- for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
- id_us_min((ID *)bgpic->ima);
- }
- else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
- id_us_min((ID *)bgpic->clip);
- }
- }
BLI_freelistN(&ca->bg_images);
BKE_animdata_free((ID *)ca, false);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 72a1f941c26..3f50321b4d5 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -655,8 +655,8 @@ DerivedMesh *CDDM_from_curve(Object *ob)
{
ListBase disp = {NULL, NULL};
- if (ob->curve_cache) {
- disp = ob->curve_cache->disp;
+ if (ob->runtime.curve_cache) {
+ disp = ob->runtime.curve_cache->disp;
}
return CDDM_from_curve_displist(ob, &disp);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index ccef747a31c..caf5b94b30e 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -924,7 +924,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, Mesh *mesh )
}
/***************************************************************************************
- * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION BEGIN
+ * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION BEGIN
***************************************************************************************/
BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
@@ -1506,5 +1506,5 @@ static int cloth_build_springs ( ClothModifierData *clmd, Mesh *mesh )
} /* cloth_build_springs */
/***************************************************************************************
- * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION END
+ * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION END
***************************************************************************************/
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 0c93f304218..04e09d06405 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -57,7 +57,7 @@
/******************************** Prototypes ********************************/
-static bool collection_child_add(Collection *parent, Collection *collection, int flag, const bool add_us);
+static bool collection_child_add(Collection *parent, Collection *collection, const int flag, const bool add_us);
static bool collection_child_remove(Collection *parent, Collection *collection);
static bool collection_object_add(Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us);
static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us);
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index ff4795afe87..d18572a57f6 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -282,6 +282,7 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
case CURVE_PRESET_MID9: cuma->totpoint = 9; break;
case CURVE_PRESET_ROUND: cuma->totpoint = 4; break;
case CURVE_PRESET_ROOT: cuma->totpoint = 4; break;
+ case CURVE_PRESET_GAUSS: cuma->totpoint = 7; break;
}
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
@@ -352,6 +353,24 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
cuma->curve[3].x = 1;
cuma->curve[3].y = 0;
break;
+ case CURVE_PRESET_GAUSS:
+ cuma->curve[0].x = 0;
+ cuma->curve[0].y = 0.025f;
+ cuma->curve[1].x = 0.16f;
+ cuma->curve[1].y = 0.135f;
+ cuma->curve[2].x = 0.298f;
+ cuma->curve[2].y = 0.36f;
+
+ cuma->curve[3].x = 0.50f;
+ cuma->curve[3].y = 1.0f;
+
+ cuma->curve[4].x = 0.70f;
+ cuma->curve[4].y = 0.36f;
+ cuma->curve[5].x = 0.84f;
+ cuma->curve[5].y = 0.135f;
+ cuma->curve[6].x = 1.0f;
+ cuma->curve[6].y = 0.025f;
+ break;
}
/* mirror curve in x direction to have positive slope
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 4f772673e1d..ef412f0006e 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -496,7 +496,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
{
Lattice *lt = (Lattice *)ob->data;
- DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
+ DispList *dl = ob->runtime.curve_cache ? BKE_displist_find(&ob->runtime.curve_cache->disp, DL_VERTS) : NULL;
const float *co = dl ? dl->verts : NULL;
BPoint *bp = lt->def;
@@ -1266,7 +1266,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
- if (ct->tar->curve_cache && ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
+ if (ct->tar->runtime.curve_cache && ct->tar->runtime.curve_cache->path && ct->tar->runtime.curve_cache->path->data) {
float quat[4];
if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */
@@ -2037,7 +2037,7 @@ static void pycon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
#endif
if (VALID_CONS_TARGET(ct)) {
- if (ct->tar->type == OB_CURVE && ct->tar->curve_cache == NULL) {
+ if (ct->tar->type == OB_CURVE && ct->tar->runtime.curve_cache == NULL) {
unit_m4(ct->matrix);
return;
}
@@ -3104,7 +3104,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
BKE_object_minmax(ct->tar, curveMin, curveMax, true);
/* get targetmatrix */
- if (data->tar->curve_cache && data->tar->curve_cache->path && data->tar->curve_cache->path->data) {
+ if (data->tar->runtime.curve_cache && data->tar->runtime.curve_cache->path && data->tar->runtime.curve_cache->path->data) {
float vec[4], dir[3], totmat[4][4];
float curvetime;
short clamp_axis;
@@ -3641,7 +3641,7 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
* - the min/max wrappers around (obvec . tarvec) result (stored temporarily in rangle)
* are used to ensure that the smallest angle is chosen
*/
- cross_v3_v3v3(raxis, obvec, tarvec);
+ cross_v3_v3v3_hi_prec(raxis, obvec, tarvec);
rangle = dot_v3v3(obvec, tarvec);
rangle = acosf(max_ff(-1.0f, min_ff(1.0f, rangle)));
@@ -3649,7 +3649,35 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
/* construct rotation matrix from the axis-angle rotation found above
* - this call takes care to make sure that the axis provided is a unit vector first
*/
- axis_angle_to_mat3(rmat, raxis, rangle);
+ float norm = normalize_v3(raxis);
+
+ if (norm < FLT_EPSILON) {
+ /* if dot product is nonzero, while cross is zero, we have two opposite vectors!
+ * - this is an ambiguity in the math that needs to be resolved arbitrarily,
+ * or there will be a case where damped track strangely does nothing
+ * - to do that, rotate around a different local axis
+ */
+ float tmpvec[3];
+
+ if (fabsf(rangle) < M_PI - 0.01f) {
+ return;
+ }
+
+ rangle = M_PI;
+ copy_v3_v3(tmpvec, track_dir_vecs[(data->trackflag + 1) % 6]);
+ mul_mat3_m4_v3(cob->matrix, tmpvec);
+ cross_v3_v3v3(raxis, obvec, tmpvec);
+
+ if (normalize_v3(raxis) == 0.0f) {
+ return;
+ }
+ }
+ else if (norm < 0.1f) {
+ /* near 0 and Pi arcsin has way better precision than arccos */
+ rangle = (rangle > M_PI_2) ? M_PI - asinf(norm) : asinf(norm);
+ }
+
+ axis_angle_normalized_to_mat3(rmat, raxis, rangle);
/* rotate the owner in the way defined by this rotation matrix, then reapply the location since
* we may have destroyed that in the process of multiplying the matrix
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 68a1e607517..84ca143dc55 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -876,9 +876,9 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu)
C->wm.menu = menu;
}
-void CTX_wm_gizmo_group_set(bContext *C, struct wmGizmoGroup *mgroup)
+void CTX_wm_gizmo_group_set(bContext *C, struct wmGizmoGroup *gzgroup)
{
- C->wm.gizmo_group = mgroup;
+ C->wm.gizmo_group = gzgroup;
}
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
@@ -1014,6 +1014,10 @@ int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectM
else if (object_mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
else if (object_mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
else if (object_mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
+ else if (object_mode & OB_MODE_GPENCIL_PAINT) return CTX_MODE_GPENCIL_PAINT;
+ else if (object_mode & OB_MODE_GPENCIL_EDIT) return CTX_MODE_GPENCIL_EDIT;
+ else if (object_mode & OB_MODE_GPENCIL_SCULPT) return CTX_MODE_GPENCIL_SCULPT;
+ else if (object_mode & OB_MODE_GPENCIL_WEIGHT) return CTX_MODE_GPENCIL_WEIGHT;
}
}
@@ -1044,6 +1048,10 @@ static const char *data_mode_strings[] = {
"imagepaint",
"particlemode",
"objectmode",
+ "greasepencil_paint",
+ "greasepencil_edit",
+ "greasepencil_sculpt",
+ "greasepencil_weight",
NULL
};
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1, "Must have a string for each context mode")
@@ -1212,17 +1220,7 @@ bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C)
return ctx_data_pointer_get(C, "active_gpencil_layer");
}
-bGPDpalette *CTX_data_active_gpencil_palette(const bContext *C)
-{
- return ctx_data_pointer_get(C, "active_gpencil_palette");
-}
-
-bGPDpalettecolor *CTX_data_active_gpencil_palettecolor(const bContext *C)
-{
- return ctx_data_pointer_get(C, "active_gpencil_palettecolor");
-}
-
-bGPDbrush *CTX_data_active_gpencil_brush(const bContext *C)
+Brush *CTX_data_active_gpencil_brush(const bContext *C)
{
return ctx_data_pointer_get(C, "active_gpencil_brush");
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 33a24f77937..39b28540205 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1752,11 +1752,11 @@ void BKE_curve_bevel_make(
BKE_displist_make_curveTypes_forRender(depsgraph, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution);
dl = bevdisp.first;
}
- else if (cu->bevobj->curve_cache) {
- dl = cu->bevobj->curve_cache->disp.first;
+ else if (cu->bevobj->runtime.curve_cache) {
+ dl = cu->bevobj->runtime.curve_cache->disp.first;
}
else {
- BLI_assert(cu->bevobj->curve_cache != NULL);
+ BLI_assert(cu->bevobj->runtime.curve_cache != NULL);
dl = NULL;
}
@@ -2669,14 +2669,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE);
- bev = &ob->curve_cache->bev;
+ bev = &ob->runtime.curve_cache->bev;
/* do we need to calculate the radius for each point? */
/* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */
/* STEP 1: MAKE POLYS */
- BKE_curve_bevelList_free(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
nu = nurbs->first;
if (cu->editnurb && ob->type != OB_FONT) {
is_editmode = 1;
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index d08e3643ca7..ddf9840a32e 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -74,7 +74,9 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
BLI_addtail(&ob->defbase, defgroup);
defgroup_unique_name(defgroup, ob);
- BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ if (ob->type != OB_GPENCIL) {
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ }
return defgroup;
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 34fd32b2908..562e2257ea0 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -692,10 +692,10 @@ static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *tap
if (taperobj == NULL || taperobj->type != OB_CURVE)
return 1.0;
- dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
+ dl = taperobj->runtime.curve_cache ? taperobj->runtime.curve_cache->disp.first : NULL;
if (dl == NULL) {
BKE_displist_make_curveTypes(depsgraph, scene, taperobj, 0);
- dl = taperobj->curve_cache->disp.first;
+ dl = taperobj->runtime.curve_cache->disp.first;
}
if (dl) {
float minx, dx, *fp;
@@ -738,17 +738,17 @@ void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob)
return;
if (ob == BKE_mball_basis_find(scene, ob)) {
- if (ob->curve_cache) {
- BKE_displist_free(&(ob->curve_cache->disp));
+ if (ob->runtime.curve_cache) {
+ BKE_displist_free(&(ob->runtime.curve_cache->disp));
}
else {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
}
- BKE_mball_polygonize(depsgraph, scene, ob, &ob->curve_cache->disp);
+ BKE_mball_polygonize(depsgraph, scene, ob, &ob->runtime.curve_cache->disp);
BKE_mball_texspace_calc(ob);
- object_deform_mball(ob, &ob->curve_cache->disp);
+ object_deform_mball(ob, &ob->runtime.curve_cache->disp);
/* NOP for MBALLs anyway... */
boundbox_displist_object(ob);
@@ -1314,7 +1314,7 @@ void BKE_displist_make_surf(
}
if (!for_orco) {
- BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
+ BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_dm_final,
for_render, use_render_resolution);
}
@@ -1558,15 +1558,15 @@ static void do_makeDispListCurveTypes(
ListBase dlbev;
ListBase nubase = {NULL, NULL};
- BKE_curve_bevelList_free(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
/* We only re-evaluate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
* was needed before and only not needed for orco calculation.
*/
if (!for_orco) {
- if (ob->curve_cache->path) free_path(ob->curve_cache->path);
- ob->curve_cache->path = NULL;
+ if (ob->runtime.curve_cache->path) free_path(ob->runtime.curve_cache->path);
+ ob->runtime.curve_cache->path = NULL;
}
if (ob->type == OB_FONT) {
@@ -1590,7 +1590,7 @@ static void do_makeDispListCurveTypes(
}
else {
float widfac = cu->width - 1.0f;
- BevList *bl = ob->curve_cache->bev.first;
+ BevList *bl = ob->runtime.curve_cache->bev.first;
Nurb *nu = nubase.first;
for (; bl && nu; bl = bl->next, nu = nu->next) {
@@ -1777,7 +1777,7 @@ static void do_makeDispListCurveTypes(
}
if (!for_orco) {
- BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
+ BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
}
@@ -1801,11 +1801,11 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph, Scene *scene, Object *ob
BKE_object_free_derived_caches(ob);
- if (!ob->curve_cache) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+ if (!ob->runtime.curve_cache) {
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
}
- dispbase = &(ob->curve_cache->disp);
+ dispbase = &(ob->runtime.curve_cache->disp);
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0);
@@ -1817,8 +1817,8 @@ void BKE_displist_make_curveTypes_forRender(
DerivedMesh **r_dm_final, const bool for_orco,
const bool use_render_resolution)
{
- if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
+ if (ob->runtime.curve_cache == NULL) {
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
@@ -1827,8 +1827,8 @@ void BKE_displist_make_curveTypes_forRender(
void BKE_displist_make_curveTypes_forOrco(
Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase)
{
- if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
+ if (ob->runtime.curve_cache == NULL) {
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, NULL, 1, 1, 1);
@@ -1903,7 +1903,7 @@ static void boundbox_displist_object(Object *ob)
float min[3], max[3];
INIT_MINMAX(min, max);
- BKE_displist_minmax(&ob->curve_cache->disp, min, max);
+ BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
BKE_boundbox_init_from_minmax(ob->bb, min, max);
ob->bb->flag &= ~BOUNDBOX_DIRTY;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 4c2f513007a..87d93db640d 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -203,7 +203,7 @@ static void emDM_calcLoopNormalsSpaceArray(
cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos,
- r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+ r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, false);
#ifdef DEBUG_CLNORS
if (r_lnors_spacearr) {
int i;
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index b63ab276b14..7d66d25c58a 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -246,3 +246,26 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
return orco;
}
+
+void BKE_editmesh_lnorspace_update(BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+
+ /* We need to create clnors data if none exist yet, otherwise there is no way to edit them.
+ * Similar code to MESH_OT_customdata_custom_splitnormals_add operator, we want to keep same shading
+ * in case we were using autosmooth so far...
+ * Note: there is a problem here, which is that if someone starts a normal editing operation on previously
+ * autosmooth-ed mesh, and cancel that operation, generated clnors data remain, with related sharp edges
+ * (and hence autosmooth is 'lost').
+ * Not sure how critical this is, and how to fix that issue? */
+ if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ Mesh *me = em->ob->data;
+ if (me->flag & ME_AUTOSMOOTH) {
+ BM_edges_sharp_from_angle_set(bm, me->smoothresh);
+
+ me->drawflag |= ME_DRAWSHARP;
+ }
+ }
+
+ BM_lnorspace_update(bm);
+}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index b6eb26443ea..52ea4bf4a5e 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -163,10 +163,10 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
Curve *cu= eff->ob->data;
if (cu->flag & CU_PATH) {
- if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
+ if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->path==NULL || eff->ob->runtime.curve_cache->path->data==NULL)
BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, 0);
- if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
+ if (eff->ob->runtime.curve_cache->path && eff->ob->runtime.curve_cache->path->data) {
where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
mul_m4_v3(eff->ob->obmat, eff->guide_loc);
mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 36633663f9d..b5fba6d30e8 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -1075,8 +1075,8 @@ makebreak:
/* TEXT ON CURVE */
/* Note: Only OB_CURVE objects could have a path */
if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) {
- BLI_assert(cu->textoncurve->curve_cache != NULL);
- if (cu->textoncurve->curve_cache->path) {
+ BLI_assert(cu->textoncurve->runtime.curve_cache != NULL);
+ if (cu->textoncurve->runtime.curve_cache->path) {
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx, miny, maxy;
float timeofs, sizefac;
@@ -1106,7 +1106,7 @@ makebreak:
/* we put the x-coordinaat exact at the curve, the y is rotated */
/* length correction */
- distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
+ distfac = sizefac * cu->textoncurve->runtime.curve_cache->path->totdist / (maxx - minx);
timeofs = 0.0f;
if (distfac > 1.0f) {
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index e89508fd6c0..fdb1123e1c7 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -39,26 +39,83 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_math_color.h"
#include "BLI_string_utils.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
#include "BLT_translation.h"
+#include "DNA_anim_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_material_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_userdef_types.h"
#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "BKE_context.h"
+#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_colortools.h"
+#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+#include "DEG_depsgraph.h"
/* ************************************************** */
-/* GENERAL STUFF */
+/* Draw Engine */
-/* --------- Memory Management ------------ */
+void(*BKE_gpencil_batch_cache_dirty_cb)(bGPdata *gpd) = NULL;
+void(*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL;
+
+void BKE_gpencil_batch_cache_dirty(bGPdata *gpd)
+{
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+ BKE_gpencil_batch_cache_dirty_cb(gpd);
+ }
+}
+
+void BKE_gpencil_batch_cache_free(bGPdata *gpd)
+{
+ if (gpd) {
+ BKE_gpencil_batch_cache_free_cb(gpd);
+ }
+}
+
+/* ************************************************** */
+/* Memory Management */
+
+/* clean vertex groups weights */
+void BKE_gpencil_free_point_weights(MDeformVert *dvert)
+{
+ if (dvert == NULL) {
+ return;
+ }
+ MEM_SAFE_FREE(dvert->dw);
+}
+
+void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
+{
+ if (gps == NULL) {
+ return;
+ }
+
+ if (gps->dvert == NULL) {
+ return;
+ }
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ BKE_gpencil_free_point_weights(dvert);
+ }
+}
/* free stroke, doesn't unlink from any listbase */
void BKE_gpencil_free_stroke(bGPDstroke *gps)
@@ -66,10 +123,14 @@ void BKE_gpencil_free_stroke(bGPDstroke *gps)
if (gps == NULL) {
return;
}
-
/* free stroke memory arrays, then stroke itself */
- if (gps->points)
+ if (gps->points) {
MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
if (gps->triangles)
MEM_freeN(gps->triangles);
@@ -92,6 +153,26 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
return changed;
}
+/* Free strokes and colors belonging to a gp-frame */
+bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf)
+{
+ bGPDstroke *gps_next;
+ if (!derived_gpf) {
+ return false;
+ }
+
+ /* free strokes */
+ for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+ BKE_gpencil_free_stroke(gps);
+ }
+ BLI_listbase_clear(&derived_gpf->strokes);
+
+ MEM_SAFE_FREE(derived_gpf);
+
+ return true;
+}
+
/* Free all of a gp-layer's frames */
void BKE_gpencil_free_frames(bGPDlayer *gpl)
{
@@ -111,101 +192,101 @@ void BKE_gpencil_free_frames(bGPDlayer *gpl)
gpl->actframe = NULL;
}
-/* Free all of a gp-colors */
-static void free_gpencil_colors(bGPDpalette *palette)
-{
- /* error checking */
- if (palette == NULL) {
- return;
- }
- /* free colors */
- BLI_freelistN(&palette->colors);
-}
-/* Free all of the gp-palettes and colors */
-void BKE_gpencil_free_palettes(ListBase *list)
+/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
+void BKE_gpencil_free_layers(ListBase *list)
{
- bGPDpalette *palette_next;
+ bGPDlayer *gpl_next;
/* error checking */
- if (list == NULL) {
- return;
- }
+ if (list == NULL) return;
- /* delete palettes */
- for (bGPDpalette *palette = list->first; palette; palette = palette_next) {
- palette_next = palette->next;
- /* free palette colors */
- free_gpencil_colors(palette);
+ /* delete layers */
+ for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
+ gpl_next = gpl->next;
- MEM_freeN(palette);
+ /* free layers and their data */
+ BKE_gpencil_free_frames(gpl);
+ BLI_freelinkN(list, gpl);
}
- BLI_listbase_clear(list);
}
-/* Free all of the gp-brushes for a viewport (list should be &gpd->brushes or so) */
-void BKE_gpencil_free_brushes(ListBase *list)
+/* clear all runtime derived data */
+static void BKE_gpencil_clear_derived(bGPDlayer *gpl)
{
- bGPDbrush *brush_next;
+ GHashIterator gh_iter;
- /* error checking */
- if (list == NULL) {
+ if (gpl->runtime.derived_data == NULL) {
return;
}
- /* delete brushes */
- for (bGPDbrush *brush = list->first; brush; brush = brush_next) {
- brush_next = brush->next;
- /* free curves */
- if (brush->cur_sensitivity) {
- curvemapping_free(brush->cur_sensitivity);
- }
- if (brush->cur_strength) {
- curvemapping_free(brush->cur_strength);
- }
- if (brush->cur_jitter) {
- curvemapping_free(brush->cur_jitter);
+ GHASH_ITER(gh_iter, gpl->runtime.derived_data) {
+ bGPDframe *gpf = (bGPDframe *)BLI_ghashIterator_getValue(&gh_iter);
+ if (gpf) {
+ BKE_gpencil_free_frame_runtime_data(gpf);
}
-
- MEM_freeN(brush);
}
- BLI_listbase_clear(list);
}
-/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
-void BKE_gpencil_free_layers(ListBase *list)
+/* Free all of the gp-layers temp data*/
+static void BKE_gpencil_free_layers_temp_data(ListBase *list)
{
bGPDlayer *gpl_next;
/* error checking */
if (list == NULL) return;
-
/* delete layers */
for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
gpl_next = gpl->next;
+ BKE_gpencil_clear_derived(gpl);
- /* free layers and their data */
- BKE_gpencil_free_frames(gpl);
- BLI_freelinkN(list, gpl);
+ if (gpl->runtime.derived_data) {
+ BLI_ghash_free(gpl->runtime.derived_data, NULL, NULL);
+ gpl->runtime.derived_data = NULL;
+ }
+ }
+}
+
+/* Free temp gpf derived frames */
+void BKE_gpencil_free_derived_frames(bGPdata *gpd)
+{
+ /* error checking */
+ if (gpd == NULL) return;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ BKE_gpencil_clear_derived(gpl);
+
+ if (gpl->runtime.derived_data) {
+ BLI_ghash_free(gpl->runtime.derived_data, NULL, NULL);
+ gpl->runtime.derived_data = NULL;
+ }
}
}
/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
-void BKE_gpencil_free(bGPdata *gpd, bool free_palettes)
+void BKE_gpencil_free(bGPdata *gpd, bool free_all)
{
+ /* clear animation data */
BKE_animdata_free(&gpd->id, false);
/* free layers */
+ if (free_all) {
+ BKE_gpencil_free_layers_temp_data(&gpd->layers);
+ }
BKE_gpencil_free_layers(&gpd->layers);
- /* free palettes */
- if (free_palettes) {
- BKE_gpencil_free_palettes(&gpd->palettes);
+ /* materials */
+ MEM_SAFE_FREE(gpd->mat);
+
+ /* free all data */
+ if (free_all) {
+ /* clear cache */
+ BKE_gpencil_batch_cache_free(gpd);
}
}
-/* -------- Container Creation ---------- */
+/* ************************************************** */
+/* Container Creation */
/* add a new gp-frame to the given layer */
bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
@@ -329,28 +410,31 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
/* add to datablock */
BLI_addtail(&gpd->layers, gpl);
- /* set basic settings */
- copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
- /* Since GPv2 thickness must be 0 */
- gpl->thickness = 0;
-
- gpl->opacity = 1.0f;
-
- /* onion-skinning settings */
- if (gpd->flag & GP_DATA_SHOW_ONIONSKINS)
- gpl->flag |= GP_LAYER_ONIONSKIN;
+ /* annotation vs GP Object behaviour is slightly different */
+ if (gpd->flag & GP_DATA_ANNOTATIONS) {
+ /* set default color of new strokes for this layer */
+ copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
+ gpl->opacity = 1.0f;
- gpl->flag |= (GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL);
+ /* set default thickness of new strokes for this layer */
+ gpl->thickness = 3;
- ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
- ARRAY_SET_ITEMS(gpl->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
-
- /* high quality fill by default */
- gpl->flag |= GP_LAYER_HQ_FILL;
+ }
+ else {
+ /* thickness parameter represents "thickness change", not absolute thickness */
+ gpl->thickness = 0;
+ gpl->opacity = 1.0f;
+ /* onion-skinning settings */
+ gpl->onion_flag |= GP_LAYER_ONIONSKIN;
+ }
/* auto-name */
BLI_strncpy(gpl->info, name, sizeof(gpl->info));
- BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
+ BLI_uniquename(&gpd->layers, gpl,
+ (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
+ '.',
+ offsetof(bGPDlayer, info),
+ sizeof(gpl->info));
/* make this one the active one */
if (setactive)
@@ -360,292 +444,153 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
return gpl;
}
-/* add a new gp-palette and make it the active */
-bGPDpalette *BKE_gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setactive)
-{
- bGPDpalette *palette;
-
- /* check that list is ok */
- if (gpd == NULL) {
- return NULL;
- }
-
- /* allocate memory and add to end of list */
- palette = MEM_callocN(sizeof(bGPDpalette), "bGPDpalette");
-
- /* add to datablock */
- BLI_addtail(&gpd->palettes, palette);
-
- /* set basic settings */
- /* auto-name */
- BLI_strncpy(palette->info, name, sizeof(palette->info));
- BLI_uniquename(&gpd->palettes, palette, DATA_("GP_Palette"), '.', offsetof(bGPDpalette, info),
- sizeof(palette->info));
-
- /* make this one the active one */
- /* NOTE: Always make this active if there's nothing else yet (T50123) */
- if ((setactive) || (gpd->palettes.first == gpd->palettes.last)) {
- BKE_gpencil_palette_setactive(gpd, palette);
- }
-
- /* return palette */
- return palette;
-}
-
-/* create a set of default drawing brushes with predefined presets */
-void BKE_gpencil_brush_init_presets(ToolSettings *ts)
+/* add a new gp-datablock */
+bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
{
- bGPDbrush *brush;
- /* Basic brush */
- brush = BKE_gpencil_brush_addnew(ts, "Basic", true);
- brush->thickness = 3.0f;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 1.0f;
- brush->flag |= GP_BRUSH_USE_PRESSURE;
-
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 1.0f;
- brush->flag |= ~GP_BRUSH_USE_STENGTH_PRESSURE;
-
- brush->draw_random_press = 0.0f;
-
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
-
- brush->draw_angle = 0.0f;
- brush->draw_angle_factor = 0.0f;
-
- brush->draw_smoothfac = 0.0f;
- brush->draw_smoothlvl = 1;
- brush->sublevel = 0;
- brush->draw_random_sub = 0.0f;
-
- /* Pencil brush */
- brush = BKE_gpencil_brush_addnew(ts, "Pencil", false);
- brush->thickness = 7.0f;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 1.0f;
- brush->flag |= GP_BRUSH_USE_PRESSURE;
-
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 0.7f;
- brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
-
- brush->draw_random_press = 0.0f;
-
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
-
- brush->draw_angle = 0.0f;
- brush->draw_angle_factor = 0.0f;
-
- brush->draw_smoothfac = 1.0f;
- brush->draw_smoothlvl = 2;
- brush->sublevel = 2;
- brush->draw_random_sub = 0.0f;
-
- /* Ink brush */
- brush = BKE_gpencil_brush_addnew(ts, "Ink", false);
- brush->thickness = 7.0f;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 1.6f;
- brush->flag |= GP_BRUSH_USE_PRESSURE;
-
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 1.0f;
- brush->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE;
-
- brush->draw_random_press = 0.0f;
-
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
-
- brush->draw_angle = 0.0f;
- brush->draw_angle_factor = 0.0f;
+ bGPdata *gpd;
- brush->draw_smoothfac = 1.1f;
- brush->draw_smoothlvl = 2;
- brush->sublevel = 2;
- brush->draw_random_sub = 0.0f;
+ /* allocate memory for a new block */
+ gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
- /* Ink Noise brush */
- brush = BKE_gpencil_brush_addnew(ts, "Ink noise", false);
- brush->thickness = 6.0f;
- brush->flag |= GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 1.611f;
- brush->flag |= GP_BRUSH_USE_PRESSURE;
+ /* initial settings */
+ gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 1.0f;
- brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ /* general flags */
+ gpd->flag |= GP_DATA_VIEWALIGN;
- brush->draw_random_press = 1.0f;
+ /* GP object specific settings */
+ ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+ gpd->xray_mode = GP_XRAY_3DSPACE;
+ gpd->runtime.batch_cache_data = NULL;
+ gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
- brush->draw_angle = 0.0f;
- brush->draw_angle_factor = 0.0f;
+ /* onion-skinning settings (datablock level) */
+ gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
+ gpd->onion_flag |= GP_ONION_FADE;
+ gpd->onion_mode = GP_ONION_MODE_RELATIVE;
+ gpd->onion_factor = 0.5f;
+ ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
+ ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
+ gpd->gstep = 1;
+ gpd->gstep_next = 1;
- brush->draw_smoothfac = 1.1f;
- brush->draw_smoothlvl = 2;
- brush->sublevel = 2;
- brush->draw_random_sub = 0.0f;
+ return gpd;
+}
- /* Marker brush */
- brush = BKE_gpencil_brush_addnew(ts, "Marker", false);
- brush->thickness = 10.0f;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 2.0f;
- brush->flag &= ~GP_BRUSH_USE_PRESSURE;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 1.0f;
- brush->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE;
+/* ************************************************** */
+/* Primitive Creation */
+/* Utilities for easier bulk-creation of geometry */
- brush->draw_random_press = 0.0f;
+/**
+ * Populate stroke with point data from data buffers
+ *
+ * \param array Flat array of point data values. Each entry has GP_PRIM_DATABUF_SIZE values
+ * \param mat 4x4 transform matrix to transform points into the right coordinate space
+ */
+void BKE_gpencil_stroke_add_points(bGPDstroke *gps, const float *array, const int totpoints, const float mat[4][4])
+{
+ for (int i = 0; i < totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ const int x = GP_PRIM_DATABUF_SIZE * i;
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+ pt->x = array[x];
+ pt->y = array[x + 1];
+ pt->z = array[x + 2];
+ mul_m4_v3(mat, &pt->x);
- brush->draw_angle = M_PI_4; /* 45 degrees */
- brush->draw_angle_factor = 1.0f;
+ pt->pressure = array[x + 3];
+ pt->strength = array[x + 4];
+ }
+}
- brush->draw_smoothfac = 1.0f;
- brush->draw_smoothlvl = 2;
- brush->sublevel = 2;
- brush->draw_random_sub = 0.0f;
+/* Create a new stroke, with pre-allocated data buffers */
+bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
+{
+ /* allocate memory for a new stroke */
+ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
- /* Crayon brush */
- brush = BKE_gpencil_brush_addnew(ts, "Crayon", false);
- brush->thickness = 10.0f;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
- brush->draw_sensitivity = 3.0f;
- brush->flag &= ~GP_BRUSH_USE_PRESSURE;
+ gps->thickness = thickness * 25;
+ gps->inittime = 0;
- brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
- brush->draw_strength = 0.140f;
- brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ /* enable recalculation flag by default */
+ gps->flag = GP_STROKE_RECALC_CACHES | GP_STROKE_3DSPACE;
- brush->draw_random_press = 0.0f;
+ gps->totpoints = totpoints;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+ /* initialize triangle memory to dummy data */
+ gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
- brush->draw_angle = 0.0f;
- brush->draw_angle_factor = 0.0f;
+ gps->mat_nr = mat_idx;
- brush->draw_smoothfac = 0.0f;
- brush->draw_smoothlvl = 1;
- brush->sublevel = 2;
- brush->draw_random_sub = 0.5f;
+ /* add to frame */
+ BLI_addtail(&gpf->strokes, gps);
+ return gps;
}
-/* add a new gp-brush and make it the active */
-bGPDbrush *BKE_gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setactive)
-{
- bGPDbrush *brush;
-
- /* check that list is ok */
- if (ts == NULL) {
- return NULL;
- }
-
- /* allocate memory and add to end of list */
- brush = MEM_callocN(sizeof(bGPDbrush), "bGPDbrush");
-
- /* add to datablock */
- BLI_addtail(&ts->gp_brushes, brush);
-
- /* set basic settings */
- brush->thickness = 3;
- brush->draw_smoothlvl = 1;
- brush->flag |= GP_BRUSH_USE_PRESSURE;
- brush->draw_sensitivity = 1.0f;
- brush->draw_strength = 1.0f;
- brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->draw_jitter = 0.0f;
- brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
-
- /* curves */
- brush->cur_sensitivity = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- brush->cur_strength = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- brush->cur_jitter = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
-
- /* auto-name */
- BLI_strncpy(brush->info, name, sizeof(brush->info));
- BLI_uniquename(&ts->gp_brushes, brush, DATA_("GP_Brush"), '.', offsetof(bGPDbrush, info), sizeof(brush->info));
-
- /* make this one the active one */
- if (setactive) {
- BKE_gpencil_brush_setactive(ts, brush);
- }
- /* return brush */
- return brush;
-}
+/* ************************************************** */
+/* Data Duplication */
-/* add a new gp-palettecolor and make it the active */
-bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, const char *name, bool setactive)
+/* make a copy of a given gpencil weights */
+void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
{
- bGPDpalettecolor *palcolor;
-
- /* check that list is ok */
- if (palette == NULL) {
- return NULL;
+ if (gps_src == NULL) {
+ return;
}
+ BLI_assert(gps_src->totpoints == gps_dst->totpoints);
- /* allocate memory and add to end of list */
- palcolor = MEM_callocN(sizeof(bGPDpalettecolor), "bGPDpalettecolor");
-
- /* add to datablock */
- BLI_addtail(&palette->colors, palcolor);
-
- /* set basic settings */
- palcolor->flag |= PC_COLOR_HQ_FILL;
- copy_v4_v4(palcolor->color, U.gpencil_new_layer_col);
- ARRAY_SET_ITEMS(palcolor->fill, 1.0f, 1.0f, 1.0f);
+ if ((gps_src->dvert == NULL) || (gps_dst->dvert == NULL)) {
+ return;
+ }
- /* auto-name */
- BLI_strncpy(palcolor->info, name, sizeof(palcolor->info));
- BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info),
- sizeof(palcolor->info));
+ for (int i = 0; i < gps_src->totpoints; i++) {
+ MDeformVert *dvert_src = &gps_src->dvert[i];
+ MDeformVert *dvert_dst = &gps_dst->dvert[i];
+ if (dvert_src->totweight > 0) {
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ }
+ else {
+ dvert_dst->dw = NULL;
+ }
- /* make this one the active one */
- if (setactive) {
- BKE_gpencil_palettecolor_setactive(palette, palcolor);
}
-
- /* return palette color */
- return palcolor;
}
-/* add a new gp-datablock */
-bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
+/* make a copy of a given gpencil stroke */
+bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
{
- bGPdata *gpd;
+ bGPDstroke *gps_dst = NULL;
- /* allocate memory for a new block */
- gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
+ gps_dst = MEM_dupallocN(gps_src);
+ gps_dst->prev = gps_dst->next = NULL;
- /* initial settings */
- gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
+ gps_dst->points = MEM_dupallocN(gps_src->points);
+
+ gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
- /* for now, stick to view is also enabled by default
- * since this is more useful...
+ /* Don't clear triangles, so that modifier evaluation can just use
+ * this without extra work first. Most places that need to force
+ * this data to get recalculated will destroy the data anyway though.
*/
- gpd->flag |= GP_DATA_VIEWALIGN;
+ gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
+ /* gps_dst->flag |= GP_STROKE_RECALC_CACHES; */
- return gpd;
+ /* return new stroke */
+ return gps_dst;
}
-/* -------- Data Duplication ---------- */
-
/* make a copy of a given gpencil frame */
bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
{
- bGPDstroke *gps_dst;
+ bGPDstroke *gps_dst = NULL;
bGPDframe *gpf_dst;
/* error checking */
@@ -660,11 +605,8 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
/* copy strokes */
BLI_listbase_clear(&gpf_dst->strokes);
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
- /* make copy of source stroke, then adjust pointer to points too */
- gps_dst = MEM_dupallocN(gps_src);
- gps_dst->points = MEM_dupallocN(gps_src->points);
- gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
- gps_dst->flag |= GP_STROKE_RECALC_CACHES;
+ /* make copy of source stroke */
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
@@ -672,55 +614,24 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
return gpf_dst;
}
-/* make a copy of a given gpencil brush */
-bGPDbrush *BKE_gpencil_brush_duplicate(const bGPDbrush *brush_src)
+/* make a copy of strokes between gpencil frames */
+void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
{
- bGPDbrush *brush_dst;
-
+ bGPDstroke *gps_dst = NULL;
/* error checking */
- if (brush_src == NULL) {
- return NULL;
- }
-
- /* make a copy of source brush */
- brush_dst = MEM_dupallocN(brush_src);
- brush_dst->prev = brush_dst->next = NULL;
- /* make a copy of curves */
- brush_dst->cur_sensitivity = curvemapping_copy(brush_src->cur_sensitivity);
- brush_dst->cur_strength = curvemapping_copy(brush_src->cur_strength);
- brush_dst->cur_jitter = curvemapping_copy(brush_src->cur_jitter);
-
- /* return new brush */
- return brush_dst;
-}
-
-/* make a copy of a given gpencil palette */
-bGPDpalette *BKE_gpencil_palette_duplicate(const bGPDpalette *palette_src)
-{
- bGPDpalette *palette_dst;
- const bGPDpalettecolor *palcolor_src;
- bGPDpalettecolor *palcolord_dst;
-
- /* error checking */
- if (palette_src == NULL) {
- return NULL;
+ if ((gpf_src == NULL) || (gpf_dst == NULL)) {
+ return;
}
- /* make a copy of source palette */
- palette_dst = MEM_dupallocN(palette_src);
- palette_dst->prev = palette_dst->next = NULL;
-
- /* copy colors */
- BLI_listbase_clear(&palette_dst->colors);
- for (palcolor_src = palette_src->colors.first; palcolor_src; palcolor_src = palcolor_src->next) {
- /* make a copy of source */
- palcolord_dst = MEM_dupallocN(palcolor_src);
- BLI_addtail(&palette_dst->colors, palcolord_dst);
+ /* copy strokes */
+ BLI_listbase_clear(&gpf_dst->strokes);
+ for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
+ /* make copy of source stroke */
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
}
-
- /* return new palette */
- return palette_dst;
}
+
/* make a copy of a given gpencil layer */
bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
{
@@ -736,6 +647,7 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
/* make a copy of source layer */
gpl_dst = MEM_dupallocN(gpl_src);
gpl_dst->prev = gpl_dst->next = NULL;
+ gpl_dst->runtime.derived_data = NULL;
/* copy frames */
BLI_listbase_clear(&gpl_dst->frames);
@@ -755,14 +667,22 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
/**
* Only copy internal data of GreasePencil ID from source to already allocated/initialized destination.
- * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ * You probably never want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
*
* WARNING! This function will not handle ID user count!
*
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-void BKE_gpencil_copy_data(Main *UNUSED(bmain), bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
+void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
{
+ /* cache data is not duplicated */
+ gpd_dst->runtime.batch_cache_data = NULL;
+
+ /* duplicate material array */
+ if (gpd_src->mat) {
+ gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
+ }
+
/* copy layers */
BLI_listbase_clear(&gpd_dst->layers);
for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
@@ -771,45 +691,46 @@ void BKE_gpencil_copy_data(Main *UNUSED(bmain), bGPdata *gpd_dst, const bGPdata
BLI_addtail(&gpd_dst->layers, gpl_dst);
}
- /* copy palettes */
- BLI_listbase_clear(&gpd_dst->palettes);
- for (const bGPDpalette *palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) {
- bGPDpalette *palette_dst = BKE_gpencil_palette_duplicate(palette_src); /* TODO here too could add unused flags... */
- BLI_addtail(&gpd_dst->palettes, palette_dst);
- }
+}
+
+/* Standard API to make a copy of GP datablock, separate from copying its data */
+bGPdata *BKE_gpencil_copy(Main *bmain, const bGPdata *gpd)
+{
+ bGPdata *gpd_copy;
+ BKE_id_copy_ex(bmain, &gpd->id, (ID **)&gpd_copy, 0, false);
+ return gpd_copy;
}
/* make a copy of a given gpencil datablock */
+// XXX: Should this be deprecated?
bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
{
+ bGPdata *gpd_dst;
+
/* Yuck and super-uber-hyper yuck!!!
* Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
* so for now keep old code for that one. */
- if (internal_copy) {
- const bGPDlayer *gpl_src;
- bGPDlayer *gpl_dst;
- bGPdata *gpd_dst;
+ /* error checking */
+ if (gpd_src == NULL) {
+ return NULL;
+ }
+
+ if (internal_copy) {
/* make a straight copy for undo buffers used during stroke drawing */
gpd_dst = MEM_dupallocN(gpd_src);
-
- /* copy layers */
- BLI_listbase_clear(&gpd_dst->layers);
- for (gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
- /* make a copy of source layer and its data */
- gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);
- BLI_addtail(&gpd_dst->layers, gpl_dst);
- }
-
- /* return new */
- return gpd_dst;
}
else {
BLI_assert(bmain != NULL);
- bGPdata *gpd_copy;
- BKE_id_copy_ex(bmain, &gpd_src->id, (ID **)&gpd_copy, 0, false);
- return gpd_copy;
+ BKE_id_copy_ex(bmain, &gpd_src->id, (ID **)&gpd_dst, 0, false);
+ gpd_dst->runtime.batch_cache_data = NULL;
}
+
+ /* Copy internal data (layers, etc.) */
+ BKE_gpencil_copy_data(gpd_dst, gpd_src, 0);
+
+ /* return new */
+ return gpd_dst;
}
void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
@@ -817,7 +738,8 @@ void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
BKE_id_make_local_generic(bmain, &gpd->id, true, lib_local);
}
-/* -------- GP-Stroke API --------- */
+/* ************************************************** */
+/* GP Stroke API */
/* ensure selection status of stroke is in sync with its points */
void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
@@ -842,7 +764,8 @@ void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
}
}
-/* -------- GP-Frame API ---------- */
+/* ************************************************** */
+/* GP Frame API */
/* delete the last stroke of the given frame */
void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
@@ -855,7 +778,13 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
return;
/* free the stroke and its data */
- MEM_freeN(gps->points);
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
MEM_freeN(gps->triangles);
BLI_freelinkN(&gpf->strokes, gps);
@@ -866,7 +795,8 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
}
}
-/* -------- GP-Layer API ---------- */
+/* ************************************************** */
+/* GP Layer API */
/* Check if the given layer is able to be edited or not */
bool gpencil_layer_is_editable(const bGPDlayer *gpl)
@@ -1048,8 +978,6 @@ bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
*/
if (gpl->actframe == gpf)
gpl->actframe = gpf->prev;
- else
- gpl->actframe = NULL;
/* free the frame and its data */
changed = BKE_gpencil_free_strokes(gpf);
@@ -1103,255 +1031,617 @@ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
/* free layer */
BKE_gpencil_free_frames(gpl);
+
+ /* free icon providing preview of icon color */
+ BKE_icon_delete(gpl->runtime.icon_id);
+
+ /* free derived data */
+ BKE_gpencil_clear_derived(gpl);
+ if (gpl->runtime.derived_data) {
+ BLI_ghash_free(gpl->runtime.derived_data, NULL, NULL);
+ gpl->runtime.derived_data = NULL;
+ }
+
BLI_freelinkN(&gpd->layers, gpl);
}
-/* ************************************************** */
-/* get the active gp-brush for editing */
-bGPDbrush *BKE_gpencil_brush_getactive(ToolSettings *ts)
+Material *BKE_gpencil_get_material_from_brush(Brush *brush)
{
- bGPDbrush *brush;
+ Material *ma = NULL;
- /* error checking */
- if (ELEM(NULL, ts, ts->gp_brushes.first)) {
- return NULL;
+ if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
+ (brush->gpencil_settings->material != NULL))
+ {
+ ma = brush->gpencil_settings->material;
}
- /* loop over brushes until found (assume only one active) */
- for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
- if (brush->flag & GP_BRUSH_ACTIVE) {
- return brush;
+ return ma;
+}
+
+/* Get active color, and add all default settings if we don't find anything */
+Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob)
+{
+ Material *ma = NULL;
+
+ /* sanity checks */
+ if (ELEM(NULL, bmain, ob))
+ return NULL;
+
+ ma = give_current_material(ob, ob->actcol);
+ if (ma == NULL) {
+ if (ob->totcol == 0) {
+ BKE_object_material_slot_add(bmain, ob);
}
+ ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
+ assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+ }
+ else if (ma->gp_style == NULL) {
+ BKE_material_init_gpencil_settings(ma);
}
- /* no active brush found */
- return NULL;
+ return ma;
}
-/* set the active gp-brush */
-void BKE_gpencil_brush_setactive(ToolSettings *ts, bGPDbrush *active)
+/* ************************************************** */
+/* GP Object - Boundbox Support */
+
+/**
+ * Get min/max coordinate bounds for single stroke
+ * \return Returns whether we found any selected points
+ */
+bool BKE_gpencil_stroke_minmax(
+ const bGPDstroke *gps, const bool use_select,
+ float r_min[3], float r_max[3])
{
- bGPDbrush *brush;
+ const bGPDspoint *pt;
+ int i;
+ bool changed = false;
- /* error checking */
- if (ELEM(NULL, ts, ts->gp_brushes.first, active)) {
- return;
- }
+ if (ELEM(NULL, gps, r_min, r_max))
+ return false;
- /* loop over brushes deactivating all */
- for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
- brush->flag &= ~GP_BRUSH_ACTIVE;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
+ minmax_v3v3_v3(r_min, r_max, &pt->x);
+ changed = true;
+ }
}
-
- /* set as active one */
- active->flag |= GP_BRUSH_ACTIVE;
+ return changed;
}
-/* delete the active gp-brush */
-void BKE_gpencil_brush_delete(ToolSettings *ts, bGPDbrush *brush)
+/* get min/max bounds of all strokes in GP datablock */
+static void gpencil_minmax(bGPdata *gpd, float r_min[3], float r_max[3])
{
- /* error checking */
- if (ELEM(NULL, ts, brush)) {
+ INIT_MINMAX(r_min, r_max);
+
+ if (gpd == NULL)
return;
- }
- /* free curves */
- if (brush->cur_sensitivity) {
- curvemapping_free(brush->cur_sensitivity);
- }
- if (brush->cur_strength) {
- curvemapping_free(brush->cur_strength);
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *gpf = gpl->actframe;
+
+ if (gpf != NULL) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
+ }
+ }
}
- if (brush->cur_jitter) {
- curvemapping_free(brush->cur_jitter);
+}
+
+/* compute center of bounding box */
+void BKE_gpencil_centroid_3D(bGPdata *gpd, float r_centroid[3])
+{
+ float min[3], max[3], tot[3];
+
+ gpencil_minmax(gpd, min, max);
+
+ add_v3_v3v3(tot, min, max);
+ mul_v3_v3fl(r_centroid, tot, 0.5f);
+}
+
+
+/* create bounding box values */
+static void boundbox_gpencil(Object *ob)
+{
+ BoundBox *bb;
+ bGPdata *gpd;
+ float min[3], max[3];
+
+ if (ob->bb == NULL) {
+ ob->bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
}
- /* free */
- BLI_freelinkN(&ts->gp_brushes, brush);
+ bb = ob->bb;
+ gpd = ob->data;
+
+ gpencil_minmax(gpd, min, max);
+ BKE_boundbox_init_from_minmax(bb, min, max);
+
+ bb->flag &= ~BOUNDBOX_DIRTY;
}
-/* ************************************************** */
-/* get the active gp-palette for editing */
-bGPDpalette *BKE_gpencil_palette_getactive(bGPdata *gpd)
+/* get bounding box */
+BoundBox *BKE_gpencil_boundbox_get(Object *ob)
{
- bGPDpalette *palette;
+ bGPdata *gpd;
- /* error checking */
- if (ELEM(NULL, gpd, gpd->palettes.first)) {
+ if (ELEM(NULL, ob, ob->data))
return NULL;
- }
- /* loop over palettes until found (assume only one active) */
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
- if (palette->flag & PL_PALETTE_ACTIVE)
- return palette;
+ gpd = ob->data;
+ if ((ob->bb) && ((ob->bb->flag & BOUNDBOX_DIRTY) == 0) &&
+ ((gpd->flag & GP_DATA_CACHE_IS_DIRTY) == 0))
+ {
+ return ob->bb;
}
- /* no active palette found */
- return NULL;
+ boundbox_gpencil(ob);
+
+ return ob->bb;
}
-/* set the active gp-palette */
-void BKE_gpencil_palette_setactive(bGPdata *gpd, bGPDpalette *active)
-{
- bGPDpalette *palette;
+/* ************************************************** */
+/* Apply Transforms */
- /* error checking */
- if (ELEM(NULL, gpd, gpd->palettes.first, active)) {
+void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
+{
+ if (gpd == NULL)
return;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* FIXME: For now, we just skip parented layers.
+ * Otherwise, we have to update each frame to find
+ * the current parent position/effects.
+ */
+ if (gpl->parent) {
+ continue;
+ }
+
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt;
+ int i;
+
+ for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
+ mul_m4_v3(mat, &pt->x);
+ }
+
+ /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
+ }
+ }
}
- /* loop over palettes deactivating all */
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
- palette->flag &= ~PL_PALETTE_ACTIVE;
+}
+
+/* ************************************************** */
+/* GP Object - Vertex Groups */
+
+/* remove a vertex group */
+void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
+{
+ bGPdata *gpd = ob->data;
+ MDeformVert *dvert = NULL;
+ MDeformWeight *gpw = NULL;
+ const int def_nr = BLI_findindex(&ob->defbase, defgroup);
+
+ /* Remove points data */
+ if (gpd) {
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ for (int i2 = 0; i2 < dvert->totweight; i2++) {
+ gpw = &dvert->dw[i2];
+ if (gpw->def_nr == def_nr) {
+ BKE_gpencil_vgroup_remove_point_weight(dvert, def_nr);
+ }
+ /* if index is greater, must be moved one back */
+ if (gpw->def_nr > def_nr) {
+ gpw->def_nr--;
+ }
+ }
+ }
+ }
+ }
+ }
}
- /* set as active one */
- active->flag |= PL_PALETTE_ACTIVE;
- /* force color recalc */
- BKE_gpencil_palette_change_strokes(gpd);
+ /* Remove the group */
+ BLI_freelinkN(&ob->defbase, defgroup);
}
-/* delete the active gp-palette */
-void BKE_gpencil_palette_delete(bGPdata *gpd, bGPDpalette *palette)
+/* add a new weight */
+MDeformWeight *BKE_gpencil_vgroup_add_point_weight(MDeformVert *dvert, int index, float weight)
{
- /* error checking */
- if (ELEM(NULL, gpd, palette)) {
- return;
+ MDeformWeight *new_gpw = NULL;
+ MDeformWeight *tmp_gpw;
+
+ /* need to verify if was used before to update */
+ for (int i = 0; i < dvert->totweight; i++) {
+ tmp_gpw = &dvert->dw[i];
+ if (tmp_gpw->def_nr == index) {
+ tmp_gpw->weight = weight;
+ return tmp_gpw;
+ }
}
- /* free colors */
- free_gpencil_colors(palette);
- BLI_freelinkN(&gpd->palettes, palette);
- /* force color recalc */
- BKE_gpencil_palette_change_strokes(gpd);
+ dvert->totweight++;
+ if (dvert->totweight == 1) {
+ dvert->dw = MEM_callocN(sizeof(MDeformWeight), "gp_weight");
+ }
+ else {
+ dvert->dw = MEM_reallocN(dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
+ }
+ new_gpw = &dvert->dw[dvert->totweight - 1];
+ new_gpw->def_nr = index;
+ new_gpw->weight = weight;
+
+ return new_gpw;
}
-/* Set all strokes to recalc the palette color */
-void BKE_gpencil_palette_change_strokes(bGPdata *gpd)
+/* return the weight if use index or -1*/
+float BKE_gpencil_vgroup_use_index(MDeformVert *dvert, int index)
{
- bGPDlayer *gpl;
- bGPDframe *gpf;
- bGPDstroke *gps;
+ MDeformWeight *gpw;
+ for (int i = 0; i < dvert->totweight; i++) {
+ gpw = &dvert->dw[i];
+ if (gpw->def_nr == index) {
+ return gpw->weight;
+ }
+ }
+ return -1.0f;
+}
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- gps->flag |= GP_STROKE_RECALC_COLOR;
- }
+/* add a new weight */
+bool BKE_gpencil_vgroup_remove_point_weight(MDeformVert *dvert, int index)
+{
+ int e = 0;
+
+ if (BKE_gpencil_vgroup_use_index(dvert, index) < 0.0f) {
+ return false;
+ }
+
+ /* if the array get empty, exit */
+ if (dvert->totweight == 1) {
+ dvert->totweight = 0;
+ MEM_SAFE_FREE(dvert->dw);
+ return true;
+ }
+
+ /* realloc weights */
+ MDeformWeight *tmp = MEM_dupallocN(dvert->dw);
+ MEM_SAFE_FREE(dvert->dw);
+ dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight - 1, "gp_weights");
+
+ for (int x = 0; x < dvert->totweight; x++) {
+ MDeformWeight *gpw = &tmp[e];
+ MDeformWeight *final_gpw = &dvert->dw[e];
+ if (gpw->def_nr != index) {
+ final_gpw->def_nr = gpw->def_nr;
+ final_gpw->weight = gpw->weight;
+ e++;
}
}
+ MEM_SAFE_FREE(tmp);
+ dvert->totweight--;
+
+ return true;
}
-/* get the active gp-palettecolor for editing */
-bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(bGPDpalette *palette)
+/* ************************************************** */
+
+/**
+ * Apply smooth to stroke point
+ * \param gps Stroke to smooth
+ * \param i Point index
+ * \param inf Amount of smoothing to apply
+ */
+bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
{
- bGPDpalettecolor *palcolor;
+ bGPDspoint *pt = &gps->points[i];
+ // float pressure = 0.0f;
+ float sco[3] = { 0.0f };
- /* error checking */
- if (ELEM(NULL, palette, palette->colors.first)) {
- return NULL;
+ /* Do nothing if not enough points to smooth out */
+ if (gps->totpoints <= 2) {
+ return false;
+ }
+
+ /* Only affect endpoints by a fraction of the normal strength,
+ * to prevent the stroke from shrinking too much
+ */
+ if ((i == 0) || (i == gps->totpoints - 1)) {
+ inf *= 0.1f;
}
- /* loop over colors until found (assume only one active) */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- if (palcolor->flag & PC_COLOR_ACTIVE) {
- return palcolor;
+ /* Compute smoothed coordinate by taking the ones nearby */
+ /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
+ {
+ // XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
+ const int steps = 2;
+ const float average_fac = 1.0f / (float)(steps * 2 + 1);
+ int step;
+
+ /* add the point itself */
+ madd_v3_v3fl(sco, &pt->x, average_fac);
+
+ /* n-steps before/after current point */
+ // XXX: review how the endpoints are treated by this algorithm
+ // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
+ for (step = 1; step <= steps; step++) {
+ bGPDspoint *pt1, *pt2;
+ int before = i - step;
+ int after = i + step;
+
+ CLAMP_MIN(before, 0);
+ CLAMP_MAX(after, gps->totpoints - 1);
+
+ pt1 = &gps->points[before];
+ pt2 = &gps->points[after];
+
+ /* add both these points to the average-sum (s += p[i]/n) */
+ madd_v3_v3fl(sco, &pt1->x, average_fac);
+ madd_v3_v3fl(sco, &pt2->x, average_fac);
+
}
}
- /* no active color found */
- return NULL;
+ /* Based on influence factor, blend between original and optimal smoothed coordinate */
+ interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
+
+ return true;
}
-/* get the gp-palettecolor looking for name */
-bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(bGPDpalette *palette, char *name)
+
+/**
+ * Apply smooth for strength to stroke point */
+bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
{
- /* error checking */
- if (ELEM(NULL, palette, name)) {
- return NULL;
+ bGPDspoint *ptb = &gps->points[point_index];
+
+ /* Do nothing if not enough points */
+ if (gps->totpoints <= 2) {
+ return false;
}
- return BLI_findstring(&palette->colors, name, offsetof(bGPDpalettecolor, info));
+ /* Compute theoretical optimal value using distances */
+ bGPDspoint *pta, *ptc;
+ int before = point_index - 1;
+ int after = point_index + 1;
+
+ CLAMP_MIN(before, 0);
+ CLAMP_MAX(after, gps->totpoints - 1);
+
+ pta = &gps->points[before];
+ ptc = &gps->points[after];
+
+ /* the optimal value is the corresponding to the interpolation of the strength
+ * at the distance of point b
+ */
+ const float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
+ const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
+
+ /* Based on influence factor, blend between original and optimal */
+ ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal;
+
+ return true;
}
-/* Change color name in all strokes */
-void BKE_gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *newname)
+/**
+ * Apply smooth for thickness to stroke point (use pressure) */
+bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
{
- bGPDlayer *gpl;
- bGPDframe *gpf;
- bGPDstroke *gps;
+ bGPDspoint *ptb = &gps->points[point_index];
- /* Sanity checks (gpd may not be set in the RNA pointers sometimes) */
- if (ELEM(NULL, gpd, oldname, newname))
- return;
+ /* Do nothing if not enough points */
+ if (gps->totpoints <= 2) {
+ return false;
+ }
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (STREQ(gps->colorname, oldname)) {
- BLI_strncpy(gps->colorname, newname, sizeof(gps->colorname));
- }
+ /* Compute theoretical optimal value using distances */
+ bGPDspoint *pta, *ptc;
+ int before = point_index - 1;
+ int after = point_index + 1;
+
+ CLAMP_MIN(before, 0);
+ CLAMP_MAX(after, gps->totpoints - 1);
+
+ pta = &gps->points[before];
+ ptc = &gps->points[after];
+
+ /* the optimal value is the corresponding to the interpolation of the pressure
+ * at the distance of point b
+ */
+ float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
+ float optimal = interpf(ptc->pressure, pta->pressure, fac);
+
+ /* Based on influence factor, blend between original and optimal */
+ ptb->pressure = interpf(optimal, ptb->pressure, influence);
+
+ return true;
+}
+
+/**
+* Apply smooth for UV rotation to stroke point (use pressure) */
+bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
+{
+ bGPDspoint *ptb = &gps->points[point_index];
+
+ /* Do nothing if not enough points */
+ if (gps->totpoints <= 2) {
+ return false;
+ }
+
+ /* Compute theoretical optimal value */
+ bGPDspoint *pta, *ptc;
+ int before = point_index - 1;
+ int after = point_index + 1;
+
+ CLAMP_MIN(before, 0);
+ CLAMP_MAX(after, gps->totpoints - 1);
+
+ pta = &gps->points[before];
+ ptc = &gps->points[after];
+
+ /* the optimal value is the corresponding to the interpolation of the pressure
+ * at the distance of point b
+ */
+ float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
+ float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
+
+ /* Based on influence factor, blend between original and optimal */
+ ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
+ CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
+
+ return true;
+}
+
+/**
+ * Get range of selected frames in layer.
+ * Always the active frame is considered as selected, so if no more selected the range
+ * will be equal to the current active frame.
+ * \param gpl Layer
+ * \param r_initframe Number of first selected frame
+ * \param r_endframe Number of last selected frame
+ */
+void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
+{
+ *r_initframe = gpl->actframe->framenum;
+ *r_endframe = gpl->actframe->framenum;
+
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ if (gpf->framenum < *r_initframe) {
+ *r_initframe = gpf->framenum;
+ }
+ if (gpf->framenum > *r_endframe) {
+ *r_endframe = gpf->framenum;
}
}
}
+}
+/**
+ * Get Falloff factor base on frame range
+ * \param gpf Frame
+ * \param actnum Number of active frame in layer
+ * \param f_init Number of first selected frame
+ * \param f_end Number of last selected frame
+ * \param cur_falloff Curve with falloff factors
+ */
+float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
+{
+ float fnum = 0.5f; /* default mid curve */
+ float value;
+
+ /* frames to the right of the active frame */
+ if (gpf->framenum < actnum) {
+ fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
+ fnum *= 0.5f;
+ value = curvemapping_evaluateF(cur_falloff, 0, fnum);
+ }
+ /* frames to the left of the active frame */
+ else if (gpf->framenum > actnum) {
+ fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
+ fnum *= 0.5f;
+ value = curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
+ }
+ else {
+ value = 1.0f;
+ }
+
+ return value;
}
-/* Delete all strokes of the color */
-void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name)
+/* remove strokes using a material */
+void BKE_gpencil_material_index_remove(bGPdata *gpd, int index)
{
- bGPDlayer *gpl;
- bGPDframe *gpf;
bGPDstroke *gps, *gpsn;
- /* Sanity checks (gpd may not be set in the RNA pointers sometimes) */
- if (ELEM(NULL, gpd, name))
- return;
-
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- if (STREQ(gps->colorname, name)) {
- if (gps->points) MEM_freeN(gps->points);
- if (gps->triangles) MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+ if (gps->mat_nr == index) {
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ if (gps->triangles) MEM_freeN(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+ else {
+ /* reassign strokes */
+ if (gps->mat_nr > index) {
+ gps->mat_nr--;
+ }
+ }
}
}
}
- }
-
}
-/* set the active gp-palettecolor */
-void BKE_gpencil_palettecolor_setactive(bGPDpalette *palette, bGPDpalettecolor *active)
+void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len)
{
- bGPDpalettecolor *palcolor;
-
- /* error checking */
- if (ELEM(NULL, palette, palette->colors.first, active)) {
- return;
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* reassign strokes */
+ MAT_NR_REMAP(gps->mat_nr);
+ }
+ }
}
- /* loop over colors deactivating all */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag &= ~PC_COLOR_ACTIVE;
+#undef MAT_NR_REMAP
+
+}
+
+/* statistics functions */
+void BKE_gpencil_stats_update(bGPdata *gpd)
+{
+ gpd->totlayer = 0;
+ gpd->totframe = 0;
+ gpd->totstroke = 0;
+ gpd->totpoint = 0;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpd->totlayer++;
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ gpd->totframe++;
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ gpd->totstroke++;
+ gpd->totpoint += gps->totpoints;
+ }
+ }
}
- /* set as active one */
- active->flag |= PC_COLOR_ACTIVE;
}
-/* delete the active gp-palettecolor */
-void BKE_gpencil_palettecolor_delete(bGPDpalette *palette, bGPDpalettecolor *palcolor)
+/* get material index */
+int BKE_gpencil_get_material_index(Object *ob, Material *ma)
{
- /* error checking */
- if (ELEM(NULL, palette, palcolor)) {
- return;
+ short *totcol = give_totcolp(ob);
+ Material *read_ma = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ read_ma = give_current_material(ob, i + 1);
+ if (ma == read_ma) {
+ return i + 1;
+ }
}
- /* free */
- BLI_freelinkN(&palette->colors, palcolor);
+ return 0;
}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
new file mode 100644
index 00000000000..d1c455f64e1
--- /dev/null
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -0,0 +1,687 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/gpencil_modifier.c
+ * \ingroup bke
+ */
+
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_gpencil.h"
+#include "BKE_lattice.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_object.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+
+static GpencilModifierTypeInfo *modifier_gpencil_types[NUM_GREASEPENCIL_MODIFIER_TYPES] = { NULL };
+
+/* *************************************************** */
+/* Geometry Utilities */
+
+/* calculate stroke normal using some points */
+void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
+{
+ if (gps->totpoints < 3) {
+ zero_v3(r_normal);
+ return;
+ }
+
+ bGPDspoint *points = gps->points;
+ int totpoints = gps->totpoints;
+
+ const bGPDspoint *pt0 = &points[0];
+ const bGPDspoint *pt1 = &points[1];
+ const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
+ float vec1[3];
+ float vec2[3];
+
+ /* initial vector (p0 -> p1) */
+ sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
+
+ /* point vector at 3/4 */
+ sub_v3_v3v3(vec2, &pt3->x, &pt0->x);
+
+ /* vector orthogonal to polygon plane */
+ cross_v3_v3v3(r_normal, vec1, vec2);
+
+ /* Normalize vector */
+ normalize_v3(r_normal);
+}
+
+/* Get points of stroke always flat to view not affected by camera view or view position */
+static void gpencil_stroke_project_2d(const bGPDspoint *points, int totpoints, vec2f *points2d)
+{
+ const bGPDspoint *pt0 = &points[0];
+ const bGPDspoint *pt1 = &points[1];
+ const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
+ float locx[3];
+ float locy[3];
+ float loc3[3];
+ float normal[3];
+
+ /* local X axis (p0 -> p1) */
+ sub_v3_v3v3(locx, &pt1->x, &pt0->x);
+
+ /* point vector at 3/4 */
+ sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
+
+ /* vector orthogonal to polygon plane */
+ cross_v3_v3v3(normal, locx, loc3);
+
+ /* local Y axis (cross to normal/x axis) */
+ cross_v3_v3v3(locy, normal, locx);
+
+ /* Normalize vectors */
+ normalize_v3(locx);
+ normalize_v3(locy);
+
+ /* Get all points in local space */
+ for (int i = 0; i < totpoints; i++) {
+ const bGPDspoint *pt = &points[i];
+ float loc[3];
+
+ /* Get local space using first point as origin */
+ sub_v3_v3v3(loc, &pt->x, &pt0->x);
+
+ vec2f *point = &points2d[i];
+ point->x = dot_v3v3(loc, locx);
+ point->y = dot_v3v3(loc, locy);
+ }
+
+}
+
+/* Stroke Simplify ------------------------------------- */
+
+/* Reduce a series of points to a simplified version, but
+ * maintains the general shape of the series
+ *
+ * Ramer - Douglas - Peucker algorithm
+ * by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ */
+static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
+{
+ vec2f *old_points2d = points2d;
+ int totpoints = gps->totpoints;
+ char *marked = NULL;
+ char work;
+
+ int start = 1;
+ int end = gps->totpoints - 2;
+
+ marked = MEM_callocN(totpoints, "GP marked array");
+ marked[start] = 1;
+ marked[end] = 1;
+
+ work = 1;
+ int totmarked = 0;
+ /* while still reducing */
+ while (work) {
+ int ls, le;
+ work = 0;
+
+ ls = start;
+ le = start + 1;
+
+ /* while not over interval */
+ while (ls < end) {
+ int max_i = 0;
+ float v1[2];
+ /* divided to get more control */
+ float max_dist = epsilon / 10.0f;
+
+ /* find the next marked point */
+ while (marked[le] == 0) {
+ le++;
+ }
+
+ /* perpendicular vector to ls-le */
+ v1[1] = old_points2d[le].x - old_points2d[ls].x;
+ v1[0] = old_points2d[ls].y - old_points2d[le].y;
+
+ for (int i = ls + 1; i < le; i++) {
+ float mul;
+ float dist;
+ float v2[2];
+
+ v2[0] = old_points2d[i].x - old_points2d[ls].x;
+ v2[1] = old_points2d[i].y - old_points2d[ls].y;
+
+ if (v2[0] == 0 && v2[1] == 0) {
+ continue;
+ }
+
+ mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]);
+
+ dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]);
+
+ if (dist > max_dist) {
+ max_dist = dist;
+ max_i = i;
+ }
+ }
+
+ if (max_i != 0) {
+ work = 1;
+ marked[max_i] = 1;
+ totmarked++;
+ }
+
+ ls = le;
+ le = ls + 1;
+ }
+ }
+
+ /* adding points marked */
+ bGPDspoint *old_points = MEM_dupallocN(gps->points);
+ MDeformVert *old_dvert = MEM_dupallocN(gps->dvert);
+
+ /* resize gps */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
+
+ int j = 0;
+ for (int i = 0; i < totpoints; i++) {
+ bGPDspoint *pt_src = &old_points[i];
+ bGPDspoint *pt = &gps->points[j];
+
+ MDeformVert *dvert_src = &old_dvert[i];
+ MDeformVert *dvert = &gps->dvert[j];
+
+ if ((marked[i]) || (i == 0) || (i == totpoints - 1)) {
+ memcpy(pt, pt_src, sizeof(bGPDspoint));
+ memcpy(dvert, dvert_src, sizeof(MDeformVert));
+ j++;
+ }
+ else {
+ BKE_gpencil_free_point_weights(dvert_src);
+ }
+ }
+
+ gps->totpoints = j;
+
+ MEM_SAFE_FREE(old_points);
+ MEM_SAFE_FREE(old_dvert);
+ MEM_SAFE_FREE(marked);
+}
+
+/* Simplify stroke using Ramer-Douglas-Peucker algorithm */
+void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float factor)
+{
+ /* first create temp data and convert points to 2D */
+ vec2f *points2d = MEM_mallocN(sizeof(vec2f) * gps->totpoints, "GP Stroke temp 2d points");
+
+ /* for some old files, the weights array could not be initializated */
+ if (gps->dvert == NULL) {
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
+ }
+
+ gpencil_stroke_project_2d(gps->points, gps->totpoints, points2d);
+
+ gpencil_rdp_stroke(gps, points2d, factor);
+
+ MEM_SAFE_FREE(points2d);
+}
+
+/* Simplify alternate vertex of stroke except extrems */
+void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
+{
+ if (gps->totpoints < 5) {
+ return;
+ }
+
+ /* for some old files, the weights array could not be initializated */
+ if (gps->dvert == NULL) {
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
+ }
+
+ /* save points */
+ bGPDspoint *old_points = MEM_dupallocN(gps->points);
+ MDeformVert *old_dvert = MEM_dupallocN(gps->dvert);
+
+ /* resize gps */
+ int newtot = (gps->totpoints - 2) / 2;
+ if (((gps->totpoints - 2) % 2) > 0) {
+ newtot++;
+ }
+ newtot += 2;
+
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
+
+ int j = 0;
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt_src = &old_points[i];
+ bGPDspoint *pt = &gps->points[j];
+
+ MDeformVert *dvert_src = &old_dvert[i];
+ MDeformVert *dvert = &gps->dvert[j];
+
+ if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) {
+ memcpy(pt, pt_src, sizeof(bGPDspoint));
+ memcpy(dvert, dvert_src, sizeof(MDeformVert));
+ j++;
+ }
+ else {
+ BKE_gpencil_free_point_weights(dvert_src);
+ }
+ }
+
+ gps->totpoints = j;
+
+ MEM_SAFE_FREE(old_points);
+ MEM_SAFE_FREE(old_dvert);
+}
+
+/* *************************************************** */
+/* Modifier Utilities */
+
+/* Lattice Modifier ---------------------------------- */
+/* Usually, evaluation of the lattice modifier is self-contained.
+ * However, since GP's modifiers operate on a per-stroke basis,
+ * we need to these two extra functions that called before/after
+ * each loop over all the geometry being evaluated.
+ */
+
+/* init lattice deform data */
+void BKE_gpencil_lattice_init(Object *ob)
+{
+ GpencilModifierData *md;
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if (md->type == eGpencilModifierType_Lattice) {
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ Object *latob = NULL;
+
+ latob = mmd->object;
+ if ((!latob) || (latob->type != OB_LATTICE)) {
+ return;
+ }
+ if (mmd->cache_data) {
+ end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ }
+
+ /* init deform data */
+ mmd->cache_data = (struct LatticeDeformData *)init_latt_deform(latob, ob);
+ }
+ }
+}
+
+/* clear lattice deform data */
+void BKE_gpencil_lattice_clear(Object *ob)
+{
+ GpencilModifierData *md;
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if (md->type == eGpencilModifierType_Lattice) {
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ if ((mmd) && (mmd->cache_data)) {
+ end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ mmd->cache_data = NULL;
+ }
+ }
+ }
+}
+
+/* *************************************************** */
+/* Modifier Methods - Evaluation Loops, etc. */
+
+/* check if exist geometry modifiers */
+bool BKE_gpencil_has_geometry_modifiers(Object *ob)
+{
+ GpencilModifierData *md;
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti && mti->generateStrokes) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* apply stroke modifiers */
+void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *UNUSED(gpf), bGPDstroke *gps, bool is_render)
+{
+ GpencilModifierData *md;
+ bGPdata *gpd = ob->data;
+ const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
+
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
+ continue;
+ }
+
+ if (mti && mti->deformStroke) {
+ mti->deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+/* apply stroke geometry modifiers */
+void BKE_gpencil_geometry_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bool is_render)
+{
+ GpencilModifierData *md;
+ bGPdata *gpd = ob->data;
+ const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
+
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
+ continue;
+ }
+
+ if (mti->generateStrokes) {
+ mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
+ }
+ }
+ }
+}
+
+/* *************************************************** */
+
+void BKE_gpencil_eval_geometry(Depsgraph *depsgraph,
+ bGPdata *gpd)
+{
+ DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
+ int ctime = (int)DEG_get_ctime(depsgraph);
+
+ /* update active frame */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
+ }
+
+ /* TODO: Move "derived_gpf" logic here from DRW_gpencil_populate_datablock()?
+ * This would be better than inventing our own logic for this stuff...
+ */
+
+ /* TODO: Move the following code to "BKE_gpencil_eval_done()" (marked as an exit node)
+ * later when there's more happening here. For now, let's just keep this in here to avoid
+ * needing to have one more node slowing down evaluation...
+ */
+ if (DEG_is_active(depsgraph)) {
+ bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
+
+ /* sync "actframe" changes back to main-db too,
+ * so that editing tools work with copy-on-write
+ * when the current frame changes
+ */
+ for (bGPDlayer *gpl = gpd_orig->layers.first; gpl; gpl = gpl->next) {
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
+ }
+ }
+}
+
+void BKE_gpencil_modifier_init(void)
+{
+ /* Initialize modifier types */
+ gpencil_modifier_type_init(modifier_gpencil_types); /* MOD_gpencil_util.c */
+}
+
+GpencilModifierData *BKE_gpencil_modifier_new(int type)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
+ GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name);
+
+ /* note, this name must be made unique later */
+ BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
+
+ md->type = type;
+ md->mode = eGpencilModifierMode_Realtime | eGpencilModifierMode_Render | eGpencilModifierMode_Expanded;
+ md->flag = eGpencilModifierFlag_StaticOverride_Local;
+
+ if (mti->flags & eGpencilModifierTypeFlag_EnableInEditmode)
+ md->mode |= eGpencilModifierMode_Editmode;
+
+ if (mti->initData) mti->initData(md);
+
+ return md;
+}
+
+static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_min(id);
+ }
+}
+
+void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (mti->foreachIDLink) {
+ mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
+ }
+ else if (mti->foreachObjectLink) {
+ mti->foreachObjectLink(md, NULL, (GreasePencilObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
+ }
+ }
+
+ if (mti->freeData) mti->freeData(md);
+ if (md->error) MEM_freeN(md->error);
+
+ MEM_freeN(md);
+}
+
+void BKE_gpencil_modifier_free(GpencilModifierData *md)
+{
+ BKE_gpencil_modifier_free_ex(md, 0);
+}
+
+/* check unique name */
+bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd)
+{
+ if (modifiers && gmd) {
+ const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifierType_getInfo(gmd->type);
+ return BLI_uniquename(modifiers, gmd, DATA_(gmti->name), '.', offsetof(GpencilModifierData, name), sizeof(gmd->name));
+ }
+ return false;
+}
+
+bool BKE_gpencil_modifier_dependsOnTime(GpencilModifierData *md)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ return mti->dependsOnTime && mti->dependsOnTime(md);
+}
+
+const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type)
+{
+ /* type unsigned, no need to check < 0 */
+ if (type < NUM_GREASEPENCIL_MODIFIER_TYPES && modifier_gpencil_types[type]->name[0] != '\0') {
+ return modifier_gpencil_types[type];
+ }
+ else {
+ return NULL;
+ }
+}
+
+void BKE_gpencil_modifier_copyData_generic(const GpencilModifierData *md_src, GpencilModifierData *md_dst)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md_src->type);
+
+ /* md_dst may have alredy be fully initialized with some extra allocated data,
+ * we need to free it now to avoid memleak. */
+ if (mti->freeData) {
+ mti->freeData(md_dst);
+ }
+
+ const size_t data_size = sizeof(GpencilModifierData);
+ const char *md_src_data = ((const char *)md_src) + data_size;
+ char *md_dst_data = ((char *)md_dst) + data_size;
+ BLI_assert(data_size <= (size_t)mti->struct_size);
+ memcpy(md_dst_data, md_src_data, (size_t)mti->struct_size - data_size);
+}
+
+static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_plus(id);
+ }
+}
+
+void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, GpencilModifierData *target, const int flag)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ target->mode = md->mode;
+ target->flag = md->flag;
+
+ if (mti->copyData) {
+ mti->copyData(md, target);
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (mti->foreachIDLink) {
+ mti->foreachIDLink(target, NULL, gpencil_modifier_copy_data_id_us_cb, NULL);
+ }
+ else if (mti->foreachObjectLink) {
+ mti->foreachObjectLink(target, NULL, (GreasePencilObjectWalkFunc)gpencil_modifier_copy_data_id_us_cb, NULL);
+ }
+ }
+}
+
+void BKE_gpencil_modifier_copyData(GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_ex(md, target, 0);
+}
+
+GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifierType type)
+{
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+
+ for (; md; md = md->next)
+ if (md->type == type)
+ break;
+
+ return md;
+}
+
+void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk, void *userData)
+{
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+
+ for (; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
+ else if (mti->foreachObjectLink) {
+ /* each Object can masquerade as an ID, so this should be OK */
+ GreasePencilObjectWalkFunc fp = (GreasePencilObjectWalkFunc)walk;
+ mti->foreachObjectLink(md, ob, fp, userData);
+ }
+ }
+}
+
+void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc walk, void *userData)
+{
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+
+ for (; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti->foreachTexLink)
+ mti->foreachTexLink(md, ob, walk, userData);
+ }
+}
+
+GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *name)
+{
+ return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
+}
+
+/* helper function for per-instance positioning */
+void BKE_gpencil_instance_modifier_instance_tfm(InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4])
+{
+ float offset[3], rot[3], scale[3];
+ int ri = mmd->rnd[0];
+ float factor;
+
+ offset[0] = mmd->offset[0] * elem_idx[0];
+ offset[1] = mmd->offset[1] * elem_idx[1];
+ offset[2] = mmd->offset[2] * elem_idx[2];
+
+ /* rotation */
+ if (mmd->flag & GP_INSTANCE_RANDOM_ROT) {
+ factor = mmd->rnd_rot * mmd->rnd[ri];
+ mul_v3_v3fl(rot, mmd->rot, factor);
+ add_v3_v3(rot, mmd->rot);
+ }
+ else {
+ copy_v3_v3(rot, mmd->rot);
+ }
+
+ /* scale */
+ if (mmd->flag & GP_INSTANCE_RANDOM_SIZE) {
+ factor = mmd->rnd_size * mmd->rnd[ri];
+ mul_v3_v3fl(scale, mmd->scale, factor);
+ add_v3_v3(scale, mmd->scale);
+ }
+ else {
+ copy_v3_v3(scale, mmd->scale);
+ }
+
+ /* advance random index */
+ mmd->rnd[0]++;
+ if (mmd->rnd[0] > 19) {
+ mmd->rnd[0] = 1;
+ }
+
+ /* calculate matrix */
+ loc_eul_size_to_mat4(r_mat, offset, rot, scale);
+}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 1c2575dfa52..3a4bf53e22d 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -37,6 +37,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -45,7 +47,6 @@
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -127,6 +128,9 @@ static void icon_free_data(int icon_id, Icon *icon)
else if (icon->obj_type == ICON_DATA_PREVIEW) {
((PreviewImage *)(icon->obj))->icon_id = 0;
}
+ else if (icon->obj_type == ICON_DATA_GPLAYER) {
+ ((bGPDlayer *)(icon->obj))->runtime.icon_id = 0;
+ }
else if (icon->obj_type == ICON_DATA_GEOM) {
((struct Icon_Geom *)(icon->obj))->icon_id = 0;
}
@@ -598,6 +602,44 @@ int BKE_icon_id_ensure(struct ID *id)
return icon_id_ensure_create_icon(id);
}
+
+static int icon_gplayer_color_ensure_create_icon(bGPDlayer *gpl)
+{
+ BLI_assert(BLI_thread_is_main());
+
+ /* NOTE: The color previews for GP Layers don't really need
+ * to be "rendered" to image per se (as it will just be a plain
+ * colored rectangle), we need to define icon data here so that
+ * we can store a pointer to the layer data in icon->obj.
+ */
+ Icon *icon = icon_create(gpl->runtime.icon_id, ICON_DATA_GPLAYER, gpl);
+ icon->flag = ICON_FLAG_MANAGED;
+
+ return gpl->runtime.icon_id;
+}
+
+int BKE_icon_gplayer_color_ensure(bGPDlayer *gpl)
+{
+ /* Never handle icons in non-main thread! */
+ BLI_assert(BLI_thread_is_main());
+
+ if (!gpl || G.background) {
+ return 0;
+ }
+
+ if (gpl->runtime.icon_id)
+ return gpl->runtime.icon_id;
+
+ gpl->runtime.icon_id = get_next_free_id();
+
+ if (!gpl->runtime.icon_id) {
+ printf("%s: Internal error - not enough IDs\n", __func__);
+ return 0;
+ }
+
+ return icon_gplayer_color_ensure_create_icon(gpl);
+}
+
/**
* Return icon id of given preview, or create new icon if not found.
*/
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index b7ca73e9f4a..3be40b414a6 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1717,8 +1717,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* IPO first to take into any non-NLA'd Object Animation */
if (ob->ipo) {
ipo_to_animdata(bmain, id, ob->ipo, NULL, NULL, NULL);
-
- id_us_min(&ob->ipo->id);
+ /* No need to id_us_min ipo ID here, ipo_to_animdata already does it. */
ob->ipo = NULL;
}
@@ -1751,7 +1750,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* IPO second... */
if (ob->ipo) {
ipo_to_animdata(bmain, id, ob->ipo, NULL, NULL, NULL);
- id_us_min(&ob->ipo->id);
+ /* No need to id_us_min ipo ID here, ipo_to_animdata already does it. */
ob->ipo = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 13f7716cd80..0d8e281fa06 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -1457,7 +1457,7 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name)
kb = MEM_callocN(sizeof(KeyBlock), "Keyblock");
BLI_addtail(&key->block, kb);
- kb->type = KEY_CARDINAL;
+ kb->type = KEY_LINEAR;
tot = BLI_listbase_count(&key->block);
if (name) {
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 1d5b6de22f4..2c1b36d3496 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -84,10 +84,10 @@ void BKE_lamp_init(Lamp *la)
la->cascade_count = 4;
la->cascade_exponent = 0.8f;
la->cascade_fade = 0.1f;
- la->contact_dist = 1.0f;
+ la->contact_dist = 0.2f;
la->contact_bias = 0.03f;
la->contact_spread = 0.2f;
- la->contact_thickness = 0.5f;
+ la->contact_thickness = 0.2f;
la->spec_fac = 1.0f;
curvemapping_initialize(la->curfalloff);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 78ff43c2981..04830eb1081 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -211,9 +211,9 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
/* works best if we force to linear type (endpoints match) */
lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
- if (ltOb->curve_cache) {
+ if (ltOb->runtime.curve_cache) {
/* prevent using deformed locations */
- BKE_displist_free(&ltOb->curve_cache->disp);
+ BKE_displist_free(&ltOb->runtime.curve_cache->disp);
}
copy_m4_m4(mat, ltOb->obmat);
@@ -349,7 +349,7 @@ LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
/* we make an array with all differences */
Lattice *lt = oblatt->data;
BPoint *bp;
- DispList *dl = oblatt->curve_cache ? BKE_displist_find(&oblatt->curve_cache->disp, DL_VERTS) : NULL;
+ DispList *dl = oblatt->runtime.curve_cache ? BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) : NULL;
const float *co = dl ? dl->verts : NULL;
float *fp, imat[4][4];
float fu, fv, fw;
@@ -558,7 +558,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
int cycl = 0;
/* test for cyclic */
- bl = ob->curve_cache->bev.first;
+ bl = ob->runtime.curve_cache->bev.first;
if (!bl->nr) return false;
if (bl->poly > -1) cycl = 1;
@@ -573,7 +573,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
if (cycl == 0) {
- Path *path = ob->curve_cache->path;
+ Path *path = ob->runtime.curve_cache->path;
float dvec[3];
if (ctime < 0.0f) {
@@ -610,12 +610,12 @@ static bool calc_curve_deform(Object *par, float co[3],
short index;
const bool is_neg_axis = (axis > 2);
- if (par->curve_cache == NULL) {
+ if (par->runtime.curve_cache == NULL) {
/* Happens with a cyclic dependencies. */
return false;
}
- if (par->curve_cache->path == NULL) {
+ if (par->runtime.curve_cache->path == NULL) {
return false; /* happens on append, cyclic dependencies and empty curves */
}
@@ -625,7 +625,7 @@ static bool calc_curve_deform(Object *par, float co[3],
if (cu->flag & CU_STRETCH)
fac = (-co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
else
- fac = -(co[index] - cd->dmax[index]) / (par->curve_cache->path->totdist);
+ fac = -(co[index] - cd->dmax[index]) / (par->runtime.curve_cache->path->totdist);
}
else {
index = axis;
@@ -633,8 +633,8 @@ static bool calc_curve_deform(Object *par, float co[3],
fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
}
else {
- if (LIKELY(par->curve_cache->path->totdist > FLT_EPSILON)) {
- fac = +(co[index] - cd->dmin[index]) / (par->curve_cache->path->totdist);
+ if (LIKELY(par->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
+ fac = +(co[index] - cd->dmin[index]) / (par->runtime.curve_cache->path->totdist);
}
else {
fac = 0.0f;
@@ -1035,11 +1035,11 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
int numVerts, editmode = (lt->editlatt != NULL);
const ModifierEvalContext mectx = {depsgraph, ob, 0};
- if (ob->curve_cache) {
- BKE_displist_free(&ob->curve_cache->disp);
+ if (ob->runtime.curve_cache) {
+ BKE_displist_free(&ob->runtime.curve_cache->disp);
}
else {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
}
for (; md; md = md->next) {
@@ -1071,7 +1071,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
dl->nr = numVerts;
dl->verts = (float *) vertexCos;
- BLI_addtail(&ob->curve_cache->disp, dl);
+ BLI_addtail(&ob->runtime.curve_cache->disp, dl);
}
}
@@ -1145,7 +1145,7 @@ BoundBox *BKE_lattice_boundbox_get(Object *ob)
void BKE_lattice_minmax_dl(Object *ob, Lattice *lt, float min[3], float max[3])
{
- DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
+ DispList *dl = ob->runtime.curve_cache ? BKE_displist_find(&ob->runtime.curve_cache->disp, DL_VERTS) : NULL;
if (!dl) {
BKE_lattice_minmax(lt, min, max);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 2f5c8e7817e..1396ad1f97c 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -715,6 +715,14 @@ static int layer_collection_sync(
lc->runtime_flag |= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS;
}
+ /* Holdout and indirect only */
+ if (lc->flag & LAYER_COLLECTION_HOLDOUT) {
+ base->flag |= BASE_HOLDOUT;
+ }
+ if (lc->flag & LAYER_COLLECTION_INDIRECT_ONLY) {
+ base->flag |= BASE_INDIRECT_ONLY;
+ }
+
lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
}
@@ -750,7 +758,13 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
/* Clear visible and selectable flags to be reset. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->flag &= ~(BASE_VISIBLE | BASE_ENABLED | BASE_SELECTABLE | BASE_ENABLED_VIEWPORT | BASE_ENABLED_RENDER);
+ base->flag &= ~(BASE_VISIBLE |
+ BASE_ENABLED |
+ BASE_SELECTABLE |
+ BASE_ENABLED_VIEWPORT |
+ BASE_ENABLED_RENDER |
+ BASE_HOLDOUT |
+ BASE_INDIRECT_ONLY);
}
view_layer->runtime_flag = 0;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index fd87c913573..07bd97b379b 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -633,7 +633,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
BKE_particlesettings_copy_data(bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag);
break;
case ID_GD:
- BKE_gpencil_copy_data(bmain, (bGPdata *)*r_newid, (bGPdata *)id, flag);
+ BKE_gpencil_copy_data((bGPdata *)*r_newid, (bGPdata *)id, flag);
break;
case ID_MC:
BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag);
@@ -1075,6 +1075,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_IP] = &(main->ipo);
lb[INDEX_ID_AC] = &(main->action); /* moved here to avoid problems when freeing with animato (aligorith) */
lb[INDEX_ID_KE] = &(main->key);
+ lb[INDEX_ID_PAL] = &(main->palettes); /* referenced by gpencil, so needs to be before that to avoid crashes */
lb[INDEX_ID_GD] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */
lb[INDEX_ID_NT] = &(main->nodetree);
lb[INDEX_ID_IM] = &(main->image);
@@ -1408,13 +1409,13 @@ void *BKE_id_new_nomain(const short type, const char *name)
/* by spec, animdata is first item after ID */
/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
-static void id_copy_animdata(Main *bmain, ID *id, const bool do_action)
+static void id_copy_animdata(Main *bmain, ID *id, const bool do_action, const bool do_id_user)
{
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
- iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action, true); /* could be set to false, need to investigate */
+ iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action, do_id_user);
}
}
@@ -1471,7 +1472,9 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
/* the duplicate should get a copy of the animdata */
if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
BLI_assert((flag & LIB_ID_COPY_ACTIONS) == 0 || (flag & LIB_ID_CREATE_NO_MAIN) == 0);
- id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0);
+ id_copy_animdata(bmain, new_id,
+ (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0,
+ (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0);
}
else if (id_can_have_animdata(new_id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)new_id;
@@ -2466,7 +2469,7 @@ void BKE_library_make_local(
* Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && ob->pose->flag & POSE_RECALC) {
- BKE_pose_rebuild(ob, ob->data);
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
}
}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 93fdd3349bf..0626e051e83 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -417,7 +417,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
SEQ_END
}
- CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
for (CollectionObject *cob = scene->master_collection->gobject.first; cob; cob = cob->next) {
CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
@@ -478,6 +477,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
if (toolsett->uvsculpt) {
library_foreach_paint(&data, &toolsett->uvsculpt->paint);
}
+ if (toolsett->gp_paint) {
+ library_foreach_paint(&data, &toolsett->gp_paint->paint);
+ }
}
if (scene->rigidbody_world) {
@@ -641,6 +643,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
if (material->texpaintslot != NULL) {
CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP);
}
+ if (material->gp_style != NULL) {
+ CALLBACK_INVOKE(material->gp_style->sima, IDWALK_CB_USER);
+ CALLBACK_INVOKE(material->gp_style->ima, IDWALK_CB_USER);
+ }
break;
}
@@ -676,6 +682,15 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
{
Camera *camera = (Camera *) id;
CALLBACK_INVOKE(camera->dof_ob, IDWALK_CB_NOP);
+ for (CameraBGImage *bgpic = camera->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ CALLBACK_INVOKE(bgpic->ima, IDWALK_CB_USER);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ CALLBACK_INVOKE(bgpic->clip, IDWALK_CB_USER);
+ }
+ }
+
break;
}
@@ -758,6 +773,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(brush->toggle_brush, IDWALK_CB_NOP);
CALLBACK_INVOKE(brush->clone.image, IDWALK_CB_NOP);
CALLBACK_INVOKE(brush->paint_curve, IDWALK_CB_USER);
+ if (brush->gpencil_settings) {
+ CALLBACK_INVOKE(brush->gpencil_settings->material, IDWALK_CB_USER);
+ }
library_foreach_mtex(&data, &brush->mtex);
library_foreach_mtex(&data, &brush->mask_mtex);
break;
@@ -941,10 +959,15 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_GD:
{
bGPdata *gpencil = (bGPdata *) id;
+ /* materials */
+ for (i = 0; i < gpencil->totcol; i++) {
+ CALLBACK_INVOKE(gpencil->mat[i], IDWALK_CB_USER);
+ }
- for (bGPDlayer *gp_layer = gpencil->layers.first; gp_layer; gp_layer = gp_layer->next) {
- CALLBACK_INVOKE(gp_layer->parent, IDWALK_CB_NOP);
+ for (bGPDlayer *gplayer = gpencil->layers.first; gplayer != NULL; gplayer = gplayer->next) {
+ CALLBACK_INVOKE(gplayer->parent, IDWALK_CB_NOP);
}
+
break;
}
@@ -1072,7 +1095,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
return true;
#endif
case ID_BR:
- return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE);
+ return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE, ID_MA);
case ID_PA:
return ELEM(id_type_used, ID_OB, ID_GR, ID_TE);
case ID_MC:
@@ -1083,6 +1106,8 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
return (ELEM(id_type_used, ID_TE, ID_OB));
case ID_LP:
return ELEM(id_type_used, ID_IM);
+ case ID_GD:
+ return ELEM(id_type_used, ID_MA);
case ID_WS:
return ELEM(id_type_used, ID_SCR, ID_SCE);
case ID_IM:
@@ -1091,7 +1116,6 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
case ID_SO:
case ID_AR:
case ID_AC:
- case ID_GD:
case ID_WM:
case ID_PAL:
case ID_PC:
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index 057b6aaaf65..baf0cdbe62f 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -53,7 +53,6 @@ void BKE_lightprobe_init(LightProbe *probe)
probe->vis_bias = 1.0f;
probe->vis_blur = 0.2f;
probe->intensity = 1.0f;
- probe->data_draw_size = 1.0f;
probe->flag = LIGHTPROBE_FLAG_SHOW_INFLUENCE | LIGHTPROBE_FLAG_SHOW_DATA;
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index ab8c8695495..5edf9b9048f 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -43,6 +43,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_customdata_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_ID.h"
#include "DNA_meta_types.h"
#include "DNA_node_types.h"
@@ -58,6 +59,7 @@
#include "BKE_animsys.h"
#include "BKE_displist.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -103,10 +105,30 @@ void BKE_material_free(Material *ma)
MEM_SAFE_FREE(ma->texpaintslot);
+ MEM_SAFE_FREE(ma->gp_style);
+
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
}
+void BKE_material_init_gpencil_settings(Material *ma)
+{
+ if ((ma) && (ma->gp_style == NULL)) {
+ ma->gp_style = MEM_callocN(sizeof(MaterialGPencilStyle), "Grease Pencil Material Settings");
+
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ /* set basic settings */
+ gp_style->stroke_rgba[3] = 1.0f;
+ gp_style->pattern_gridsize = 0.1f;
+ gp_style->gradient_radius = 0.5f;
+ ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
+ ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
+ ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
+ gp_style->texture_opacity = 1.0f;
+ gp_style->texture_pixsize = 100.0f;
+ }
+}
+
void BKE_material_init(Material *ma)
{
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id));
@@ -124,6 +146,7 @@ void BKE_material_init(Material *ma)
ma->preview = NULL;
ma->alpha_threshold = 0.5f;
+
}
Material *BKE_material_add(Main *bmain, const char *name)
@@ -137,6 +160,19 @@ Material *BKE_material_add(Main *bmain, const char *name)
return ma;
}
+Material *BKE_material_add_gpencil(Main *bmain, const char *name)
+{
+ Material *ma;
+
+ ma = BKE_material_add(bmain, name);
+
+ /* grease pencil settings */
+ BKE_material_init_gpencil_settings(ma);
+
+ return ma;
+}
+
+
/**
* Only copy internal data of Material ID from source to already allocated/initialized destination.
* You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
@@ -164,6 +200,10 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
ma_dst->texpaintslot = MEM_dupallocN(ma_src->texpaintslot);
}
+ if (ma_src->gp_style != NULL) {
+ ma_dst->gp_style = MEM_dupallocN(ma_src->gp_style);
+ }
+
BLI_listbase_clear(&ma_dst->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
@@ -199,6 +239,7 @@ Material *BKE_material_localize(Material *ma)
man->texpaintslot = NULL;
man->preview = NULL;
+ /* man->gp_style = NULL; */ /* XXX: We probably don't want to clear here, or else we may get problems with COW later? */
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
@@ -218,6 +259,7 @@ Material ***give_matarar(Object *ob)
Mesh *me;
Curve *cu;
MetaBall *mb;
+ bGPdata *gpd;
if (ob->type == OB_MESH) {
me = ob->data;
@@ -231,6 +273,10 @@ Material ***give_matarar(Object *ob)
mb = ob->data;
return &(mb->mat);
}
+ else if (ob->type == OB_GPENCIL) {
+ gpd = ob->data;
+ return &(gpd->mat);
+ }
return NULL;
}
@@ -239,6 +285,7 @@ short *give_totcolp(Object *ob)
Mesh *me;
Curve *cu;
MetaBall *mb;
+ bGPdata *gpd;
if (ob->type == OB_MESH) {
me = ob->data;
@@ -252,6 +299,10 @@ short *give_totcolp(Object *ob)
mb = ob->data;
return &(mb->totcol);
}
+ else if (ob->type == OB_GPENCIL) {
+ gpd = ob->data;
+ return &(gpd->totcol);
+ }
return NULL;
}
@@ -268,6 +319,8 @@ Material ***give_matarar_id(ID *id)
return &(((Curve *)id)->mat);
case ID_MB:
return &(((MetaBall *)id)->mat);
+ case ID_GD:
+ return &(((bGPdata *)id)->mat);
default:
break;
}
@@ -286,6 +339,8 @@ short *give_totcolp_id(ID *id)
return &(((Curve *)id)->totcol);
case ID_MB:
return &(((MetaBall *)id)->totcol);
+ case ID_GD:
+ return &(((bGPdata *)id)->totcol);
default:
break;
}
@@ -307,6 +362,9 @@ static void material_data_index_remove_id(ID *id, short index)
case ID_MB:
/* meta-elems don't have materials atm */
break;
+ case ID_GD:
+ BKE_gpencil_material_index_remove((bGPdata *)id, index);
+ break;
default:
break;
}
@@ -487,6 +545,21 @@ Material *give_current_material(Object *ob, short act)
return ma;
}
+MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act)
+{
+ Material *ma = give_current_material(ob, act);
+ if (ma != NULL) {
+ if (ma->gp_style == NULL) {
+ BKE_material_init_gpencil_settings(ma);
+ }
+
+ return ma->gp_style;
+ }
+ else {
+ return NULL;
+ }
+}
+
Material *give_node_material(Material *ma)
{
if (ma && ma->use_nodes && ma->nodetree) {
@@ -727,6 +800,9 @@ void BKE_material_remap_object(Object *ob, const unsigned int *remap)
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_curve_material_remap(ob->data, remap, ob->totcol);
}
+ if (ob->type == OB_GPENCIL) {
+ BKE_gpencil_material_remap(ob->data, remap, ob->totcol);
+ }
else {
/* add support for this object data! */
BLI_assert(matar == NULL);
@@ -924,10 +1000,10 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
}
/* check indices from mesh */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
material_data_index_remove_id((ID *)ob->data, actcol - 1);
- if (ob->curve_cache) {
- BKE_displist_free(&ob->curve_cache->disp);
+ if (ob->runtime.curve_cache) {
+ BKE_displist_free(&ob->runtime.curve_cache->disp);
}
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 2ff69c5ee6d..43b7eba2810 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -207,7 +207,7 @@ void BKE_mball_texspace_calc(Object *ob)
(min)[0] = (min)[1] = (min)[2] = 1.0e30f;
(max)[0] = (max)[1] = (max)[2] = -1.0e30f;
- dl = ob->curve_cache->disp.first;
+ dl = ob->runtime.curve_cache->disp.first;
while (dl) {
tot = dl->nr;
if (tot) do_it = true;
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 738f116310b..2e2afa6834b 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -217,8 +217,8 @@ int BKE_mesh_nurbs_to_mdata(
{
ListBase disp = {NULL, NULL};
- if (ob->curve_cache) {
- disp = ob->curve_cache->disp;
+ if (ob->runtime.curve_cache) {
+ disp = ob->runtime.curve_cache->disp;
}
return BKE_mesh_nurbs_displist_to_mdata(
@@ -537,8 +537,8 @@ Mesh *BKE_mesh_new_nomain_from_curve(Object *ob)
{
ListBase disp = {NULL, NULL};
- if (ob->curve_cache) {
- disp = ob->curve_cache->disp;
+ if (ob->runtime.curve_cache) {
+ disp = ob->runtime.curve_cache->disp;
}
return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
@@ -650,8 +650,8 @@ void BKE_mesh_from_nurbs(Main *bmain, Object *ob)
bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
ListBase disp = {NULL, NULL};
- if (ob->curve_cache) {
- disp = ob->curve_cache->disp;
+ if (ob->runtime.curve_cache) {
+ disp = ob->runtime.curve_cache->disp;
}
BKE_mesh_from_nurbs_displist(bmain, ob, &disp, use_orco_uv, cu->id.name, false);
@@ -871,11 +871,11 @@ Mesh *BKE_mesh_new_from_object(
*
* TODO(sergey): Look into more proper solution.
*/
- if (ob->curve_cache != NULL) {
- if (tmpobj->curve_cache == NULL) {
- tmpobj->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+ if (ob->runtime.curve_cache != NULL) {
+ if (tmpobj->runtime.curve_cache == NULL) {
+ tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
}
- BKE_displist_copy(&tmpobj->curve_cache->disp, &ob->curve_cache->disp);
+ BKE_displist_copy(&tmpobj->runtime.curve_cache->disp, &ob->runtime.curve_cache->disp);
}
/* if getting the original caged mesh, delete object modifiers */
@@ -953,8 +953,8 @@ Mesh *BKE_mesh_new_from_object(
}
else {
ListBase disp = {NULL, NULL};
- if (ob->curve_cache) {
- disp = ob->curve_cache->disp;
+ if (ob->runtime.curve_cache) {
+ disp = ob->runtime.curve_cache->disp;
}
BKE_mesh_from_metaball(&disp, tmpmesh);
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index ac935bb7f81..66419b03e01 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -480,6 +480,8 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoo
mem = lnors_spacearr->mem;
lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
+
+ lnors_spacearr->num_spaces = 0;
}
BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
lnors_spacearr->data_type = data_type;
@@ -487,21 +489,24 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoo
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
{
- BLI_memarena_clear(lnors_spacearr->mem);
+ lnors_spacearr->num_spaces = 0;
lnors_spacearr->lspacearr = NULL;
lnors_spacearr->loops_pool = NULL;
+ BLI_memarena_clear(lnors_spacearr->mem);
}
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
{
- BLI_memarena_free(lnors_spacearr->mem);
+ lnors_spacearr->num_spaces = 0;
lnors_spacearr->lspacearr = NULL;
lnors_spacearr->loops_pool = NULL;
+ BLI_memarena_free(lnors_spacearr->mem);
lnors_spacearr->mem = NULL;
}
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
{
+ lnors_spacearr->num_spaces++;
return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
}
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 699d6bce2b0..5c9849f6b74 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -55,13 +55,13 @@
* but for now this replaces it because its unused. */
UvVertMap *BKE_mesh_uv_vert_map_create(
- struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
+ const MPoly *mpoly, const MLoop *mloop, const MLoopUV *mloopuv,
unsigned int totpoly, unsigned int totvert,
const float limit[2], const bool selected, const bool use_winding)
{
UvVertMap *vmap;
UvMapVert *buf;
- MPoly *mp;
+ const MPoly *mp;
unsigned int a;
int i, totuv, nverts;
@@ -103,8 +103,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
nverts = mp->totloop;
for (i = 0; i < nverts; i++) {
- buf->tfindex = (unsigned char)i;
- buf->f = a;
+ buf->loop_of_poly_index = (unsigned short)i;
+ buf->poly_index = a;
buf->separate = 0;
buf->next = vmap->vert[mloop[mp->loopstart + i].v];
vmap->vert[mloop[mp->loopstart + i].v] = buf;
@@ -126,7 +126,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
for (a = 0; a < totvert; a++) {
UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
UvMapVert *iterv, *v, *lastv, *next;
- float *uv, *uv2, uvdiff[2];
+ const float *uv, *uv2;
+ float uvdiff[2];
while (vlist) {
v = vlist;
@@ -134,19 +135,19 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
v->next = newvlist;
newvlist = v;
- uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv;
+ uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index].uv;
lastv = NULL;
iterv = vlist;
while (iterv) {
next = iterv->next;
- uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv;
+ uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index].uv;
sub_v2_v2v2(uvdiff, uv2, uv);
if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
- (!use_winding || winding[iterv->f] == winding[v->f]))
+ (!use_winding || winding[iterv->poly_index] == winding[v->poly_index]))
{
if (lastv) lastv->next = next;
else vlist = next;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 7aa0ecdad87..c81f5f425d8 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3432,6 +3432,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_doubleedgemask();
register_node_type_cmp_keyingscreen();
register_node_type_cmp_keying();
+ register_node_type_cmp_cryptomatte();
register_node_type_cmp_translate();
register_node_type_cmp_rotate();
@@ -3520,6 +3521,7 @@ static void registerShaderNodes(void)
register_node_type_sh_bsdf_velvet();
register_node_type_sh_bsdf_toon();
register_node_type_sh_bsdf_hair();
+ register_node_type_sh_bsdf_hair_principled();
register_node_type_sh_emission();
register_node_type_sh_holdout();
register_node_type_sh_volume_absorption();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 14794bd7061..41c23c46c44 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -41,6 +41,7 @@
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
@@ -53,6 +54,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_shader_fx_types.h"
#include "DNA_smoke_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
@@ -86,6 +88,7 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
@@ -110,12 +113,14 @@
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
+#include "BKE_shader_fx.h"
#include "BKE_speaker.h"
#include "BKE_softbody.h"
#include "BKE_subsurf.h"
#include "BKE_material.h"
#include "BKE_camera.h"
#include "BKE_image.h"
+#include "BKE_gpencil.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -170,26 +175,30 @@ void BKE_object_free_softbody(Object *ob)
void BKE_object_free_curve_cache(Object *ob)
{
- if (ob->curve_cache) {
- BKE_displist_free(&ob->curve_cache->disp);
- BKE_curve_bevelList_free(&ob->curve_cache->bev);
- if (ob->curve_cache->path) {
- free_path(ob->curve_cache->path);
+ if (ob->runtime.curve_cache) {
+ BKE_displist_free(&ob->runtime.curve_cache->disp);
+ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
+ if (ob->runtime.curve_cache->path) {
+ free_path(ob->runtime.curve_cache->path);
}
- BKE_nurbList_free(&ob->curve_cache->deformed_nurbs);
- MEM_freeN(ob->curve_cache);
- ob->curve_cache = NULL;
+ BKE_nurbList_free(&ob->runtime.curve_cache->deformed_nurbs);
+ MEM_freeN(ob->runtime.curve_cache);
+ ob->runtime.curve_cache = NULL;
}
}
void BKE_object_free_modifiers(Object *ob, const int flag)
{
ModifierData *md;
+ GpencilModifierData *gp_md;
while ((md = BLI_pophead(&ob->modifiers))) {
modifier_free_ex(md, flag);
}
+ while ((gp_md = BLI_pophead(&ob->greasepencil_modifiers))) {
+ BKE_gpencil_modifier_free_ex(gp_md, flag);
+ }
/* particle modifiers were freed, so free the particlesystems as well */
BKE_object_free_particlesystems(ob);
@@ -200,6 +209,15 @@ void BKE_object_free_modifiers(Object *ob, const int flag)
BKE_object_free_derived_caches(ob);
}
+void BKE_object_free_shaderfx(Object *ob, const int flag)
+{
+ ShaderFxData *fx;
+
+ while ((fx = BLI_pophead(&ob->shader_fx))) {
+ BKE_shaderfx_free_ex(fx, flag);
+ }
+}
+
void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
{
/* reset functionality */
@@ -222,6 +240,29 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
}
}
+void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData *hmd)
+{
+ if (hmd->object == NULL) {
+ return;
+ }
+ /* reset functionality */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
+
+ if (hmd->subtarget[0] && pchan) {
+ float imat[4][4], mat[4][4];
+
+ /* calculate the world-space matrix for the pose-channel target first, then carry on as usual */
+ mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
+
+ invert_m4_m4(imat, mat);
+ mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
+ }
+ else {
+ invert_m4_m4(hmd->object->imat, hmd->object->obmat);
+ mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
+ }
+}
+
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
{
const ModifierTypeInfo *mti;
@@ -428,6 +469,7 @@ void BKE_object_free(Object *ob)
/* BKE_<id>_free shall never touch to ID->us. Never ever. */
BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
+ BKE_object_free_shaderfx(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
MEM_SAFE_FREE(ob->mat);
MEM_SAFE_FREE(ob->matbits);
@@ -460,12 +502,12 @@ void BKE_object_free(Object *ob)
BLI_freelistN(&ob->lodlevels);
/* Free runtime curves data. */
- if (ob->curve_cache) {
- BKE_curve_bevelList_free(&ob->curve_cache->bev);
- if (ob->curve_cache->path)
- free_path(ob->curve_cache->path);
- MEM_freeN(ob->curve_cache);
- ob->curve_cache = NULL;
+ if (ob->runtime.curve_cache) {
+ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
+ if (ob->runtime.curve_cache->path)
+ free_path(ob->runtime.curve_cache->path);
+ MEM_freeN(ob->runtime.curve_cache);
+ ob->runtime.curve_cache = NULL;
}
BKE_previewimg_free(&ob->preview);
@@ -653,6 +695,7 @@ static const char *get_obdata_defname(int type)
case OB_ARMATURE: return DATA_("Armature");
case OB_SPEAKER: return DATA_("Speaker");
case OB_EMPTY: return DATA_("Empty");
+ case OB_GPENCIL: return DATA_("GPencil");
default:
printf("get_obdata_defname: Internal error, bad type: %d\n", type);
return DATA_("Empty");
@@ -677,6 +720,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
case OB_ARMATURE: return BKE_armature_add(bmain, name);
case OB_SPEAKER: return BKE_speaker_add(bmain, name);
case OB_LIGHTPROBE:return BKE_lightprobe_add(bmain, name);
+ case OB_GPENCIL: return BKE_gpencil_data_addnew(bmain, name);
case OB_EMPTY: return NULL;
default:
printf("%s: Internal error, bad type: %d\n", __func__, type);
@@ -810,7 +854,7 @@ Object *BKE_object_add(
/**
* Add a new object, using another one as a reference
*
- * /param ob_src object to use to determine the collections of the new object.
+ * \param ob_src object to use to determine the collections of the new object.
*/
Object *BKE_object_add_from(
Main *bmain, Scene *scene, ViewLayer *view_layer,
@@ -828,6 +872,41 @@ Object *BKE_object_add_from(
return ob;
}
+/**
+ * Add a new object, but assign the given datablock as the ob->data
+ * for the newly created object.
+ *
+ * \param data The datablock to assign as ob->data for the new object.
+ * This is assumed to be of the correct type.
+ * \param do_id_user If true, id_us_plus() will be called on data when
+ * assigning it to the object.
+ */
+Object *BKE_object_add_for_data(
+ Main *bmain, ViewLayer *view_layer,
+ int type, const char *name, ID *data, bool do_id_user)
+{
+ Object *ob;
+ Base *base;
+ LayerCollection *layer_collection;
+
+ /* same as object_add_common, except we don't create new ob->data */
+ ob = BKE_object_add_only_object(bmain, type, name);
+ ob->data = data;
+ if (do_id_user) id_us_plus(data);
+
+ BKE_view_layer_base_deselect_all(view_layer);
+ DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, ob);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
+
+ return ob;
+}
+
+
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src, const int flag)
{
SoftBody *sb = ob_src->soft;
@@ -1150,9 +1229,14 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
*
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_src, const int flag)
+void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
{
ModifierData *md;
+ GpencilModifierData *gmd;
+ ShaderFxData *fx;
+
+ /* Do not copy runtime data. */
+ BKE_object_runtime_reset(ob_dst);
/* We never handle usercount here for own data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
@@ -1176,11 +1260,31 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
BLI_addtail(&ob_dst->modifiers, nmd);
}
+ BLI_listbase_clear(&ob_dst->greasepencil_modifiers);
+
+ for (gmd = ob_src->greasepencil_modifiers.first; gmd; gmd = gmd->next) {
+ GpencilModifierData *nmd = BKE_gpencil_modifier_new(gmd->type);
+ BLI_strncpy(nmd->name, gmd->name, sizeof(nmd->name));
+ BKE_gpencil_modifier_copyData_ex(gmd, nmd, flag_subdata);
+ BLI_addtail(&ob_dst->greasepencil_modifiers, nmd);
+ }
+
+ BLI_listbase_clear(&ob_dst->shader_fx);
+
+ for (fx = ob_src->shader_fx.first; fx; fx = fx->next) {
+ ShaderFxData *nfx = BKE_shaderfx_new(fx->type);
+ BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name));
+ BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata);
+ BLI_addtail(&ob_dst->shader_fx, nfx);
+ }
+
if (ob_src->pose) {
copy_object_pose(ob_dst, ob_src, flag_subdata);
/* backwards compat... non-armatures can get poses in older files? */
- if (ob_src->type == OB_ARMATURE)
- BKE_pose_rebuild(ob_dst, ob_dst->data);
+ if (ob_src->type == OB_ARMATURE) {
+ const bool do_pose_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0;
+ BKE_pose_rebuild(bmain, ob_dst, ob_dst->data, do_pose_id_user);
+ }
}
defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
@@ -1204,18 +1308,18 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
ob_dst->derivedDeform = NULL;
ob_dst->derivedFinal = NULL;
- BLI_listbase_clear(&ob_dst->gpulamp);
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
+ /* grease pencil: clean derived data */
+ if (ob_dst->type == OB_GPENCIL)
+ BKE_gpencil_free_derived_frames(ob_dst->data);
+
ob_dst->avs = ob_src->avs;
ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
copy_object_lod(ob_dst, ob_src, flag_subdata);
- /* Do not copy runtime curve data. */
- ob_dst->curve_cache = NULL;
-
/* Do not copy object's preview (mostly due to the fact renderers create temp copy of objects). */
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id);
@@ -1359,7 +1463,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* local_object->proxy == pointer to library object, saved in files and read */
/* local_object->proxy_group == pointer to collection dupli-object, saved in files and read */
-void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
+void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
{
/* paranoia checks */
if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
@@ -1434,7 +1538,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
if (target->type == OB_ARMATURE) {
copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */
BKE_pose_rest(ob->pose); /* clear all transforms in channels */
- BKE_pose_rebuild(ob, ob->data); /* set all internal links */
+ BKE_pose_rebuild(bmain, ob, ob->data, true); /* set all internal links */
armature_set_id_extern(ob);
}
@@ -1470,6 +1574,11 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
ob->empty_drawsize *= size;
break;
}
+ case OB_GPENCIL:
+ {
+ ob->empty_drawsize *= size;
+ break;
+ }
case OB_FONT:
{
Curve *cu = ob->data;
@@ -1726,7 +1835,7 @@ static bool ob_parcurve(Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob,
}
#endif
- if (par->curve_cache->path == NULL) {
+ if (par->runtime.curve_cache->path == NULL) {
return false;
}
@@ -1945,10 +2054,10 @@ static void give_parvert(Object *par, int nr, float vec[3])
ListBase *nurb;
/* Unless there's some weird depsgraph failure the cache should exist. */
- BLI_assert(par->curve_cache != NULL);
+ BLI_assert(par->runtime.curve_cache != NULL);
- if (par->curve_cache->deformed_nurbs.first != NULL) {
- nurb = &par->curve_cache->deformed_nurbs;
+ if (par->runtime.curve_cache->deformed_nurbs.first != NULL) {
+ nurb = &par->runtime.curve_cache->deformed_nurbs;
}
else {
Curve *cu = par->data;
@@ -1959,7 +2068,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
else if (par->type == OB_LATTICE) {
Lattice *latt = par->data;
- DispList *dl = par->curve_cache ? BKE_displist_find(&par->curve_cache->disp, DL_VERTS) : NULL;
+ DispList *dl = par->runtime.curve_cache ? BKE_displist_find(&par->runtime.curve_cache->disp, DL_VERTS) : NULL;
float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
int tot;
@@ -2453,7 +2562,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
float size[3];
copy_v3_v3(size, ob->size);
- if (ob->type == OB_EMPTY) {
+ if ((ob->type == OB_EMPTY) || (ob->type == OB_GPENCIL)) {
mul_v3_fl(size, ob->empty_drawsize);
}
@@ -2540,10 +2649,10 @@ void BKE_object_foreach_display_point(
func_cb(co, user_data);
}
}
- else if (ob->curve_cache && ob->curve_cache->disp.first) {
+ else if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
DispList *dl;
- for (dl = ob->curve_cache->disp.first; dl; dl = dl->next) {
+ for (dl = ob->runtime.curve_cache->disp.first; dl; dl = dl->next) {
const float *v3 = dl->verts;
int totvert = dl->nr;
int i;
@@ -2698,8 +2807,10 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
* with poses we do it ahead of BKE_object_where_is_calc to ensure animation
* is evaluated on the rebuilt pose, otherwise we get incorrect poses
* on file load */
- if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC))
- BKE_pose_rebuild(ob, ob->data);
+ if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
+ /* No need to pass bmain here, we assume we do not need to rebuild DEG from here... */
+ BKE_pose_rebuild(NULL, ob, ob->data, true);
+ }
}
}
/* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers,
@@ -3693,6 +3804,74 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md)
return false;
}
+bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md)
+{
+ if (BKE_gpencil_modifier_dependsOnTime(md)) {
+ return true;
+ }
+
+ /* Check whether modifier is animated. */
+ /* TODO (Aligorith): this should be handled as part of build_animdata() */
+ if (ob->adt) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+
+ char pattern[MAX_NAME + 32];
+ BLI_snprintf(pattern, sizeof(pattern), "grease_pencil_modifiers[\"%s\"]", md->name);
+
+ /* action - check for F-Curves with paths containing 'grease_pencil_modifiers[' */
+ if (adt->action) {
+ for (fcu = adt->action->curves.first; fcu != NULL; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern)) {
+ return true;
+ }
+ }
+ }
+
+ /* This here allows modifier properties to get driven and still update properly */
+ for (fcu = adt->drivers.first; fcu != NULL; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool BKE_object_shaderfx_use_time(Object *ob, ShaderFxData *fx)
+{
+ if (BKE_shaderfx_dependsOnTime(fx)) {
+ return true;
+ }
+
+ /* Check whether effect is animated. */
+ /* TODO (Aligorith): this should be handled as part of build_animdata() */
+ if (ob->adt) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+
+ char pattern[MAX_NAME + 32];
+ BLI_snprintf(pattern, sizeof(pattern), "shader_effects[\"%s\"]", fx->name);
+
+ /* action - check for F-Curves with paths containing string[' */
+ if (adt->action) {
+ for (fcu = adt->action->curves.first; fcu != NULL; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern))
+ return true;
+ }
+ }
+
+ /* This here allows properties to get driven and still update properly */
+ for (fcu = adt->drivers.first; fcu != NULL; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, pattern))
+ return true;
+ }
+ }
+
+ return false;
+}
+
/* set "ignore cache" flag for all caches on this object */
static void object_cacheIgnoreClear(Object *ob, int state)
{
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 5c9e53aaa56..a6b0e57e55c 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -53,6 +53,7 @@
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
+#include "BKE_gpencil.h"
/** \name Misc helpers
* \{ */
@@ -402,12 +403,17 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
*/
void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
{
- if (BKE_object_is_in_editmode_vgroup(ob))
- object_defgroup_remove_edit_mode(ob, defgroup);
- else
- object_defgroup_remove_object_mode(ob, defgroup);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ BKE_gpencil_vgroup_remove(ob, defgroup);
+ }
+ else {
+ if (BKE_object_is_in_editmode_vgroup(ob))
+ object_defgroup_remove_edit_mode(ob, defgroup);
+ else
+ object_defgroup_remove_object_mode(ob, defgroup);
- BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ }
}
/**
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 3e72de3909f..3641df26496 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -62,6 +62,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
+#include "BKE_gpencil.h"
#include "MEM_guardedalloc.h"
@@ -324,6 +325,9 @@ void BKE_object_eval_uber_data(Depsgraph *depsgraph,
case OB_MBALL:
BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
break;
+ case OB_GPENCIL:
+ BKE_gpencil_batch_cache_dirty(ob->data);
+ break;
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 07aa21f44ff..cb26f7e9f3e 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -41,13 +41,19 @@
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_space_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_workspace_types.h"
#include "BLI_bitmap.h"
+#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
#include "BLI_math_vector.h"
#include "BLI_listbase.h"
+#include "BLT_translation.h"
+
+#include "BKE_animsys.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_deform.h"
@@ -55,6 +61,7 @@
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_library.h"
@@ -151,6 +158,8 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
return &ts->imapaint.paint;
case ePaintSculptUV:
return &ts->uvsculpt->paint;
+ case ePaintGpencil:
+ return &ts->gp_paint->paint;
case ePaintInvalid:
return NULL;
default:
@@ -176,6 +185,8 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
return &ts->wpaint->paint;
case OB_MODE_TEXTURE_PAINT:
return &ts->imapaint.paint;
+ case OB_MODE_GPENCIL_PAINT:
+ return &ts->gp_paint->paint;
case OB_MODE_EDIT:
if (ts->use_uv_sculpt)
return &ts->uvsculpt->paint;
@@ -430,13 +441,11 @@ PaletteColor *BKE_palette_color_add(Palette *palette)
return color;
}
-
bool BKE_palette_is_empty(const struct Palette *palette)
{
return BLI_listbase_is_empty(&palette->colors);
}
-
/* are we in vertex paint or weight pain face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 35c8761f671..cee1c9147b5 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2941,7 +2941,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
skip = 1; /* only hair, keyed and baked stuff can have paths */
else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
skip = 1; /* particle visualization must be set as path */
- else {
+ else if (DEG_get_mode(sim->depsgraph) != DAG_EVAL_RENDER) {
if (part->draw_as != PART_DRAW_REND)
skip = 1; /* draw visualization */
else if (psys->pointcache->flag & PTCACHE_BAKING)
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 0a4cd3ec3c1..3e7a9b7ce24 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -2077,7 +2077,7 @@ static void pbvh_node_check_mask_changed(PBVH *bvh, PBVHNode *node)
struct PBVHNodeDrawCallbackData {
- void (*draw_fn)(void *user_data, Gwn_Batch *batch);
+ void (*draw_fn)(void *user_data, GPUBatch *batch);
void *user_data;
bool fast;
};
@@ -2087,7 +2087,7 @@ static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
struct PBVHNodeDrawCallbackData *data = data_v;
if (!(node->flag & PBVH_FullyHidden)) {
- Gwn_Batch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast);
+ GPUBatch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast);
if (triangles != NULL) {
data->draw_fn(data->user_data, triangles);
}
@@ -2099,7 +2099,7 @@ static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
*/
void BKE_pbvh_draw_cb(
PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
- void (*draw_fn)(void *user_data, Gwn_Batch *batch), void *user_data)
+ void (*draw_fn)(void *user_data, GPUBatch *batch), void *user_data)
{
struct PBVHNodeDrawCallbackData draw_data = {
.fast = fast,
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 59847b28785..c542c3f927d 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -716,6 +716,35 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* --------------------- */
+static void rigidbody_constraint_init_spring(
+ RigidBodyCon *rbc, void (*set_spring)(rbConstraint *, int, int),
+ void (*set_stiffness)(rbConstraint *, int, float), void (*set_damping)(rbConstraint *, int, float))
+{
+ set_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
+ set_damping(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
+
+ set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
+ set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
+
+ set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
+ set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
+
+ set_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x);
+ set_damping(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x);
+
+ set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y);
+ set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y);
+
+ set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z);
+ set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z);
+ set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
+}
+
static void rigidbody_constraint_set_limits(
RigidBodyCon *rbc, void (*set_limits)(rbConstraint *, int, float, float))
{
@@ -841,35 +870,24 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper);
break;
case RBC_TYPE_6DOF_SPRING:
- rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
-
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
+ if (rbc->spring_type == RBC_SPRING_TYPE2) {
+ rbc->physics_constraint = RB_constraint_new_6dof_spring2(loc, rot, rb1, rb2);
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
+ rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring2, RB_constraint_set_stiffness_6dof_spring2, RB_constraint_set_damping_6dof_spring2);
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
+ RB_constraint_set_equilibrium_6dof_spring2(rbc->physics_constraint);
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x);
-
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring2);
+ }
+ else {
+ rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
- RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z);
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z);
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
+ rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring, RB_constraint_set_stiffness_6dof_spring, RB_constraint_set_damping_6dof_spring);
- RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
+ RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
- rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof);
+ }
break;
case RBC_TYPE_6DOF:
rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
@@ -1094,6 +1112,8 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty
rbc->flag |= RBC_FLAG_ENABLED;
rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
+ rbc->spring_type = RBC_SPRING_TYPE2;
+
rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
rbc->num_solver_iterations = 10; /* 10 is Bullet default */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 6a8f46badd9..8522c7f4445 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -113,7 +113,7 @@
#include "bmesh.h"
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
-const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH";
+const char *RE_engine_id_BLENDER_OPENGL = "BLENDER_OPENGL";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -173,6 +173,10 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag);
}
+ if (ts->gp_paint) {
+ ts->gp_paint = MEM_dupallocN(ts->gp_paint);
+ BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag);
+ }
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
ts->imapaint.paintcursor = NULL;
@@ -180,15 +184,10 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
ts->particle.scene = NULL;
ts->particle.object = NULL;
- /* duplicate Grease Pencil Drawing Brushes */
- BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = toolsettings->gp_brushes.first; brush; brush = brush->next) {
- bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
- BLI_addtail(&ts->gp_brushes, newbrush);
- }
-
/* duplicate Grease Pencil interpolation curve */
ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
+ /* duplicate Grease Pencil multiframe fallof */
+ ts->gp_sculpt.cur_falloff = curvemapping_copy(ts->gp_sculpt.cur_falloff);
return ts;
}
@@ -213,16 +212,20 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
BKE_paint_free(&toolsettings->uvsculpt->paint);
MEM_freeN(toolsettings->uvsculpt);
}
+ if (toolsettings->gp_paint) {
+ BKE_paint_free(&toolsettings->gp_paint->paint);
+ MEM_freeN(toolsettings->gp_paint);
+ }
BKE_paint_free(&toolsettings->imapaint.paint);
- /* free Grease Pencil Drawing Brushes */
- BKE_gpencil_free_brushes(&toolsettings->gp_brushes);
- BLI_freelistN(&toolsettings->gp_brushes);
-
/* free Grease Pencil interpolation curve */
if (toolsettings->gp_interpolate.custom_ipo) {
curvemapping_free(toolsettings->gp_interpolate.custom_ipo);
}
+ /* free Grease Pencil multiframe falloff curve */
+ if (toolsettings->gp_sculpt.cur_falloff) {
+ curvemapping_free(toolsettings->gp_sculpt.cur_falloff);
+ }
MEM_freeN(toolsettings);
}
@@ -361,6 +364,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
curvemapping_copy_data(&sce_copy->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve);
+ /* viewport display settings */
+ sce_copy->display = sce->display;
+
/* tool settings */
sce_copy->toolsettings = BKE_toolsettings_copy(sce->toolsettings, 0);
@@ -425,9 +431,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
/* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
- * are done outside of blenkernel with ED_objects_single_users! */
+ * are done outside of blenkernel with ED_object_single_users! */
- /* camera */
+ /* camera */
if (ELEM(type, SCE_COPY_LINK_DATA, SCE_COPY_FULL)) {
ID_NEW_REMAP(sce_copy->camera);
}
@@ -680,6 +686,19 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->imapaint.normal_angle = 80;
sce->toolsettings->imapaint.seam_bleed = 2;
+ /* alloc grease pencil drawing brushes */
+ sce->toolsettings->gp_paint = MEM_callocN(sizeof(GpPaint), "GpPaint");
+
+ /* grease pencil multiframe falloff curve */
+ sce->toolsettings->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ CurveMapping *gp_falloff_curve = sce->toolsettings->gp_sculpt.cur_falloff;
+ curvemapping_set_defaults(gp_falloff_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f);
+ curvemapping_initialize(gp_falloff_curve);
+ curvemap_reset(gp_falloff_curve->cm,
+ &gp_falloff_curve->clipr,
+ CURVE_PRESET_GAUSS,
+ CURVEMAP_SLOPE_POSITIVE);
+
sce->physics_settings.gravity[0] = 0.0f;
sce->physics_settings.gravity[1] = 0.0f;
sce->physics_settings.gravity[2] = -9.81f;
@@ -757,46 +776,65 @@ void BKE_scene_init(Scene *sce)
{
GP_BrushEdit_Settings *gset = &sce->toolsettings->gp_sculpt;
GP_EditBrush_Data *gp_brush;
+ float curcolor_add[3], curcolor_sub[3];
+ ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
+ ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_SMOOTH];
gp_brush->size = 25;
gp_brush->strength = 0.3f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_THICKNESS];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_STRENGTH];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_GRAB];
gp_brush->size = 50;
gp_brush->strength = 0.3f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_PUSH];
gp_brush->size = 25;
gp_brush->strength = 0.3f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_TWIST];
gp_brush->size = 50;
gp_brush->strength = 0.3f; // XXX?
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_PINCH];
gp_brush->size = 50;
gp_brush->strength = 0.5f; // XXX?
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_EDITBRUSH_TYPE_RANDOMIZE];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
- gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ gp_brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
}
/* GP Stroke Placement */
@@ -805,6 +843,10 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+ /* Annotations */
+ sce->toolsettings->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
+ sce->toolsettings->annotate_thickness = 3;
+
sce->orientation_index_custom = -1;
/* Master Collection */
@@ -820,6 +862,9 @@ void BKE_scene_init(Scene *sce)
sce->display.matcap_ssao_attenuation = 1.0f;
sce->display.matcap_ssao_samples = 16;
+ /* OpenGL Render. */
+ BKE_screen_view3d_shading_init(&sce->display.shading);
+
/* SceneEEVEE */
sce->eevee.gi_diffuse_bounces = 3;
sce->eevee.gi_cubemap_resolution = 512;
@@ -872,7 +917,6 @@ void BKE_scene_init(Scene *sce)
sce->eevee.flag =
SCE_EEVEE_VOLUMETRIC_LIGHTS |
- SCE_EEVEE_VOLUMETRIC_COLORED |
SCE_EEVEE_GTAO_BENT_NORMALS |
SCE_EEVEE_GTAO_BOUNCE |
SCE_EEVEE_TAA_REPROJECTION |
@@ -1202,6 +1246,16 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
+int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int cfra)
+{
+ const int fps = round_db_to_int(FPS * interval_in_seconds);
+ const int second_prev = cfra - mod_i(cfra, fps);
+ const int second_next = second_prev + fps;
+ const int delta_prev = cfra - second_prev;
+ const int delta_next = second_next - cfra;
+ return (delta_prev < delta_next) ? second_prev : second_next;
+}
+
void BKE_scene_remove_rigidbody_object(struct Main *bmain, Scene *scene, Object *ob)
{
/* remove rigid body constraint from world before removing object */
@@ -1282,7 +1336,7 @@ static void scene_armature_depsgraph_workaround(Main *bmain, Depsgraph *depsgrap
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) {
if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild(ob, ob->data);
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
}
}
}
@@ -1307,7 +1361,7 @@ static bool check_rendered_viewport_visible(Main *bmain)
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
- if (v3d->drawtype == OB_RENDER) {
+ if (v3d->shading.type == OB_RENDER) {
return true;
}
}
@@ -1423,6 +1477,18 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph,
DEG_ids_clear_recalc(bmain, depsgraph);
}
+/** Ensures given scene/view_layer pair has a valid, up-to-date depsgraph.
+ *
+ * \warning Sets matching depsgraph as active, so should only be called from the active editing context
+ * (usually, from operators).
+ */
+void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, ViewLayer *view_layer)
+{
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ DEG_make_active(depsgraph);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+}
+
/* return default view */
SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
{
@@ -1541,6 +1607,11 @@ bool BKE_scene_uses_blender_eevee(const Scene *scene)
return STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE);
}
+bool BKE_scene_uses_blender_opengl(const Scene *scene)
+{
+ return STREQ(scene->r.engine, RE_engine_id_BLENDER_OPENGL);
+}
+
bool BKE_scene_uses_cycles(const Scene *scene)
{
return STREQ(scene->r.engine, RE_engine_id_CYCLES);
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 448b97c63b3..c107bb04e6e 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -45,9 +45,10 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
+#include "BLI_math_vector.h"
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
@@ -855,6 +856,22 @@ void BKE_screen_view3d_scene_sync(bScreen *sc, Scene *scene)
}
}
+void BKE_screen_view3d_shading_init(View3DShading *shading)
+{
+ memset(shading, 0, sizeof(*shading));
+
+ shading->type = OB_SOLID;
+ shading->prev_type = OB_SOLID;
+ shading->flag = V3D_SHADING_SPECULAR_HIGHLIGHT;
+ shading->light = V3D_LIGHTING_STUDIO;
+ shading->shadow_intensity = 0.5f;
+ shading->xray_alpha = 0.5f;
+ shading->cavity_valley_factor = 1.0f;
+ shading->cavity_ridge_factor = 1.0f;
+ copy_v3_fl(shading->single_color, 0.8f);
+ copy_v3_fl(shading->background_color, 0.05f);
+}
+
/* magic zoom calculation, no idea what
* it signifies, if you find out, tell me! -zr
*/
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index d857db7e276..b5b4ec5cd41 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -5530,6 +5530,7 @@ static Sequence *seq_dupli(const Scene *scene_src, Scene *scene_dst, Sequence *s
if (scene_src == scene_dst) {
if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) {
+ /* TODO this is broken in case of Meta strips recursive duplication... Not trivial to fix. */
BKE_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn);
}
diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c
new file mode 100644
index 00000000000..c028c2184fd
--- /dev/null
+++ b/source/blender/blenkernel/intern/shader_fx.c
@@ -0,0 +1,245 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/shader_fx.c
+ * \ingroup bke
+ */
+
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_shader_fx_types.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_gpencil.h"
+#include "BKE_shader_fx.h"
+#include "BKE_object.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "FX_shader_types.h"
+
+static ShaderFxTypeInfo *shader_fx_types[NUM_SHADER_FX_TYPES] = { NULL };
+
+/* *************************************************** */
+/* Methods - Evaluation Loops, etc. */
+
+/* check if exist grease pencil effects */
+bool BKE_shaderfx_has_gpencil(Object *ob)
+{
+ ShaderFxData *fx;
+ for (fx = ob->shader_fx.first; fx; fx = fx->next) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+ if (fxi->type == eShaderFxType_GpencilType) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void BKE_shaderfx_init(void)
+{
+ /* Initialize shaders */
+ shaderfx_type_init(shader_fx_types); /* FX_shader_util.c */
+}
+
+ShaderFxData *BKE_shaderfx_new(int type)
+{
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
+ ShaderFxData *fx = MEM_callocN(fxi->struct_size, fxi->struct_name);
+
+ /* note, this name must be made unique later */
+ BLI_strncpy(fx->name, DATA_(fxi->name), sizeof(fx->name));
+
+ fx->type = type;
+ fx->mode = eShaderFxMode_Realtime | eShaderFxMode_Render | eShaderFxMode_Expanded;
+ fx->flag = eShaderFxFlag_StaticOverride_Local;
+
+ if (fxi->flags & eShaderFxTypeFlag_EnableInEditmode)
+ fx->mode |= eShaderFxMode_Editmode;
+
+ if (fxi->initData) fxi->initData(fx);
+
+ return fx;
+}
+
+static void shaderfx_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_min(id);
+ }
+}
+
+void BKE_shaderfx_free_ex(ShaderFxData *fx, const int flag)
+{
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (fxi->foreachIDLink) {
+ fxi->foreachIDLink(fx, NULL, shaderfx_free_data_id_us_cb, NULL);
+ }
+ else if (fxi->foreachObjectLink) {
+ fxi->foreachObjectLink(fx, NULL, (ShaderFxObjectWalkFunc)shaderfx_free_data_id_us_cb, NULL);
+ }
+ }
+
+ if (fxi->freeData) fxi->freeData(fx);
+ if (fx->error) MEM_freeN(fx->error);
+
+ MEM_freeN(fx);
+}
+
+void BKE_shaderfx_free(ShaderFxData *fx)
+{
+ BKE_shaderfx_free_ex(fx, 0);
+}
+
+/* check unique name */
+bool BKE_shaderfx_unique_name(ListBase *shaders, ShaderFxData *fx)
+{
+ if (shaders && fx) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+ return BLI_uniquename(shaders, fx, DATA_(fxi->name), '.', offsetof(ShaderFxData, name), sizeof(fx->name));
+ }
+ return false;
+}
+
+bool BKE_shaderfx_dependsOnTime(ShaderFxData *fx)
+{
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+
+ return fxi->dependsOnTime && fxi->dependsOnTime(fx);
+}
+
+const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type)
+{
+ /* type unsigned, no need to check < 0 */
+ if (type < NUM_SHADER_FX_TYPES && shader_fx_types[type]->name[0] != '\0') {
+ return shader_fx_types[type];
+ }
+ else {
+ return NULL;
+ }
+}
+
+void BKE_shaderfx_copyData_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst)
+{
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx_src->type);
+
+ /* fx_dst may have alredy be fully initialized with some extra allocated data,
+ * we need to free it now to avoid memleak. */
+ if (fxi->freeData) {
+ fxi->freeData(fx_dst);
+ }
+
+ const size_t data_size = sizeof(ShaderFxData);
+ const char *fx_src_data = ((const char *)fx_src) + data_size;
+ char *fx_dst_data = ((char *)fx_dst) + data_size;
+ BLI_assert(data_size <= (size_t)fxi->struct_size);
+ memcpy(fx_dst_data, fx_src_data, (size_t)fxi->struct_size - data_size);
+}
+
+static void shaderfx_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_plus(id);
+ }
+}
+
+void BKE_shaderfx_copyData_ex(ShaderFxData *fx, ShaderFxData *target, const int flag)
+{
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+
+ target->mode = fx->mode;
+ target->flag = fx->flag;
+
+ if (fxi->copyData) {
+ fxi->copyData(fx, target);
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (fxi->foreachIDLink) {
+ fxi->foreachIDLink(target, NULL, shaderfx_copy_data_id_us_cb, NULL);
+ }
+ else if (fxi->foreachObjectLink) {
+ fxi->foreachObjectLink(target, NULL, (ShaderFxObjectWalkFunc)shaderfx_copy_data_id_us_cb, NULL);
+ }
+ }
+}
+
+void BKE_shaderfx_copyData(ShaderFxData *fx, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_ex(fx, target, 0);
+}
+
+ShaderFxData *BKE_shaderfx_findByType(Object *ob, ShaderFxType type)
+{
+ ShaderFxData *fx = ob->shader_fx.first;
+
+ for (; fx; fx = fx->next)
+ if (fx->type == type)
+ break;
+
+ return fx;
+}
+
+void BKE_shaderfx_foreachIDLink(Object *ob, ShaderFxIDWalkFunc walk, void *userData)
+{
+ ShaderFxData *fx = ob->shader_fx.first;
+
+ for (; fx; fx = fx->next) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+
+ if (fxi->foreachIDLink) fxi->foreachIDLink(fx, ob, walk, userData);
+ else if (fxi->foreachObjectLink) {
+ /* each Object can masquerade as an ID, so this should be OK */
+ ShaderFxObjectWalkFunc fp = (ShaderFxObjectWalkFunc)walk;
+ fxi->foreachObjectLink(fx, ob, fp, userData);
+ }
+ }
+}
+
+ShaderFxData *BKE_shaderfx_findByName(Object *ob, const char *name)
+{
+ return BLI_findstring(&(ob->shader_fx), name, offsetof(ShaderFxData, name));
+}
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index ebb23f8d5c6..5135362bd69 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -756,15 +756,19 @@ int BKE_sound_scene_playing(struct Scene *scene)
void BKE_sound_free_waveform(bSound *sound)
{
- SoundWaveform *waveform = sound->waveform;
- if (waveform) {
- if (waveform->data) {
- MEM_freeN(waveform->data);
+ if ((sound->tags & SOUND_TAGS_WAVEFORM_NO_RELOAD) == 0) {
+ SoundWaveform *waveform = sound->waveform;
+ if (waveform) {
+ if (waveform->data) {
+ MEM_freeN(waveform->data);
+ }
+ MEM_freeN(waveform);
}
- MEM_freeN(waveform);
- }
- sound->waveform = NULL;
+ sound->waveform = NULL;
+ }
+ /* This tag is only valid once. */
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_NO_RELOAD;
}
void BKE_sound_read_waveform(bSound *sound, short *stop)
@@ -793,7 +797,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
}
MEM_freeN(waveform);
BLI_spin_lock(sound->spinlock);
- sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
return;
}
@@ -802,7 +806,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
BLI_spin_lock(sound->spinlock);
sound->waveform = waveform;
- sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
}
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 200c50e5c23..df5cc7551aa 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -442,106 +442,64 @@ static void studiolight_calculate_spherical_harmonics_coefficient(StudioLight *s
switch (sh_component) {
/* L0 */
case 0:
- {
coef = 0.2822095f;
break;
- }
-
/* L1 */
case 1:
- {
coef = -0.488603f * nz * 2.0f / 3.0f;
break;
- }
case 2:
- {
coef = 0.488603f * ny * 2.0f / 3.0f;
break;
- }
case 3:
- {
coef = -0.488603f * nx * 2.0f / 3.0f;
break;
- }
-
/* L2 */
case 4:
- {
coef = 1.092548f * nx * nz * 1.0f / 4.0f;
break;
- }
case 5:
- {
coef = -1.092548f * nz * ny * 1.0f / 4.0f;
break;
- }
case 6:
- {
coef = 0.315392f * (3.0f * ny2 - 1.0f) * 1.0f / 4.0f;
break;
- }
case 7:
- {
coef = 1.092548f * nx * ny * 1.0f / 4.0f;
break;
- }
case 8:
- {
coef = 0.546274f * (nx2 - nz2) * 1.0f / 4.0f;
break;
- }
-
/* L4 */
case 9:
- {
coef = (2.5033429417967046f * nx * nz * (nx2 - nz2)) / -24.0f;
break;
- }
case 10:
- {
coef = (-1.7701307697799304f * nz * ny * (3.0f * nx2 - nz2)) / -24.0f;
break;
- }
case 11:
- {
coef = (0.9461746957575601f * nz * nx * (-1.0f + 7.0f * ny2)) / -24.0f;
break;
- }
case 12:
- {
coef = (-0.6690465435572892f * nz * ny * (-3.0f + 7.0f * ny2)) / -24.0f;
break;
- }
case 13:
- {
coef = ((105.0f * ny4 - 90.0f * ny2 + 9.0f) / 28.359261614f) / -24.0f;
break;
- }
case 14:
- {
coef = (-0.6690465435572892f * nx * ny * (-3.0f + 7.0f * ny2)) / -24.0f;
break;
- }
case 15:
- {
coef = (0.9461746957575601f * (nx2 - nz2) * (-1.0f + 7.0f * ny2)) / -24.0f;
break;
- }
case 16:
- {
coef = (-1.7701307697799304f * nx * ny * (nx2 - 3.0f * nz2)) / -24.0f;
break;
- }
case 17:
- {
coef = (0.6258357354491761f * (nx4 - 6.0f * nz2 * nx2 + nz4)) / -24.0f;
break;
- }
-
default:
- {
coef = 0.0f;
- }
}
madd_v3_v3fl(sh, color, coef * weight);
@@ -1037,7 +995,7 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
if (flipped) {
fx = 1.0f - fx;
}
- nearest_interpolation_color(ibuf, NULL, color, fx * ibuf->x, fy * ibuf->y);
+ nearest_interpolation_color(ibuf, NULL, color, fx * ibuf->x - 1.0f, fy * ibuf->y - 1.0f);
uint alphamask = alpha_circle_mask(fx, fy, 0.5f - pixel_size, 0.5f);
diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c
new file mode 100644
index 00000000000..bae5491c079
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv.c
@@ -0,0 +1,114 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/subdiv.c
+ * \ingroup bke
+ */
+
+#include "BKE_subdiv.h"
+
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "subdiv_converter.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+# include "opensubdiv_converter_capi.h"
+# include "opensubdiv_evaluator_capi.h"
+# include "opensubdiv_topology_refiner_capi.h"
+#endif
+
+Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
+ struct OpenSubdiv_Converter *converter)
+{
+#ifdef WITH_OPENSUBDIV
+ SubdivStats stats;
+ BKE_subdiv_stats_init(&stats);
+ BKE_subdiv_stats_begin(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
+ OpenSubdiv_TopologyRefinerSettings topology_refiner_settings;
+ topology_refiner_settings.level = settings->level;
+ topology_refiner_settings.is_adaptive = settings->is_adaptive;
+ struct OpenSubdiv_TopologyRefiner *osd_topology_refiner = NULL;
+ if (converter->getNumVertices(converter) != 0) {
+ osd_topology_refiner =
+ openSubdiv_createTopologyRefinerFromConverter(
+ converter, &topology_refiner_settings);
+
+ }
+ else {
+ /* TODO(sergey): Check whether original geometry had any vertices.
+ * The thing here is: OpenSubdiv can only deal with faces, but our
+ * side of subdiv also deals with loose vertices and edges.
+ */
+ }
+ Subdiv *subdiv = MEM_callocN(sizeof(Subdiv), "subdiv from converetr");
+ subdiv->settings = *settings;
+ subdiv->topology_refiner = osd_topology_refiner;
+ subdiv->evaluator = NULL;
+ BKE_subdiv_stats_end(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
+ subdiv->stats = stats;
+ return subdiv;
+#else
+ UNUSED_VARS(settings, converter);
+ return NULL;
+#endif
+}
+
+Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
+ struct Mesh *mesh)
+{
+#ifdef WITH_OPENSUBDIV
+ if (mesh->totvert == 0) {
+ return NULL;
+ }
+ OpenSubdiv_Converter converter;
+ BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
+ Subdiv *subdiv = BKE_subdiv_new_from_converter(settings, &converter);
+ BKE_subdiv_converter_free(&converter);
+ return subdiv;
+#else
+ UNUSED_VARS(settings, mesh);
+ return NULL;
+#endif
+}
+
+void BKE_subdiv_free(Subdiv *subdiv)
+{
+#ifdef WITH_OPENSUBDIV
+ if (subdiv->evaluator != NULL) {
+ openSubdiv_deleteEvaluator(subdiv->evaluator);
+ }
+ if (subdiv->topology_refiner != NULL) {
+ openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner);
+ }
+ MEM_freeN(subdiv);
+#else
+ UNUSED_VARS(subdiv);
+#endif
+}
diff --git a/source/blender/blenkernel/intern/subdiv_converter.c b/source/blender/blenkernel/intern/subdiv_converter.c
new file mode 100644
index 00000000000..f6dabfa1c80
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_converter.c
@@ -0,0 +1,65 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "subdiv_converter.h"
+
+#include "BLI_utildefines.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_converter_capi.h"
+#endif
+
+void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter)
+{
+#ifdef WITH_OPENSUBDIV
+ if (converter->freeUserData) {
+ converter->freeUserData(converter);
+ }
+#else
+ UNUSED_VARS(converter);
+#endif
+}
+
+/*OpenSubdiv_FVarLinearInterpolation*/ int
+BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings)
+{
+#ifdef WITH_OPENSUBDIV
+ switch (settings->fvar_linear_interpolation) {
+ case SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE:
+ return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
+ case SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY:
+ return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY;
+ case SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES:
+ return OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES;
+ case SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL:
+ return OSD_FVAR_LINEAR_INTERPOLATION_ALL;
+ }
+ BLI_assert(!"Unknown fvar linear interpolation");
+ return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
+#else
+ UNUSED_VARS(settings);
+ return 0;
+#endif
+}
diff --git a/source/blender/blenkernel/intern/subdiv_converter.h b/source/blender/blenkernel/intern/subdiv_converter.h
new file mode 100644
index 00000000000..4c552a9164e
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_converter.h
@@ -0,0 +1,57 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __SUBDIV_CONVERTER_H__
+#define __SUBDIV_CONVERTER_H__
+
+#include "BKE_subdiv.h"
+
+/* NOTE: Was initially used to get proper enumerator types, but this makes
+ * it tricky to compile without OpenSubdiv.
+ */
+/* #include "opensubdiv_converter_capi.h" */
+
+struct Mesh;
+struct OpenSubdiv_Converter;
+struct SubdivSettings;
+
+void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
+ const struct SubdivSettings *settings,
+ const struct Mesh *mesh);
+
+/* NOTE: Frees converter data, but not converter itself. This means, that if
+ * converter was allocated on heap, it is up to the user to free that memory.
+ */
+void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter);
+
+/* ============================ INTERNAL HELPERS ============================ */
+
+/* TODO(sergey): Find a way to make it OpenSubdiv_FVarLinearInterpolation,
+ * without breaking compilation without OpenSubdiv.
+ */
+int BKE_subdiv_converter_fvar_linear_from_settings(
+ const SubdivSettings *settings);
+
+#endif /* __SUBDIV_CONVERTER_H__ */
diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.c b/source/blender/blenkernel/intern/subdiv_converter_mesh.c
new file mode 100644
index 00000000000..c5fb8afb6cd
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.c
@@ -0,0 +1,406 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "subdiv_converter.h"
+
+#include <string.h>
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_customdata.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_subdiv.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+# include "opensubdiv_converter_capi.h"
+#endif
+
+#ifdef WITH_OPENSUBDIV
+typedef struct ConverterStorage {
+ SubdivSettings settings;
+ const Mesh *mesh;
+ /* Indexed by loop index, value denotes index of face-varying vertex
+ * which corresponds to the UV coordinate.
+ */
+ int *loop_uv_indices;
+ int num_uv_coordinates;
+ /* Indexed by coarse mesh elements, gives index of corresponding element
+ * with ignoring all non-manifold entities.
+ *
+ * NOTE: This isn't strictly speaking manifold, this is more like non-loose
+ * geometry index. As in, index of element as if there were no loose edges
+ * or vertices in the mesh.
+ */
+ int *manifold_vertex_index;
+ /* Indexed by vertex index from mesh, corresponds to whether this vertex has
+ * infinite sharpness due to non-manifol topology.
+ */
+ BLI_bitmap *infinite_sharp_vertices_map;
+ /* Reverse mapping to above. */
+ int *manifold_vertex_index_reverse;
+ int *manifold_edge_index_reverse;
+ /* Number of non-loose elements. */
+ int num_manifold_vertices;
+ int num_manifold_edges;
+} ConverterStorage;
+
+static OpenSubdiv_SchemeType get_scheme_type(
+ const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ if (storage->settings.is_simple) {
+ return OSD_SCHEME_BILINEAR;
+ }
+ else {
+ return OSD_SCHEME_CATMARK;
+ }
+}
+
+static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
+ const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ return BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings);
+}
+
+static bool specifies_full_topology(
+ const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return false;
+}
+
+static int get_num_faces(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ return storage->mesh->totpoly;
+}
+
+static int get_num_edges(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ return storage->num_manifold_edges;
+}
+
+static int get_num_vertices(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ return storage->num_manifold_vertices;
+}
+
+static int get_num_face_vertices(const OpenSubdiv_Converter *converter,
+ int manifold_face_index)
+{
+ ConverterStorage *storage = converter->user_data;
+ return storage->mesh->mpoly[manifold_face_index].totloop;
+}
+
+static void get_face_vertices(const OpenSubdiv_Converter *converter,
+ int manifold_face_index,
+ int *manifold_face_vertices)
+{
+ ConverterStorage *storage = converter->user_data;
+ const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
+ const MLoop *mloop = storage->mesh->mloop;
+ for (int corner = 0; corner < poly->totloop; corner++) {
+ manifold_face_vertices[corner] = storage->manifold_vertex_index[
+ mloop[poly->loopstart + corner].v];
+ }
+}
+
+static void get_edge_vertices(const OpenSubdiv_Converter *converter,
+ int manifold_edge_index,
+ int *manifold_edge_vertices)
+{
+ ConverterStorage *storage = converter->user_data;
+ const int edge_index =
+ storage->manifold_edge_index_reverse[manifold_edge_index];
+ const MEdge *edge = &storage->mesh->medge[edge_index];
+ manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
+ manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
+}
+
+static float get_edge_sharpness(const OpenSubdiv_Converter *converter,
+ int manifold_edge_index)
+{
+ ConverterStorage *storage = converter->user_data;
+ const int edge_index =
+ storage->manifold_edge_index_reverse[manifold_edge_index];
+ const MEdge *medge = storage->mesh->medge;
+ const float edge_crease = (float)medge[edge_index].crease / 255.0f;
+ return edge_crease * edge_crease * 10.0f;
+}
+
+
+static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
+ int manifold_vertex_index)
+{
+ ConverterStorage *storage = converter->user_data;
+ const int vertex_index =
+ storage->manifold_vertex_index_reverse[manifold_vertex_index];
+ return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map,
+ vertex_index);
+}
+
+static float get_vertex_sharpness(const OpenSubdiv_Converter *UNUSED(converter),
+ int UNUSED(manifold_vertex_index))
+{
+ return 0.0f;
+}
+
+static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ const Mesh *mesh = storage->mesh;
+ return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
+}
+
+static void precalc_uv_layer(const OpenSubdiv_Converter *converter,
+ const int layer_index)
+{
+ ConverterStorage *storage = converter->user_data;
+ const Mesh *mesh = storage->mesh;
+ const MPoly *mpoly = mesh->mpoly;
+ const MLoop *mloop = mesh->mloop;
+ const MLoopUV *mloopuv = CustomData_get_layer_n(
+ &mesh->ldata, CD_MLOOPUV, layer_index);
+ const int num_poly = mesh->totpoly;
+ const int num_vert = mesh->totvert;
+ const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
+ /* Initialize memory required for the operations. */
+ if (storage->loop_uv_indices == NULL) {
+ storage->loop_uv_indices = MEM_malloc_arrayN(
+ mesh->totloop, sizeof(int), "loop uv vertex index");
+ }
+ UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
+ mpoly, mloop, mloopuv,
+ num_poly, num_vert,
+ limit,
+ false, true);
+ /* NOTE: First UV vertex is supposed to be always marked as separate. */
+ storage->num_uv_coordinates = -1;
+ for (int vertex_index = 0; vertex_index < num_vert; ++vertex_index) {
+ const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map,
+ vertex_index);
+ while (uv_vert != NULL) {
+ if (uv_vert->separate) {
+ storage->num_uv_coordinates++;
+ }
+ const MPoly *mp = &mpoly[uv_vert->poly_index];
+ const int global_loop_index = mp->loopstart +
+ uv_vert->loop_of_poly_index;
+ storage->loop_uv_indices[global_loop_index] =
+ storage->num_uv_coordinates;
+ uv_vert = uv_vert->next;
+ }
+ }
+ /* So far this value was used as a 0-based index, actual number of UV
+ * vertices is 1 more.
+ */
+ storage->num_uv_coordinates += 1;
+ BKE_mesh_uv_vert_map_free(uv_vert_map);
+}
+
+static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
+{
+}
+
+static int get_num_uvs(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *storage = converter->user_data;
+ return storage->num_uv_coordinates;
+}
+
+static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
+ const int face_index,
+ const int corner)
+{
+ ConverterStorage *storage = converter->user_data;
+ const MPoly *mp = &storage->mesh->mpoly[face_index];
+ return storage->loop_uv_indices[mp->loopstart + corner];
+}
+
+static void free_user_data(const OpenSubdiv_Converter *converter)
+{
+ ConverterStorage *user_data = converter->user_data;
+ MEM_SAFE_FREE(user_data->loop_uv_indices);
+ MEM_freeN(user_data->manifold_vertex_index);
+ MEM_freeN(user_data->infinite_sharp_vertices_map);
+ MEM_freeN(user_data->manifold_vertex_index_reverse);
+ MEM_freeN(user_data->manifold_edge_index_reverse);
+ MEM_freeN(user_data);
+}
+
+static void init_functions(OpenSubdiv_Converter *converter)
+{
+ converter->getSchemeType = get_scheme_type;
+ converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
+ converter->specifiesFullTopology = specifies_full_topology;
+
+ converter->getNumFaces = get_num_faces;
+ converter->getNumEdges = get_num_edges;
+ converter->getNumVertices = get_num_vertices;
+
+ converter->getNumFaceVertices = get_num_face_vertices;
+ converter->getFaceVertices = get_face_vertices;
+ converter->getFaceEdges = NULL;
+
+ converter->getEdgeVertices = get_edge_vertices;
+ converter->getNumEdgeFaces = NULL;
+ converter->getEdgeFaces = NULL;
+ converter->getEdgeSharpness = get_edge_sharpness;
+
+ converter->getNumVertexEdges = NULL;
+ converter->getVertexEdges = NULL;
+ converter->getNumVertexFaces = NULL;
+ converter->getVertexFaces = NULL;
+ converter->isInfiniteSharpVertex = is_infinite_sharp_vertex;
+ converter->getVertexSharpness = get_vertex_sharpness;
+
+ converter->getNumUVLayers = get_num_uv_layers;
+ converter->precalcUVLayer = precalc_uv_layer;
+ converter->finishUVLayer = finish_uv_layer;
+ converter->getNumUVCoordinates = get_num_uvs;
+ converter->getFaceCornerUVIndex = get_face_corner_uv_index;
+
+ converter->freeUserData = free_user_data;
+}
+
+static void initialize_manifold_index_array(const BLI_bitmap *used_map,
+ const int num_elements,
+ int **indices_r,
+ int **indices_reverse_r,
+ int *num_manifold_elements_r)
+{
+ int *indices = NULL;
+ if (indices_r != NULL) {
+ indices = MEM_malloc_arrayN(
+ num_elements, sizeof(int), "manifold indices");
+ }
+ int *indices_reverse = NULL;
+ if (indices_reverse_r != NULL) {
+ indices_reverse = MEM_malloc_arrayN(
+ num_elements, sizeof(int), "manifold indices reverse");
+ }
+ int offset = 0;
+ for (int i = 0; i < num_elements; i++) {
+ if (BLI_BITMAP_TEST_BOOL(used_map, i)) {
+ if (indices != NULL) {
+ indices[i] = i - offset;
+ }
+ if (indices_reverse != NULL) {
+ indices_reverse[i - offset] = i;
+ }
+ }
+ else {
+ if (indices != NULL) {
+ indices[i] = -1;
+ }
+ offset++;
+ }
+ }
+ if (indices_r != NULL) {
+ *indices_r = indices;
+ }
+ if (indices_reverse_r != NULL) {
+ *indices_reverse_r = indices_reverse;
+ }
+ *num_manifold_elements_r = num_elements - offset;
+}
+
+static void initialize_manifold_indices(ConverterStorage *storage)
+{
+ const Mesh *mesh = storage->mesh;
+ const MEdge *medge = mesh->medge;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ /* Set bits of elements which are not loose. */
+ BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
+ BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
+ for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
+ const MPoly *poly = &mpoly[poly_index];
+ for (int corner = 0; corner < poly->totloop; corner++) {
+ const MLoop *loop = &mloop[poly->loopstart + corner];
+ BLI_BITMAP_ENABLE(vert_used_map, loop->v);
+ BLI_BITMAP_ENABLE(edge_used_map, loop->e);
+ }
+ }
+ initialize_manifold_index_array(vert_used_map,
+ mesh->totvert,
+ &storage->manifold_vertex_index,
+ &storage->manifold_vertex_index_reverse,
+ &storage->num_manifold_vertices);
+ initialize_manifold_index_array(edge_used_map,
+ mesh->totedge,
+ NULL,
+ &storage->manifold_edge_index_reverse,
+ &storage->num_manifold_edges);
+ /* Initialize infinite sharp mapping. */
+ storage->infinite_sharp_vertices_map =
+ BLI_BITMAP_NEW(mesh->totvert, "vert used map");
+ for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
+ if (!BLI_BITMAP_TEST_BOOL(edge_used_map, edge_index)) {
+ const MEdge *edge = &medge[edge_index];
+ BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v1);
+ BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v2);
+ }
+ }
+ /* Free working variables. */
+ MEM_freeN(vert_used_map);
+ MEM_freeN(edge_used_map);
+}
+
+static void init_user_data(OpenSubdiv_Converter *converter,
+ const SubdivSettings *settings,
+ const Mesh *mesh)
+{
+ ConverterStorage *user_data =
+ MEM_mallocN(sizeof(ConverterStorage), __func__);
+ user_data->settings = *settings;
+ user_data->mesh = mesh;
+ user_data->loop_uv_indices = NULL;
+ initialize_manifold_indices(user_data);
+ converter->user_data = user_data;
+}
+#endif
+
+void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
+ const SubdivSettings *settings,
+ const Mesh *mesh)
+{
+#ifdef WITH_OPENSUBDIV
+ init_functions(converter);
+ init_user_data(converter, settings, mesh);
+#else
+ UNUSED_VARS(converter, settings, mesh);
+#endif
+}
diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c
new file mode 100644
index 00000000000..e23be84ee26
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_eval.c
@@ -0,0 +1,361 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/subdiv_eval.c
+ * \ingroup bke
+ */
+
+#include "BKE_subdiv.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_customdata.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_evaluator_capi.h"
+# include "opensubdiv_topology_refiner_capi.h"
+#endif
+
+void BKE_subdiv_eval_begin(Subdiv *subdiv)
+{
+#ifdef WITH_OPENSUBDIV
+ if (subdiv->topology_refiner == NULL) {
+ /* Happens on input mesh with just loose geometry. */
+ }
+ else if (subdiv->evaluator == NULL) {
+ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
+ subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(
+ subdiv->topology_refiner);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
+ }
+ else {
+ /* TODO(sergey): Check for topology change. */
+ }
+#else
+ UNUSED_VARS(subdiv);
+#endif
+}
+
+#ifdef WITH_OPENSUBDIV
+static void set_coarse_positions(Subdiv *subdiv, const Mesh *mesh)
+{
+ const MVert *mvert = mesh->mvert;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ /* Mark vertices which needs new coordinates. */
+ /* TODO(sergey): This is annoying to calculate this on every update,
+ * maybe it's better to cache this mapping. Or make it possible to have
+ * OpenSubdiv's vertices match mesh ones?
+ */
+ BLI_bitmap *vertex_used_map =
+ BLI_BITMAP_NEW(mesh->totvert, "vert used map");
+ for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
+ const MPoly *poly = &mpoly[poly_index];
+ for (int corner = 0; corner < poly->totloop; corner++) {
+ const MLoop *loop = &mloop[poly->loopstart + corner];
+ BLI_BITMAP_ENABLE(vertex_used_map, loop->v);
+ }
+ }
+ for (int vertex_index = 0, manifold_veretx_index = 0;
+ vertex_index < mesh->totvert;
+ vertex_index++)
+ {
+ if (!BLI_BITMAP_TEST_BOOL(vertex_used_map, vertex_index)) {
+ continue;
+ }
+ const MVert *vertex = &mvert[vertex_index];
+ subdiv->evaluator->setCoarsePositions(
+ subdiv->evaluator,
+ vertex->co,
+ manifold_veretx_index, 1);
+ manifold_veretx_index++;
+ }
+ MEM_freeN(vertex_used_map);
+}
+
+static void set_face_varying_data_from_uv(Subdiv *subdiv,
+ const MLoopUV *mloopuv,
+ const int layer_index)
+{
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+ OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
+ const int num_faces = topology_refiner->getNumFaces(topology_refiner);
+ const MLoopUV *mluv = mloopuv;
+ /* TODO(sergey): OpenSubdiv's C-API converter can change winding of
+ * loops of a face, need to watch for that, to prevent wrong UVs assigned.
+ */
+ for (int face_index = 0; face_index < num_faces; ++face_index) {
+ const int num_face_vertices = topology_refiner->getNumFaceVertices(
+ topology_refiner, face_index);
+ const int *uv_indicies = topology_refiner->getFaceFVarValueIndices(
+ topology_refiner, face_index, layer_index);
+ for (int vertex_index = 0;
+ vertex_index < num_face_vertices;
+ vertex_index++, mluv++)
+ {
+ evaluator->setFaceVaryingData(evaluator,
+ layer_index,
+ mluv->uv,
+ uv_indicies[vertex_index],
+ 1);
+ }
+ }
+}
+#endif
+
+void BKE_subdiv_eval_update_from_mesh(Subdiv *subdiv, const Mesh *mesh)
+{
+#ifdef WITH_OPENSUBDIV
+ BKE_subdiv_eval_begin(subdiv);
+ if (subdiv->evaluator == NULL) {
+ return;
+ }
+ /* Set coordinates of base mesh vertices. */
+ set_coarse_positions(subdiv, mesh);
+ /* Set face-varyign data to UV maps. */
+ const int num_uv_layers =
+ CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
+ for (int layer_index = 0; layer_index < num_uv_layers; layer_index++) {
+ const MLoopUV *mloopuv = CustomData_get_layer_n(
+ &mesh->ldata, CD_MLOOPUV, layer_index);
+ set_face_varying_data_from_uv(subdiv, mloopuv, layer_index);
+ }
+ /* Update evaluator to the new coarse geometry. */
+ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
+ subdiv->evaluator->refine(subdiv->evaluator);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
+#else
+ UNUSED_VARS(subdiv, mesh);
+#endif
+}
+
+/* ========================== Single point queries ========================== */
+
+void BKE_subdiv_eval_limit_point(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3])
+{
+ BKE_subdiv_eval_limit_point_and_derivatives(subdiv,
+ ptex_face_index,
+ u, v,
+ P, NULL, NULL);
+}
+
+void BKE_subdiv_eval_limit_point_and_derivatives(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], float dPdu[3], float dPdv[3])
+{
+#ifdef WITH_OPENSUBDIV
+ subdiv->evaluator->evaluateLimit(subdiv->evaluator,
+ ptex_face_index,
+ u, v,
+ P, dPdu, dPdv);
+#else
+ UNUSED_VARS(subdiv, ptex_face_index, u, v, P, dPdu, dPdv);
+#endif
+}
+
+void BKE_subdiv_eval_limit_point_and_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], float N[3])
+{
+ float dPdu[3], dPdv[3];
+ BKE_subdiv_eval_limit_point_and_derivatives(subdiv,
+ ptex_face_index,
+ u, v,
+ P, dPdu, dPdv);
+ cross_v3_v3v3(N, dPdu, dPdv);
+ normalize_v3(N);
+}
+
+void BKE_subdiv_eval_limit_point_and_short_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float P[3], short N[3])
+{
+ float N_float[3];
+ BKE_subdiv_eval_limit_point_and_normal(subdiv,
+ ptex_face_index,
+ u, v,
+ P, N_float);
+ normal_float_to_short_v3(N, N_float);
+}
+
+void BKE_subdiv_eval_face_varying(
+ Subdiv *subdiv,
+ const int face_varying_channel,
+ const int ptex_face_index,
+ const float u, const float v,
+ float face_varying[2])
+{
+#ifdef WITH_OPENSUBDIV
+ subdiv->evaluator->evaluateFaceVarying(subdiv->evaluator,
+ face_varying_channel,
+ ptex_face_index,
+ u, v,
+ face_varying);
+#else
+ UNUSED_VARS(subdiv, face_varying_channel, ptex_face_index, u, v, face_varying);
+#endif
+}
+
+/* =================== Patch queries at given resolution =================== */
+
+/* Move buffer forward by a given number of bytes. */
+static void buffer_apply_offset(void **buffer, const int offset)
+{
+ *buffer = ((unsigned char *)*buffer) + offset;
+}
+
+/* Write given number of floats to the beginning of given buffer. */
+static void buffer_write_float_value(void **buffer,
+ const float *values_buffer, int num_values)
+{
+ memcpy(*buffer, values_buffer, sizeof(float) * num_values);
+}
+
+/* Similar to above, just operates with short values. */
+static void buffer_write_short_value(void **buffer,
+ const short *values_buffer, int num_values)
+{
+ memcpy(*buffer, values_buffer, sizeof(short) * num_values);
+}
+
+void BKE_subdiv_eval_limit_patch_resolution_point(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *buffer, const int offset, const int stride)
+{
+ buffer_apply_offset(&buffer, offset);
+ const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * inv_resolution_1;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * inv_resolution_1;
+ BKE_subdiv_eval_limit_point(subdiv,
+ ptex_face_index,
+ u, v,
+ buffer);
+ buffer_apply_offset(&buffer, stride);
+ }
+ }
+}
+
+void BKE_subdiv_eval_limit_patch_resolution_point_and_derivatives(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *du_buffer, const int du_offset, const int du_stride,
+ void *dv_buffer, const int dv_offset, const int dv_stride)
+{
+ buffer_apply_offset(&point_buffer, point_offset);
+ buffer_apply_offset(&du_buffer, du_offset);
+ buffer_apply_offset(&dv_buffer, dv_offset);
+ const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * inv_resolution_1;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * inv_resolution_1;
+ BKE_subdiv_eval_limit_point_and_derivatives(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ point_buffer, du_buffer, dv_buffer);
+ buffer_apply_offset(&point_buffer, point_stride);
+ buffer_apply_offset(&du_buffer, du_stride);
+ buffer_apply_offset(&dv_buffer, dv_stride);
+ }
+ }
+}
+
+void BKE_subdiv_eval_limit_patch_resolution_point_and_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *normal_buffer, const int normal_offset, const int normal_stride)
+{
+ buffer_apply_offset(&point_buffer, point_offset);
+ buffer_apply_offset(&normal_buffer, normal_offset);
+ const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * inv_resolution_1;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * inv_resolution_1;
+ float normal[3];
+ BKE_subdiv_eval_limit_point_and_normal(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ point_buffer, normal);
+ buffer_write_float_value(&normal_buffer, normal, 3);
+ buffer_apply_offset(&point_buffer, point_stride);
+ buffer_apply_offset(&normal_buffer, normal_stride);
+ }
+ }
+}
+
+void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const int resolution,
+ void *point_buffer, const int point_offset, const int point_stride,
+ void *normal_buffer, const int normal_offset, const int normal_stride)
+{
+ buffer_apply_offset(&point_buffer, point_offset);
+ buffer_apply_offset(&normal_buffer, normal_offset);
+ const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
+ for (int y = 0; y < resolution; y++) {
+ const float v = y * inv_resolution_1;
+ for (int x = 0; x < resolution; x++) {
+ const float u = x * inv_resolution_1;
+ short normal[3];
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ point_buffer, normal);
+ buffer_write_short_value(&normal_buffer, normal, 3);
+ buffer_apply_offset(&point_buffer, point_stride);
+ buffer_apply_offset(&normal_buffer, normal_stride);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
new file mode 100644
index 00000000000..bb27cb6a31e
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -0,0 +1,2432 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/subdiv_mesh.c
+ * \ingroup bke
+ */
+
+#include "BKE_subdiv.h"
+
+#include "atomic_ops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_key_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_bitmap.h"
+#include "BLI_math_vector.h"
+#include "BLI_task.h"
+
+#include "BKE_mesh.h"
+#include "BKE_key.h"
+
+#include "MEM_guardedalloc.h"
+
+/* =============================================================================
+ * General helpers.
+ */
+
+/* Number of ptex faces for a given polygon. */
+BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly)
+{
+ return (poly->totloop == 4) ? 1 : poly->totloop;
+}
+
+BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
+{
+ return 2 * (resolution - 1) * resolution;
+}
+
+BLI_INLINE int num_inner_edges_per_ptex_face_get(const int resolution)
+{
+ if (resolution < 2) {
+ return 0;
+ }
+ return (resolution - 2) * resolution +
+ (resolution - 1) * (resolution - 1);
+}
+
+/* Number of subdivision polygons per ptex face. */
+BLI_INLINE int num_polys_per_ptex_get(const int resolution)
+{
+ return (resolution - 1) * (resolution - 1);
+}
+
+/* Subdivision resolution per given polygon's ptex faces. */
+BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution)
+{
+ return (poly->totloop == 4) ? (resolution)
+ : ((resolution >> 1) + 1);
+}
+
+/* =============================================================================
+ * Mesh subdivision context.
+ */
+
+typedef struct SubdivMeshContext {
+ const Mesh *coarse_mesh;
+ Subdiv *subdiv;
+ Mesh *subdiv_mesh;
+ const SubdivToMeshSettings *settings;
+ /* Cached custom data arrays for fastter access. */
+ int *vert_origindex;
+ int *edge_origindex;
+ int *loop_origindex;
+ int *poly_origindex;
+ /* UV layers interpolation. */
+ int num_uv_layers;
+ MLoopUV *uv_layers[MAX_MTFACE];
+ /* Counters of geometry in subdivided mesh, initialized as a part of
+ * offsets calculation.
+ */
+ int num_subdiv_vertices;
+ int num_subdiv_edges;
+ int num_subdiv_loops;
+ int num_subdiv_polygons;
+ /* Offsets of various geometry in the subdivision mesh arrays. */
+ int vertices_corner_offset;
+ int vertices_edge_offset;
+ int vertices_inner_offset;
+ int edge_boundary_offset;
+ int edge_inner_offset;
+ /* Indexed by coarse polygon index, indicates offset in subdivided mesh
+ * vertices, edges and polygons arrays, where first element of the poly
+ * begins.
+ */
+ int *subdiv_vertex_offset;
+ int *subdiv_edge_offset;
+ int *subdiv_polygon_offset;
+ /* Indexed by base face index, element indicates total number of ptex faces
+ * created for preceding base faces.
+ */
+ int *face_ptex_offset;
+ /* Bitmap indicating whether vertex was used already or not.
+ * - During patch evaluation indicates whether coarse vertex was already
+ * evaluated and its position on limit is already known.
+ */
+ BLI_bitmap *coarse_vertices_used_map;
+ /* Bitmap indicating whether edge was used already or not. This includes:
+ * - During context initialization it indicates whether subdivided verticies
+ * for corresponding edge were already calculated or not.
+ * - During patch evaluation it indicates whether vertices along this edge
+ * were already evaluated.
+ */
+ BLI_bitmap *coarse_edges_used_map;
+} SubdivMeshContext;
+
+static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
+{
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ ctx->num_uv_layers =
+ CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
+ for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) {
+ ctx->uv_layers[layer_index] = CustomData_get_layer_n(
+ &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
+ }
+}
+
+static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
+{
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ /* Pointers to original indices layers. */
+ ctx->vert_origindex = CustomData_get_layer(
+ &subdiv_mesh->vdata, CD_ORIGINDEX);
+ ctx->edge_origindex = CustomData_get_layer(
+ &subdiv_mesh->edata, CD_ORIGINDEX);
+ ctx->loop_origindex = CustomData_get_layer(
+ &subdiv_mesh->ldata, CD_ORIGINDEX);
+ ctx->poly_origindex = CustomData_get_layer(
+ &subdiv_mesh->pdata, CD_ORIGINDEX);
+ /* UV layers interpolation. */
+ subdiv_mesh_ctx_cache_uv_layers(ctx);
+}
+
+/* NOTE: Expects edge map to be zeroed. */
+static void subdiv_mesh_ctx_count(SubdivMeshContext *ctx)
+{
+ /* Reset counters. */
+ ctx->num_subdiv_vertices = 0;
+ ctx->num_subdiv_edges = 0;
+ ctx->num_subdiv_loops = 0;
+ ctx->num_subdiv_polygons = 0;
+ /* Static geometry counters. */
+ const int resolution = ctx->settings->resolution;
+ const int no_quad_patch_resolution = ((resolution >> 1) + 1);
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_inner_vertices_per_quad = (resolution - 2) * (resolution - 2);
+ const int num_inner_vertices_per_noquad_patch =
+ (no_quad_patch_resolution - 2) * (no_quad_patch_resolution - 2);
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ ctx->num_subdiv_vertices = coarse_mesh->totvert;
+ ctx->num_subdiv_edges =
+ coarse_mesh->totedge * (num_subdiv_vertices_per_coarse_edge + 1);
+ /* Calculate extra vertices and edges createdd by non-loose geometry. */
+ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ const int num_ptex_faces_per_poly =
+ num_ptex_faces_per_poly_get(coarse_poly);
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
+ const bool is_edge_used =
+ BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, loop->e);
+ /* Edges which aren't counted yet. */
+ if (!is_edge_used) {
+ BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
+ ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
+ }
+ }
+ /* Inner verticies of polygon. */
+ if (num_ptex_faces_per_poly == 1) {
+ ctx->num_subdiv_vertices += num_inner_vertices_per_quad;
+ ctx->num_subdiv_edges +=
+ num_edges_per_ptex_face_get(resolution - 2) +
+ 4 * num_subdiv_vertices_per_coarse_edge;
+ ctx->num_subdiv_polygons += num_polys_per_ptex_get(resolution);
+ }
+ else {
+ ctx->num_subdiv_vertices +=
+ 1 +
+ num_ptex_faces_per_poly * (no_quad_patch_resolution - 2) +
+ num_ptex_faces_per_poly * num_inner_vertices_per_noquad_patch;
+ ctx->num_subdiv_edges +=
+ num_ptex_faces_per_poly *
+ (num_inner_edges_per_ptex_face_get(
+ no_quad_patch_resolution - 1) +
+ (no_quad_patch_resolution - 2) +
+ num_subdiv_vertices_per_coarse_edge);
+ if (no_quad_patch_resolution >= 3) {
+ ctx->num_subdiv_edges += coarse_poly->totloop;
+ }
+ ctx->num_subdiv_polygons +=
+ num_ptex_faces_per_poly *
+ num_polys_per_ptex_get(no_quad_patch_resolution);
+ }
+ }
+ /* Calculate extra edges createdd by loose edges. */
+ for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
+ if (!BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
+ ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
+ }
+ }
+ ctx->num_subdiv_loops = ctx->num_subdiv_polygons * 4;
+}
+
+static void subdiv_mesh_ctx_init_offsets(SubdivMeshContext *ctx)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const int resolution = ctx->settings->resolution;
+ const int resolution_2 = resolution - 2;
+ const int resolution_2_squared = resolution_2 * resolution_2;
+ const int no_quad_patch_resolution = ((resolution >> 1) + 1);
+ const int num_irregular_vertices_per_patch =
+ (no_quad_patch_resolution - 2) * (no_quad_patch_resolution - 1);
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_subdiv_edges_per_coarse_edge = resolution - 1;
+ /* Constant offsets in arrays. */
+ ctx->vertices_corner_offset = 0;
+ ctx->vertices_edge_offset = coarse_mesh->totvert;
+ ctx->vertices_inner_offset =
+ ctx->vertices_edge_offset +
+ coarse_mesh->totedge * num_subdiv_vertices_per_coarse_edge;
+ ctx->edge_boundary_offset = 0;
+ ctx->edge_inner_offset =
+ ctx->edge_boundary_offset +
+ coarse_mesh->totedge * num_subdiv_edges_per_coarse_edge;
+ /* "Indexed" offsets. */
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ int vertex_offset = 0;
+ int edge_offset = 0;
+ int polygon_offset = 0;
+ int face_ptex_offset = 0;
+ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ const int num_ptex_faces_per_poly =
+ num_ptex_faces_per_poly_get(coarse_poly);
+ ctx->face_ptex_offset[poly_index] = face_ptex_offset;
+ ctx->subdiv_vertex_offset[poly_index] = vertex_offset;
+ ctx->subdiv_edge_offset[poly_index] = edge_offset;
+ ctx->subdiv_polygon_offset[poly_index] = polygon_offset;
+ face_ptex_offset += num_ptex_faces_per_poly;
+ if (num_ptex_faces_per_poly == 1) {
+ vertex_offset += resolution_2_squared;
+ edge_offset += num_edges_per_ptex_face_get(resolution - 2) +
+ 4 * num_subdiv_vertices_per_coarse_edge;
+ polygon_offset += num_polys_per_ptex_get(resolution);
+ }
+ else {
+ vertex_offset +=
+ 1 +
+ num_ptex_faces_per_poly * num_irregular_vertices_per_patch;
+ edge_offset +=
+ num_ptex_faces_per_poly *
+ (num_inner_edges_per_ptex_face_get(
+ no_quad_patch_resolution - 1) +
+ (no_quad_patch_resolution - 2) +
+ num_subdiv_vertices_per_coarse_edge);
+ if (no_quad_patch_resolution >= 3) {
+ edge_offset += coarse_poly->totloop;
+ }
+ polygon_offset +=
+ num_ptex_faces_per_poly *
+ num_polys_per_ptex_get(no_quad_patch_resolution);
+ }
+ }
+}
+
+static void subdiv_mesh_ctx_init(SubdivMeshContext *ctx)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ /* Allocate maps and offsets. */
+ ctx->coarse_vertices_used_map =
+ BLI_BITMAP_NEW(coarse_mesh->totvert, "vertices used map");
+ ctx->coarse_edges_used_map =
+ BLI_BITMAP_NEW(coarse_mesh->totedge, "edges used map");
+ ctx->subdiv_vertex_offset = MEM_malloc_arrayN(
+ coarse_mesh->totpoly,
+ sizeof(*ctx->subdiv_vertex_offset),
+ "vertex_offset");
+ ctx->subdiv_edge_offset = MEM_malloc_arrayN(
+ coarse_mesh->totpoly,
+ sizeof(*ctx->subdiv_edge_offset),
+ "subdiv_edge_offset");
+ ctx->subdiv_polygon_offset = MEM_malloc_arrayN(
+ coarse_mesh->totpoly,
+ sizeof(*ctx->subdiv_polygon_offset),
+ "subdiv_edge_offset");
+ ctx->face_ptex_offset = MEM_malloc_arrayN(coarse_mesh->totpoly,
+ sizeof(*ctx->face_ptex_offset),
+ "face_ptex_offset");
+ /* Initialize all offsets. */
+ subdiv_mesh_ctx_init_offsets(ctx);
+ /* Calculate number of geometry in the result subdivision mesh. */
+ subdiv_mesh_ctx_count(ctx);
+ /* Re-set maps which were used at this step. */
+ BLI_BITMAP_SET_ALL(ctx->coarse_edges_used_map, false, coarse_mesh->totedge);
+}
+
+static void subdiv_mesh_ctx_init_result(SubdivMeshContext *ctx)
+{
+ subdiv_mesh_ctx_cache_custom_data_layers(ctx);
+}
+
+static void subdiv_mesh_ctx_free(SubdivMeshContext *ctx)
+{
+ MEM_freeN(ctx->coarse_vertices_used_map);
+ MEM_freeN(ctx->coarse_edges_used_map);
+ MEM_freeN(ctx->subdiv_vertex_offset);
+ MEM_freeN(ctx->subdiv_edge_offset);
+ MEM_freeN(ctx->subdiv_polygon_offset);
+ MEM_freeN(ctx->face_ptex_offset);
+}
+
+/* =============================================================================
+ * Loop custom data copy helpers.
+ */
+
+typedef struct LoopsOfPtex {
+ /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
+ const MLoop *first_loop;
+ /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
+ const MLoop *last_loop;
+ /* For quad coarse faces only. */
+ const MLoop *second_loop;
+ const MLoop *third_loop;
+} LoopsOfPtex;
+
+static void loops_of_ptex_get(
+ const SubdivMeshContext *ctx,
+ LoopsOfPtex *loops_of_ptex,
+ const MPoly *coarse_poly,
+ const int ptex_of_poly_index)
+{
+ const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
+ const int first_ptex_loop_index =
+ coarse_poly->loopstart + ptex_of_poly_index;
+ /* Loop which look in the (opposite) V direction of the current
+ * ptex face.
+ *
+ * TOOD(sergey): Get rid of using module on every iteration.
+ */
+ const int last_ptex_loop_index =
+ coarse_poly->loopstart +
+ (ptex_of_poly_index + coarse_poly->totloop - 1) %
+ coarse_poly->totloop;
+ loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
+ loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
+ if (coarse_poly->totloop == 4) {
+ loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
+ loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
+ }
+ else {
+ loops_of_ptex->second_loop = NULL;
+ loops_of_ptex->third_loop = NULL;
+ }
+}
+
+/* =============================================================================
+ * Vertex custom data interpolation helpers.
+ */
+
+/* TODO(sergey): Somehow de-duplicate with loops storage, without too much
+ * exception cases all over the code.
+ */
+
+typedef struct VerticesForInterpolation {
+ /* This field points to a vertex data which is to be used for interpolation.
+ * The idea is to avoid unnecessary allocations for regular faces, where
+ * we can simply
+ */
+ const CustomData *vertex_data;
+ /* Vertices data calculated for ptex corners. There are always 4 elements
+ * in this custom data, aligned the following way:
+ *
+ * index 0 -> uv (0, 0)
+ * index 1 -> uv (0, 1)
+ * index 2 -> uv (1, 1)
+ * index 3 -> uv (1, 0)
+ *
+ * Is allocated for non-regular faces (triangles and n-gons).
+ */
+ CustomData vertex_data_storage;
+ bool vertex_data_storage_allocated;
+ /* Infices within vertex_data to interpolate for. The indices are aligned
+ * with uv coordinates in a similar way as indices in loop_data_storage.
+ */
+ int vertex_indices[4];
+} VerticesForInterpolation;
+
+static void vertex_interpolation_init(
+ const SubdivMeshContext *ctx,
+ VerticesForInterpolation *vertex_interpolation,
+ const MPoly *coarse_poly)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ if (coarse_poly->totloop == 4) {
+ vertex_interpolation->vertex_data = &coarse_mesh->vdata;
+ vertex_interpolation->vertex_indices[0] =
+ coarse_mloop[coarse_poly->loopstart + 0].v;
+ vertex_interpolation->vertex_indices[1] =
+ coarse_mloop[coarse_poly->loopstart + 1].v;
+ vertex_interpolation->vertex_indices[2] =
+ coarse_mloop[coarse_poly->loopstart + 2].v;
+ vertex_interpolation->vertex_indices[3] =
+ coarse_mloop[coarse_poly->loopstart + 3].v;
+ vertex_interpolation->vertex_data_storage_allocated = false;
+ }
+ else {
+ vertex_interpolation->vertex_data =
+ &vertex_interpolation->vertex_data_storage;
+ /* Allocate storage for loops corresponding to ptex corners. */
+ CustomData_copy(&ctx->coarse_mesh->vdata,
+ &vertex_interpolation->vertex_data_storage,
+ CD_MASK_EVERYTHING,
+ CD_CALLOC,
+ 4);
+ /* Initialize indices. */
+ vertex_interpolation->vertex_indices[0] = 0;
+ vertex_interpolation->vertex_indices[1] = 1;
+ vertex_interpolation->vertex_indices[2] = 2;
+ vertex_interpolation->vertex_indices[3] = 3;
+ vertex_interpolation->vertex_data_storage_allocated = true;
+ /* Interpolate center of poly right away, it stays unchanged for all
+ * ptex faces.
+ */
+ const float weight = 1.0f / (float)coarse_poly->totloop;
+ float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
+ int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
+ for (int i = 0; i < coarse_poly->totloop; ++i) {
+ weights[i] = weight;
+ indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
+ }
+ CustomData_interp(&coarse_mesh->vdata,
+ &vertex_interpolation->vertex_data_storage,
+ indices,
+ weights, NULL,
+ coarse_poly->totloop,
+ 2);
+ }
+}
+
+static void vertex_interpolation_from_ptex(
+ const SubdivMeshContext *ctx,
+ VerticesForInterpolation *vertex_interpolation,
+ const MPoly *coarse_poly,
+ const int ptex_of_poly_index)
+{
+ if (coarse_poly->totloop == 4) {
+ /* Nothing to do, all indices and data is already assigned. */
+ }
+ else {
+ const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ LoopsOfPtex loops_of_ptex;
+ loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, ptex_of_poly_index);
+ /* Ptex face corner corresponds to a poly loop with same index. */
+ CustomData_copy_data(
+ vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ coarse_mloop[coarse_poly->loopstart + ptex_of_poly_index].v,
+ 0,
+ 1);
+ /* Interpolate remaining ptex face corners, which hits loops
+ * middle points.
+ *
+ * TODO(sergey): Re-use one of interpolation results from previous
+ * iteration.
+ */
+ const float weights[2] = {0.5f, 0.5f};
+ const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
+ const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
+ const int first_indices[2] = {
+ coarse_mloop[first_loop_index].v,
+ coarse_mloop[coarse_poly->loopstart +
+ (first_loop_index - coarse_poly->loopstart + 1) %
+ coarse_poly->totloop].v};
+ const int last_indices[2] = {coarse_mloop[first_loop_index].v,
+ coarse_mloop[last_loop_index].v};
+ CustomData_interp(vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ first_indices,
+ weights, NULL,
+ 2,
+ 1);
+ CustomData_interp(vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ last_indices,
+ weights, NULL,
+ 2,
+ 3);
+ }
+}
+
+static void vertex_interpolation_end(
+ VerticesForInterpolation *vertex_interpolation)
+{
+ if (vertex_interpolation->vertex_data_storage_allocated) {
+ CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
+ }
+}
+
+/* =============================================================================
+ * Loop custom data interpolation helpers.
+ */
+
+typedef struct LoopsForInterpolation {
+ /* This field points to a loop data which is to be used for interpolation.
+ * The idea is to avoid unnecessary allocations for regular faces, where
+ * we can simply
+ */
+ const CustomData *loop_data;
+ /* Loops data calculated for ptex corners. There are always 4 elements
+ * in this custom data, aligned the following way:
+ *
+ * index 0 -> uv (0, 0)
+ * index 1 -> uv (0, 1)
+ * index 2 -> uv (1, 1)
+ * index 3 -> uv (1, 0)
+ *
+ * Is allocated for non-regular faces (triangles and n-gons).
+ */
+ CustomData loop_data_storage;
+ bool loop_data_storage_allocated;
+ /* Infices within loop_data to interpolate for. The indices are aligned with
+ * uv coordinates in a similar way as indices in loop_data_storage.
+ */
+ int loop_indices[4];
+} LoopsForInterpolation;
+
+static void loop_interpolation_init(
+ const SubdivMeshContext *ctx,
+ LoopsForInterpolation *loop_interpolation,
+ const MPoly *coarse_poly)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ if (coarse_poly->totloop == 4) {
+ loop_interpolation->loop_data = &coarse_mesh->ldata;
+ loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
+ loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
+ loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
+ loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
+ loop_interpolation->loop_data_storage_allocated = false;
+ }
+ else {
+ loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
+ /* Allocate storage for loops corresponding to ptex corners. */
+ CustomData_copy(&ctx->coarse_mesh->ldata,
+ &loop_interpolation->loop_data_storage,
+ CD_MASK_EVERYTHING,
+ CD_CALLOC,
+ 4);
+ /* Initialize indices. */
+ loop_interpolation->loop_indices[0] = 0;
+ loop_interpolation->loop_indices[1] = 1;
+ loop_interpolation->loop_indices[2] = 2;
+ loop_interpolation->loop_indices[3] = 3;
+ loop_interpolation->loop_data_storage_allocated = true;
+ /* Interpolate center of poly right away, it stays unchanged for all
+ * ptex faces.
+ */
+ const float weight = 1.0f / (float)coarse_poly->totloop;
+ float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
+ int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
+ for (int i = 0; i < coarse_poly->totloop; ++i) {
+ weights[i] = weight;
+ indices[i] = coarse_poly->loopstart + i;
+ }
+ CustomData_interp(&coarse_mesh->ldata,
+ &loop_interpolation->loop_data_storage,
+ indices,
+ weights, NULL,
+ coarse_poly->totloop,
+ 2);
+ }
+}
+
+static void loop_interpolation_from_ptex(
+ const SubdivMeshContext *ctx,
+ LoopsForInterpolation *loop_interpolation,
+ const MPoly *coarse_poly,
+ const int ptex_face_index)
+{
+ if (coarse_poly->totloop == 4) {
+ /* Nothing to do, all indices and data is already assigned. */
+ }
+ else {
+ const CustomData *loop_data = &ctx->coarse_mesh->ldata;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ LoopsOfPtex loops_of_ptex;
+ loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, ptex_face_index);
+ /* Ptex face corner corresponds to a poly loop with same index. */
+ CustomData_copy_data(loop_data,
+ &loop_interpolation->loop_data_storage,
+ coarse_poly->loopstart + ptex_face_index,
+ 0,
+ 1);
+ /* Interpolate remaining ptex face corners, which hits loops
+ * middle points.
+ *
+ * TODO(sergey): Re-use one of interpolation results from previous
+ * iteration.
+ */
+ const float weights[2] = {0.5f, 0.5f};
+ const int first_indices[2] = {
+ loops_of_ptex.first_loop - coarse_mloop,
+ (loops_of_ptex.first_loop + 1 - coarse_mloop) %
+ coarse_poly->totloop};
+ const int last_indices[2] = {
+ loops_of_ptex.last_loop - coarse_mloop,
+ loops_of_ptex.first_loop - coarse_mloop};
+ CustomData_interp(loop_data,
+ &loop_interpolation->loop_data_storage,
+ first_indices,
+ weights, NULL,
+ 2,
+ 1);
+ CustomData_interp(loop_data,
+ &loop_interpolation->loop_data_storage,
+ last_indices,
+ weights, NULL,
+ 2,
+ 3);
+ }
+}
+
+static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
+{
+ if (loop_interpolation->loop_data_storage_allocated) {
+ CustomData_free(&loop_interpolation->loop_data_storage, 4);
+ }
+}
+
+/* =============================================================================
+ * Vertex subdivision process.
+ */
+
+/* Custom data interpolation helpers. */
+
+static void subdiv_vertex_data_copy(
+ const SubdivMeshContext *ctx,
+ const MVert *coarse_vertex,
+ MVert *subdiv_vertex)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
+ const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
+ CustomData_copy_data(&coarse_mesh->vdata,
+ &ctx->subdiv_mesh->vdata,
+ coarse_vertex_index,
+ subdiv_vertex_index,
+ 1);
+}
+
+static void subdiv_vertex_data_interpolate(
+ const SubdivMeshContext *ctx,
+ MVert *subdiv_vertex,
+ const VerticesForInterpolation *vertex_interpolation,
+ const float u, const float v)
+{
+ const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
+ const float weights[4] = {(1.0f - u) * (1.0f - v),
+ u * (1.0f - v),
+ u * v,
+ (1.0f - u) * v};
+ CustomData_interp(vertex_interpolation->vertex_data,
+ &ctx->subdiv_mesh->vdata,
+ vertex_interpolation->vertex_indices,
+ weights, NULL,
+ 4,
+ subdiv_vertex_index);
+ if (ctx->vert_origindex != NULL) {
+ ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
+ }
+}
+
+/* Evaluation of corner vertices. They are coming from coarse vertices. */
+
+static void subdiv_evaluate_corner_vertices_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const float weights[4][2] = {{0.0f, 0.0f},
+ {1.0f, 0.0f},
+ {1.0f, 1.0f},
+ {0.0f, 1.0f}};
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map,
+ coarse_loop->v))
+ {
+ continue;
+ }
+ const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_loop->v];
+ subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ weights[corner][0], weights[corner][1],
+ subdiv_vert->co, subdiv_vert->no);
+ }
+}
+
+static void subdiv_evaluate_corner_vertices_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, ptex_face_index++)
+ {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map,
+ coarse_loop->v))
+ {
+ continue;
+ }
+ const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_loop->v];
+ subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ 0.0f, 0.0f,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+}
+
+static void subdiv_evaluate_corner_vertices(SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ if (coarse_poly->totloop == 4) {
+ subdiv_evaluate_corner_vertices_regular(ctx, coarse_poly);
+ }
+ else {
+ subdiv_evaluate_corner_vertices_special(ctx, coarse_poly);
+ }
+}
+
+/* Evaluation of edge vertices. They are coming from coarse edges. */
+
+static void subdiv_evaluate_edge_vertices_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ const int resolution = ctx->settings->resolution;
+ const int resolution_1 = resolution - 1;
+ const float inv_resolution_1 = 1.0f / (float)resolution_1;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map,
+ coarse_loop->e))
+ {
+ continue;
+ }
+ vertex_interpolation_from_ptex(ctx,
+ vertex_interpolation,
+ coarse_poly,
+ corner);
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
+ for (int vertex_index = 0;
+ vertex_index < num_subdiv_vertices_per_coarse_edge;
+ vertex_index++, subdiv_vert++)
+ {
+ float fac = (vertex_index + 1) * inv_resolution_1;
+ if (flip) {
+ fac = 1.0f - fac;
+ }
+ if (corner >= 2) {
+ fac = 1.0f - fac;
+ }
+ float u, v;
+ if ((corner & 1) == 0) {
+ u = fac;
+ v = (corner == 2) ? 1.0f : 0.0f;
+ }
+ else {
+ u = (corner == 1) ? 1.0f : 0.0f;
+ v = fac;
+ }
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ u, v);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+ }
+}
+
+static void subdiv_evaluate_edge_vertices_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ const int resolution = ctx->settings->resolution;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
+ const float inv_ptex_resolution_1 =
+ 1.0f / (float)(num_vertices_per_ptex_edge - 1);
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
+ int ptex_face_index = ptex_face_start_index;
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, ptex_face_index++)
+ {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map,
+ coarse_loop->e))
+ {
+ continue;
+ }
+ vertex_interpolation_from_ptex(ctx,
+ vertex_interpolation,
+ coarse_poly,
+ corner);
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
+ int veretx_delta = 1;
+ if (flip) {
+ subdiv_vert += num_subdiv_vertices_per_coarse_edge - 1;
+ veretx_delta = -1;
+ }
+ for (int vertex_index = 1;
+ vertex_index < num_vertices_per_ptex_edge;
+ vertex_index++, subdiv_vert += veretx_delta)
+ {
+ float u = vertex_index * inv_ptex_resolution_1;
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ u, 0.0f);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ u, 0.0f,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+ const int next_ptex_face_index =
+ ptex_face_start_index + (corner + 1) % coarse_poly->totloop;
+ for (int vertex_index = 1;
+ vertex_index < num_vertices_per_ptex_edge - 1;
+ vertex_index++, subdiv_vert += veretx_delta)
+ {
+ float v = 1.0f - vertex_index * inv_ptex_resolution_1;
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ 0.0f, v);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ next_ptex_face_index,
+ 0.0f, v,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+ }
+}
+
+static void subdiv_evaluate_edge_vertices(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ if (coarse_poly->totloop == 4) {
+ subdiv_evaluate_edge_vertices_regular(
+ ctx, coarse_poly, vertex_interpolation);
+ }
+ else {
+ subdiv_evaluate_edge_vertices_special(
+ ctx, coarse_poly, vertex_interpolation);
+ }
+}
+
+/* Evaluation of inner vertices, they are coming from ptex patches. */
+
+static void subdiv_evaluate_inner_vertices_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ const int resolution = ctx->settings->resolution;
+ const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index];
+ MVert *subdiv_vert =
+ &subdiv_mvert[ctx->vertices_inner_offset + start_vertex_index];
+ vertex_interpolation_from_ptex(ctx,
+ vertex_interpolation,
+ coarse_poly,
+ 0);
+ for (int y = 1; y < resolution - 1; y++) {
+ const float v = y * inv_resolution_1;
+ for (int x = 1; x < resolution - 1; x++, subdiv_vert++) {
+ const float u = x * inv_resolution_1;
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ u, v);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+ }
+}
+
+static void subdiv_evaluate_inner_vertices_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ const int resolution = ctx->settings->resolution;
+ const int ptex_face_resolution = ptex_face_resolution_get(
+ coarse_poly, resolution);
+ const float inv_ptex_face_resolution_1 =
+ 1.0f / (float)(ptex_face_resolution - 1);
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index];
+ MVert *subdiv_vert =
+ &subdiv_mvert[ctx->vertices_inner_offset + start_vertex_index];
+ vertex_interpolation_from_ptex(ctx,
+ vertex_interpolation,
+ coarse_poly,
+ 0);
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ 1.0f, 1.0f);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ 1.0f, 1.0f,
+ subdiv_vert->co, subdiv_vert->no);
+ subdiv_vert++;
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, ptex_face_index++)
+ {
+ if (corner != 0) {
+ vertex_interpolation_from_ptex(ctx,
+ vertex_interpolation,
+ coarse_poly,
+ corner);
+ }
+ for (int y = 1; y < ptex_face_resolution - 1; y++) {
+ const float v = y * inv_ptex_face_resolution_1;
+ for (int x = 1; x < ptex_face_resolution; x++, subdiv_vert++) {
+ const float u = x * inv_ptex_face_resolution_1;
+ subdiv_vertex_data_interpolate(ctx,
+ subdiv_vert,
+ vertex_interpolation,
+ u, v);
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv,
+ ptex_face_index,
+ u, v,
+ subdiv_vert->co, subdiv_vert->no);
+ }
+ }
+ }
+}
+
+static void subdiv_evaluate_inner_vertices(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly,
+ VerticesForInterpolation *vertex_interpolation)
+{
+ if (coarse_poly->totloop == 4) {
+ subdiv_evaluate_inner_vertices_regular(
+ ctx, coarse_poly, vertex_interpolation);
+ }
+ else {
+ subdiv_evaluate_inner_vertices_special(
+ ctx, coarse_poly, vertex_interpolation);
+ }
+}
+
+/* Evaluate all vertices which are emitted from given coarse polygon. */
+static void subdiv_evaluate_vertices(SubdivMeshContext *ctx,
+ const int poly_index)
+{
+ /* Base/coarse mesh information. */
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ /* Initialize vertex interpolation, it is reused by corner vertices, coarse
+ * edges and patch evaluation.
+ */
+ VerticesForInterpolation vertex_interpolation;
+ vertex_interpolation_init(ctx, &vertex_interpolation, coarse_poly);
+ (void) vertex_interpolation;
+ subdiv_evaluate_corner_vertices(ctx, coarse_poly);
+ subdiv_evaluate_edge_vertices(ctx, coarse_poly, &vertex_interpolation);
+ subdiv_evaluate_inner_vertices(ctx, coarse_poly, &vertex_interpolation);
+ vertex_interpolation_end(&vertex_interpolation);
+}
+
+/* =============================================================================
+ * Edge subdivision process.
+ */
+
+static void subdiv_copy_edge_data(
+ SubdivMeshContext *ctx,
+ MEdge *subdiv_edge,
+ const MEdge *coarse_edge)
+{
+ const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
+ if (coarse_edge == NULL) {
+ subdiv_edge->crease = 0;
+ subdiv_edge->bweight = 0;
+ subdiv_edge->flag = 0;
+ if (ctx->edge_origindex != NULL) {
+ ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
+ }
+ return;
+ }
+ const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
+ CustomData_copy_data(&ctx->coarse_mesh->edata,
+ &ctx->subdiv_mesh->edata,
+ coarse_edge_index,
+ subdiv_edge_index,
+ 1);
+}
+
+static MEdge *subdiv_create_edges_row(SubdivMeshContext *ctx,
+ MEdge *subdiv_edge,
+ const MEdge *coarse_edge,
+ const int start_vertex_index,
+ const int num_edges_per_row)
+{
+ int vertex_index = start_vertex_index;
+ for (int edge_index = 0;
+ edge_index < num_edges_per_row - 1;
+ edge_index++, subdiv_edge++)
+ {
+ subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
+ subdiv_edge->v1 = vertex_index;
+ subdiv_edge->v2 = vertex_index + 1;
+ vertex_index += 1;
+ }
+ return subdiv_edge;
+}
+
+static MEdge *subdiv_create_edges_column(SubdivMeshContext *ctx,
+ MEdge *subdiv_edge,
+ const MEdge *coarse_start_edge,
+ const MEdge *coarse_end_edge,
+ const int start_vertex_index,
+ const int num_edges_per_row)
+{
+ int vertex_index = start_vertex_index;
+ for (int edge_index = 0;
+ edge_index < num_edges_per_row;
+ edge_index++, subdiv_edge++)
+ {
+ const MEdge *coarse_edge = NULL;
+ if (edge_index == 0) {
+ coarse_edge = coarse_start_edge;
+ }
+ else if (edge_index == num_edges_per_row - 1) {
+ coarse_edge = coarse_end_edge;
+ }
+ subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
+ subdiv_edge->v1 = vertex_index;
+ subdiv_edge->v2 = vertex_index + num_edges_per_row;
+ vertex_index += 1;
+ }
+ return subdiv_edge;
+}
+
+/* Create edges between inner vertices of patch, and also edges to the
+ * boundary.
+ */
+
+/* Consider a subdivision of base face at level 1:
+ *
+ * y
+ * ^
+ * | (6) ---- (7) ---- (8)
+ * | | | |
+ * | (3) ---- (4) ---- (5)
+ * | | | |
+ * | (0) ---- (1) ---- (2)
+ * o---------------------------> x
+ *
+ * This is illustrate which parts of geometry is created by code below.
+ */
+
+static void subdiv_create_edges_all_patches_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int poly_index = coarse_poly - coarse_mpoly;
+ const int resolution = ctx->settings->resolution;
+ const int start_vertex_index =
+ ctx->vertices_inner_offset +
+ ctx->subdiv_vertex_offset[poly_index];
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MEdge *subdiv_medge = subdiv_mesh->medge;
+ MEdge *subdiv_edge = &subdiv_medge[
+ ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]];
+ /* Create bottom row of edges (0-1, 1-2). */
+ subdiv_edge = subdiv_create_edges_row(
+ ctx,
+ subdiv_edge,
+ NULL,
+ start_vertex_index,
+ resolution - 2);
+ /* Create remaining edges. */
+ for (int row = 0; row < resolution - 3; row++) {
+ const int start_row_vertex_index =
+ start_vertex_index + row * (resolution - 2);
+ /* Create vertical columns.
+ *
+ * At first iteration it will be edges (0-3. 1-4, 2-5), then it
+ * will be (3-6, 4-7, 5-8) and so on.
+ */
+ subdiv_edge = subdiv_create_edges_column(
+ ctx,
+ subdiv_edge,
+ NULL,
+ NULL,
+ start_row_vertex_index,
+ resolution - 2);
+ /* Create horizontal edge row.
+ *
+ * At first iteration it will be edges (3-4, 4-5), then it will be
+ * (6-7, 7-8) and so on.
+ */
+ subdiv_edge = subdiv_create_edges_row(
+ ctx,
+ subdiv_edge,
+ NULL,
+ start_row_vertex_index + resolution - 2,
+ resolution - 2);
+ }
+ /* Connect inner part of patch to boundary. */
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const int start_edge_vertex = ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ int side_start_index = start_vertex_index;
+ int side_stride = 0;
+ /* Calculate starting veretx of corresponding inner part of ptex. */
+ if (corner == 0) {
+ side_stride = 1;
+ }
+ else if (corner == 1) {
+ side_start_index += resolution - 3;
+ side_stride = resolution - 2;
+ }
+ else if (corner == 2) {
+ side_start_index += num_subdiv_vertices_per_coarse_edge *
+ num_subdiv_vertices_per_coarse_edge - 1;
+ side_stride = -1;
+ }
+ else if (corner == 3) {
+ side_start_index += num_subdiv_vertices_per_coarse_edge *
+ (num_subdiv_vertices_per_coarse_edge - 1);
+ side_stride = -(resolution - 2);
+ }
+ for (int i = 0; i < resolution - 2; i++, subdiv_edge++) {
+ subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
+ if (flip) {
+ subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
+ }
+ else {
+ subdiv_edge->v1 = start_edge_vertex + i;
+ }
+ subdiv_edge->v2 = side_start_index + side_stride * i;
+ }
+ }
+}
+
+static void subdiv_create_edges_all_patches_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int poly_index = coarse_poly - coarse_mpoly;
+ const int resolution = ctx->settings->resolution;
+ const int ptex_face_resolution =
+ ptex_face_resolution_get(coarse_poly, resolution);
+ const int ptex_face_inner_resolution = ptex_face_resolution - 2;
+ const int num_inner_vertices_per_ptex =
+ (ptex_face_resolution - 1) * (ptex_face_resolution - 2);
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int center_vertex_index =
+ ctx->vertices_inner_offset +
+ ctx->subdiv_vertex_offset[poly_index];
+ const int start_vertex_index = center_vertex_index + 1;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MEdge *subdiv_medge = subdiv_mesh->medge;
+ MEdge *subdiv_edge = &subdiv_medge[
+ ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]];
+ /* Create inner ptex edges. */
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const int start_ptex_face_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex;
+ /* Similar steps to regular patch case. */
+ subdiv_edge = subdiv_create_edges_row(
+ ctx,
+ subdiv_edge,
+ NULL,
+ start_ptex_face_vertex_index,
+ ptex_face_inner_resolution + 1);
+ for (int row = 0; row < ptex_face_inner_resolution - 1; row++) {
+ const int start_row_vertex_index =
+ start_ptex_face_vertex_index +
+ row * (ptex_face_inner_resolution + 1);
+ subdiv_edge = subdiv_create_edges_column(
+ ctx,
+ subdiv_edge,
+ NULL,
+ NULL,
+ start_row_vertex_index,
+ ptex_face_inner_resolution + 1);
+ subdiv_edge = subdiv_create_edges_row(
+ ctx,
+ subdiv_edge,
+ NULL,
+ start_row_vertex_index + ptex_face_inner_resolution + 1,
+ ptex_face_inner_resolution + 1);
+ }
+ }
+ /* Create connections between ptex faces. */
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const int next_corner = (corner + 1) % coarse_poly->totloop;
+ int current_patch_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex +
+ ptex_face_inner_resolution;
+ int next_path_vertex_index =
+ start_vertex_index + next_corner * num_inner_vertices_per_ptex +
+ num_inner_vertices_per_ptex - ptex_face_resolution + 1;
+ for (int row = 0;
+ row < ptex_face_inner_resolution;
+ row++, subdiv_edge++)
+ {
+ subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
+ subdiv_edge->v1 = current_patch_vertex_index;
+ subdiv_edge->v2 = next_path_vertex_index;
+ current_patch_vertex_index += ptex_face_inner_resolution + 1;
+ next_path_vertex_index += 1;
+ }
+ }
+ /* Create edges from center. */
+ if (ptex_face_resolution >= 3) {
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, subdiv_edge++)
+ {
+ const int current_patch_end_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex +
+ num_inner_vertices_per_ptex - 1;
+ subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
+ subdiv_edge->v1 = center_vertex_index;
+ subdiv_edge->v2 = current_patch_end_vertex_index;
+ }
+ }
+ /* Connect inner path of patch to boundary. */
+ const MLoop *prev_coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ {
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const int start_edge_vertex = ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ int side_start_index;
+ if (ptex_face_resolution >= 3) {
+ side_start_index =
+ start_vertex_index + num_inner_vertices_per_ptex * corner;
+ }
+ else {
+ side_start_index = center_vertex_index;
+ }
+ for (int i = 0; i < ptex_face_resolution - 1; i++, subdiv_edge++) {
+ subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
+ if (flip) {
+ subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
+ }
+ else {
+ subdiv_edge->v1 = start_edge_vertex + i;
+ }
+ subdiv_edge->v2 = side_start_index + i;
+ }
+ }
+ if (ptex_face_resolution >= 3) {
+ const MEdge *coarse_edge = &coarse_medge[prev_coarse_loop->e];
+ const int start_edge_vertex = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ int side_start_index =
+ start_vertex_index + num_inner_vertices_per_ptex * corner;
+ for (int i = 0; i < ptex_face_resolution - 2; i++, subdiv_edge++) {
+ subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
+ if (flip) {
+ subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
+ }
+ else {
+ subdiv_edge->v1 = start_edge_vertex + i;
+ }
+ subdiv_edge->v2 = side_start_index +
+ (ptex_face_inner_resolution + 1) * i;
+ }
+ }
+ prev_coarse_loop = coarse_loop;
+ }
+}
+
+static void subdiv_create_edges_all_patches(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ if (coarse_poly->totloop == 4) {
+ subdiv_create_edges_all_patches_regular(ctx, coarse_poly);
+ }
+ else {
+ subdiv_create_edges_all_patches_special(ctx, coarse_poly);
+ }
+}
+
+static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ subdiv_create_edges_all_patches(ctx, coarse_poly);
+}
+
+static void subdiv_create_boundary_edges(
+ SubdivMeshContext *ctx,
+ int edge_index)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MEdge *coarse_edge = &coarse_medge[edge_index];
+ const int resolution = ctx->settings->resolution;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_subdiv_edges_per_coarse_edge = resolution - 1;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MEdge *subdiv_medge = subdiv_mesh->medge;
+ MEdge *subdiv_edge = &subdiv_medge[
+ ctx->edge_boundary_offset +
+ edge_index * num_subdiv_edges_per_coarse_edge];
+ int last_vertex_index = ctx->vertices_corner_offset + coarse_edge->v1;
+ for (int i = 0;
+ i < num_subdiv_edges_per_coarse_edge - 1;
+ i++, subdiv_edge++)
+ {
+ subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
+ subdiv_edge->v1 = last_vertex_index;
+ subdiv_edge->v2 =
+ ctx->vertices_edge_offset +
+ edge_index * num_subdiv_vertices_per_coarse_edge +
+ i;
+ last_vertex_index = subdiv_edge->v2;
+ }
+ subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
+ subdiv_edge->v1 = last_vertex_index;
+ subdiv_edge->v2 = ctx->vertices_corner_offset + coarse_edge->v2;
+}
+
+/* =============================================================================
+ * Loops creation/interpolation.
+ */
+
+static void subdiv_copy_loop_data(
+ const SubdivMeshContext *ctx,
+ MLoop *subdiv_loop,
+ const LoopsForInterpolation *loop_interpolation,
+ const float u, const float v)
+{
+ const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
+ const float weights[4] = {(1.0f - u) * (1.0f - v),
+ u * (1.0f - v),
+ u * v,
+ (1.0f - u) * v};
+ CustomData_interp(loop_interpolation->loop_data,
+ &ctx->subdiv_mesh->ldata,
+ loop_interpolation->loop_indices,
+ weights, NULL,
+ 4,
+ subdiv_loop_index);
+ /* TODO(sergey): Set ORIGINDEX. */
+}
+
+static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
+ MLoop *subdiv_loop,
+ const int ptex_face_index,
+ const float u, const float v,
+ const float du, const float dv)
+{
+ if (ctx->num_uv_layers == 0) {
+ return;
+ }
+ Subdiv *subdiv = ctx->subdiv;
+ const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
+ for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
+ MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
+ BKE_subdiv_eval_face_varying(subdiv,
+ layer_index,
+ ptex_face_index,
+ u, v,
+ subdiv_loopuv[0].uv);
+ BKE_subdiv_eval_face_varying(subdiv,
+ layer_index,
+ ptex_face_index,
+ u + du, v,
+ subdiv_loopuv[1].uv);
+ BKE_subdiv_eval_face_varying(subdiv,
+ layer_index,
+ ptex_face_index,
+ u + du, v + dv,
+ subdiv_loopuv[2].uv);
+ BKE_subdiv_eval_face_varying(subdiv,
+ layer_index,
+ ptex_face_index,
+ u, v + dv,
+ subdiv_loopuv[3].uv);
+ }
+}
+
+static void rotate_indices(const int rot, int *a, int *b, int *c, int *d)
+{
+ int values[4] = {*a, *b, *c, *d};
+ *a = values[(0 - rot + 4) % 4];
+ *b = values[(1 - rot + 4) % 4];
+ *c = values[(2 - rot + 4) % 4];
+ *d = values[(3 - rot + 4) % 4];
+}
+
+static void subdiv_create_loops_of_poly(
+ SubdivMeshContext *ctx,
+ LoopsForInterpolation *loop_interpolation,
+ MLoop *subdiv_loop_start,
+ const int ptex_face_index,
+ const int rotation,
+ /*const*/ int v0, /*const*/ int e0,
+ /*const*/ int v1, /*const*/ int e1,
+ /*const*/ int v2, /*const*/ int e2,
+ /*const*/ int v3, /*const*/ int e3,
+ const float u, const float v,
+ const float du, const float dv)
+{
+ rotate_indices(rotation, &v0, &v1, &v2, &v3);
+ rotate_indices(rotation, &e0, &e1, &e2, &e3);
+ subdiv_copy_loop_data(ctx,
+ &subdiv_loop_start[0],
+ loop_interpolation,
+ u, v);
+ subdiv_loop_start[0].v = v0;
+ subdiv_loop_start[0].e = e0;
+ subdiv_copy_loop_data(ctx,
+ &subdiv_loop_start[1],
+ loop_interpolation,
+ u + du, v);
+ subdiv_loop_start[1].v = v1;
+ subdiv_loop_start[1].e = e1;
+ subdiv_copy_loop_data(ctx,
+ &subdiv_loop_start[2],
+ loop_interpolation,
+ u + du, v + dv);
+ subdiv_loop_start[2].v = v2;
+ subdiv_loop_start[2].e = e2;
+ subdiv_copy_loop_data(ctx,
+ &subdiv_loop_start[3],
+ loop_interpolation,
+ u, v + dv);
+ subdiv_loop_start[3].v = v3;
+ subdiv_loop_start[3].e = e3;
+ /* Interpolate UV layers using OpenSubdiv. */
+ subdiv_eval_uv_layer(ctx,
+ subdiv_loop_start,
+ ptex_face_index,
+ u, v, du, dv);
+}
+
+static void subdiv_create_loops_regular(SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const int resolution = ctx->settings->resolution;
+ /* Base/coarse mesh information. */
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int poly_index = coarse_poly - coarse_mpoly;
+ const int ptex_resolution =
+ ptex_face_resolution_get(coarse_poly, resolution);
+ const int ptex_inner_resolution = ptex_resolution - 2;
+ const int num_subdiv_edges_per_coarse_edge = resolution - 1;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_resolution - 1);
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ const int start_vertex_index =
+ ctx->vertices_inner_offset +
+ ctx->subdiv_vertex_offset[poly_index];
+ const int start_edge_index =
+ ctx->edge_inner_offset +
+ ctx->subdiv_edge_offset[poly_index];
+ const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
+ const int start_loop_index = 4 * start_poly_index;
+ const float du = inv_ptex_resolution_1;
+ const float dv = inv_ptex_resolution_1;
+ /* Hi-poly subdivided mesh. */
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MLoop *subdiv_loopoop = subdiv_mesh->mloop;
+ MLoop *subdiv_loop = &subdiv_loopoop[start_loop_index];
+ LoopsForInterpolation loop_interpolation;
+ loop_interpolation_init(ctx, &loop_interpolation, coarse_poly);
+ loop_interpolation_from_ptex(ctx,
+ &loop_interpolation,
+ coarse_poly,
+ 0);
+ /* Loops for inner part of ptex. */
+ for (int y = 1; y < ptex_resolution - 2; y++) {
+ const float v = y * inv_ptex_resolution_1;
+ const int inner_y = y - 1;
+ for (int x = 1; x < ptex_resolution - 2; x++, subdiv_loop += 4) {
+ const int inner_x = x - 1;
+ const float u = x * inv_ptex_resolution_1;
+ /* Vertex indicies ordered counter-clockwise. */
+ const int v0 = start_vertex_index +
+ (inner_y * ptex_inner_resolution + inner_x);
+ const int v1 = v0 + 1;
+ const int v2 = v0 + ptex_inner_resolution + 1;
+ const int v3 = v0 + ptex_inner_resolution;
+ /* Edge indicies ordered counter-clockwise. */
+ const int e0 = start_edge_index +
+ (inner_y * (2 * ptex_inner_resolution - 1) + inner_x);
+ const int e1 = e0 + ptex_inner_resolution;
+ const int e2 = e0 + (2 * ptex_inner_resolution - 1);
+ const int e3 = e0 + ptex_inner_resolution - 1;
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop, ptex_face_index, 0,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ }
+ }
+ /* Loops for faces connecting inner ptex part with boundary. */
+ const MLoop *prev_coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
+ const int start_edge_vertex = ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ int side_start_index = start_vertex_index;
+ int side_stride = 0;
+ int v0 = ctx->vertices_corner_offset + coarse_loop->v;
+ int v3, e3;
+ int e2_offset, e2_stride;
+ float u, v, delta_u, delta_v;
+ if (prev_coarse_loop->v == prev_coarse_edge->v1) {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
+ num_subdiv_vertices_per_coarse_edge - 1;
+ e3 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ num_subdiv_edges_per_coarse_edge - 1;
+ }
+ else {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ e3 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
+ }
+ /* Calculate starting veretx of corresponding inner part of ptex. */
+ if (corner == 0) {
+ side_stride = 1;
+ e2_offset = 0;
+ e2_stride = 1;
+ u = 0.0f;
+ v = 0.0f;
+ delta_u = du;
+ delta_v = 0.0f;
+ }
+ else if (corner == 1) {
+ side_start_index += resolution - 3;
+ side_stride = resolution - 2;
+ e2_offset = 2 * num_subdiv_edges_per_coarse_edge - 4;
+ e2_stride = 2 * num_subdiv_edges_per_coarse_edge - 3;
+ u = 1.0f - du;
+ v = 0;
+ delta_u = 0.0f;
+ delta_v = dv;
+ }
+ else if (corner == 2) {
+ side_start_index += num_subdiv_vertices_per_coarse_edge *
+ num_subdiv_vertices_per_coarse_edge - 1;
+ side_stride = -1;
+ e2_offset = num_edges_per_ptex_face_get(resolution - 2) - 1;
+ e2_stride = -1;
+ u = 1.0f - du;
+ v = 1.0f - dv;
+ delta_u = -du;
+ delta_v = 0.0f;
+ }
+ else if (corner == 3) {
+ side_start_index += num_subdiv_vertices_per_coarse_edge *
+ (num_subdiv_vertices_per_coarse_edge - 1);
+ side_stride = -(resolution - 2);
+ e2_offset = num_edges_per_ptex_face_get(resolution - 2) -
+ (2 * num_subdiv_edges_per_coarse_edge - 3);
+ e2_stride = -(2 * num_subdiv_edges_per_coarse_edge - 3);
+ u = 0.0f;
+ v = 1.0f - dv;
+ delta_u = 0.0f;
+ delta_v = -dv;
+ }
+ for (int i = 0; i < resolution - 2; i++, subdiv_loop += 4) {
+ int v1;
+ if (flip) {
+ v1 = start_edge_vertex + (resolution - i - 3);
+ }
+ else {
+ v1 = start_edge_vertex + i;
+ }
+ const int v2 = side_start_index + side_stride * i;
+ int e0;
+ if (flip) {
+ e0 = ctx->edge_boundary_offset +
+ coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ num_subdiv_edges_per_coarse_edge - i - 1;
+ }
+ else {
+ e0 = ctx->edge_boundary_offset +
+ coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ i;
+ }
+ int e1 = start_edge_index +
+ num_edges_per_ptex_face_get(resolution - 2) +
+ corner * num_subdiv_vertices_per_coarse_edge +
+ i;
+ int e2;
+ if (i == 0) {
+ e2 = start_edge_index +
+ num_edges_per_ptex_face_get(resolution - 2) +
+ ((corner - 1 + coarse_poly->totloop) %
+ coarse_poly->totloop) *
+ num_subdiv_vertices_per_coarse_edge +
+ num_subdiv_vertices_per_coarse_edge - 1;
+ }
+ else {
+ e2 = start_edge_index + e2_offset + e2_stride * (i - 1);
+ }
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index, corner,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u + delta_u * i, v + delta_v * i, du, dv);
+ v0 = v1;
+ v3 = v2;
+ e3 = e1;
+ }
+ prev_coarse_loop = coarse_loop;
+ }
+ loop_interpolation_end(&loop_interpolation);
+}
+
+static void subdiv_create_loops_special(SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const int resolution = ctx->settings->resolution;
+ /* Base/coarse mesh information. */
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const int poly_index = coarse_poly - coarse_mpoly;
+ const int ptex_face_resolution =
+ ptex_face_resolution_get(coarse_poly, resolution);
+ const int ptex_face_inner_resolution = ptex_face_resolution - 2;
+ const float inv_ptex_resolution_1 =
+ 1.0f / (float)(ptex_face_resolution - 1);
+ const int num_inner_vertices_per_ptex =
+ (ptex_face_resolution - 1) * (ptex_face_resolution - 2);
+ const int num_inner_edges_per_ptex_face =
+ num_inner_edges_per_ptex_face_get(
+ ptex_face_inner_resolution + 1);
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_subdiv_edges_per_coarse_edge = resolution - 1;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ const int center_vertex_index =
+ ctx->vertices_inner_offset +
+ ctx->subdiv_vertex_offset[poly_index];
+ const int start_vertex_index = center_vertex_index + 1;
+ const int start_inner_vertex_index = center_vertex_index + 1;
+ const int start_edge_index = ctx->edge_inner_offset +
+ ctx->subdiv_edge_offset[poly_index];
+ const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
+ const int start_loop_index = 4 * start_poly_index;
+ const float du = inv_ptex_resolution_1;
+ const float dv = inv_ptex_resolution_1;
+ /* Hi-poly subdivided mesh. */
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MLoop *subdiv_loopoop = subdiv_mesh->mloop;
+ MLoop *subdiv_loop = &subdiv_loopoop[start_loop_index];
+ LoopsForInterpolation loop_interpolation;
+ loop_interpolation_init(ctx, &loop_interpolation, coarse_poly);
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++)
+ {
+ const int corner_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex;
+ const int corner_edge_index =
+ start_edge_index + corner * num_inner_edges_per_ptex_face;
+ loop_interpolation_from_ptex(ctx,
+ &loop_interpolation,
+ coarse_poly,
+ corner);
+ for (int y = 1; y < ptex_face_inner_resolution; y++) {
+ const float v = y * inv_ptex_resolution_1;
+ const int inner_y = y - 1;
+ for (int x = 1;
+ x < ptex_face_inner_resolution + 1;
+ x++, subdiv_loop += 4)
+ {
+ const int inner_x = x - 1;
+ const float u = x * inv_ptex_resolution_1;
+ /* Vertex indicies ordered counter-clockwise. */
+ const int v0 =
+ corner_vertex_index +
+ (inner_y * (ptex_face_inner_resolution + 1) + inner_x);
+ const int v1 = v0 + 1;
+ const int v2 = v0 + ptex_face_inner_resolution + 2;
+ const int v3 = v0 + ptex_face_inner_resolution + 1;
+ /* Edge indicies ordered counter-clockwise. */
+ const int e0 = corner_edge_index +
+ (inner_y * (2 * ptex_face_inner_resolution + 1) + inner_x);
+ const int e1 = e0 + ptex_face_inner_resolution + 1;
+ const int e2 = e0 + (2 * ptex_face_inner_resolution + 1);
+ const int e3 = e0 + ptex_face_inner_resolution;
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index + corner, 0,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ }
+ }
+ }
+ /* Create connections between ptex faces. */
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const int next_corner = (corner + 1) % coarse_poly->totloop;
+ const int corner_edge_index =
+ start_edge_index + corner * num_inner_edges_per_ptex_face;
+ const int next_corner_edge_index =
+ start_edge_index + next_corner * num_inner_edges_per_ptex_face;
+ int current_patch_vertex_index =
+ start_inner_vertex_index +
+ corner * num_inner_vertices_per_ptex +
+ ptex_face_inner_resolution;
+ int next_path_vertex_index =
+ start_inner_vertex_index +
+ next_corner * num_inner_vertices_per_ptex +
+ num_inner_vertices_per_ptex - ptex_face_resolution + 1;
+ int v0 = current_patch_vertex_index;
+ int v1 = next_path_vertex_index;
+ current_patch_vertex_index += ptex_face_inner_resolution + 1;
+ next_path_vertex_index += 1;
+ int e0 = start_edge_index +
+ coarse_poly->totloop * num_inner_edges_per_ptex_face +
+ corner * (ptex_face_resolution - 2);
+ int e1 = next_corner_edge_index + num_inner_edges_per_ptex_face -
+ ptex_face_resolution + 2;
+ int e3 = corner_edge_index + 2 * ptex_face_resolution - 4;
+ loop_interpolation_from_ptex(ctx,
+ &loop_interpolation,
+ coarse_poly,
+ next_corner);
+ for (int row = 1;
+ row < ptex_face_inner_resolution;
+ row++, subdiv_loop += 4)
+ {
+ const int v2 = next_path_vertex_index;
+ const int v3 = current_patch_vertex_index;
+ const int e2 = e0 + 1;
+ const float u = row * du;
+ const float v = 1.0f - dv;
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index + next_corner, 3,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ current_patch_vertex_index += ptex_face_inner_resolution + 1;
+ next_path_vertex_index += 1;
+ v0 = v3;
+ v1 = v2;
+ e0 = e2;
+ e1 += 1;
+ e3 += 2 * ptex_face_resolution - 3;
+ }
+ }
+ /* Create loops from center. */
+ if (ptex_face_resolution >= 3) {
+ const int start_center_edge_index =
+ start_edge_index +
+ (num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution) * coarse_poly->totloop;
+ const int start_boundary_edge =
+ start_edge_index +
+ coarse_poly->totloop * num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution - 1;
+ for (int corner = 0, prev_corner = coarse_poly->totloop - 1;
+ corner < coarse_poly->totloop;
+ prev_corner = corner, corner++, subdiv_loop += 4)
+ {
+ loop_interpolation_from_ptex(ctx,
+ &loop_interpolation,
+ coarse_poly,
+ corner);
+ const int corner_edge_index =
+ start_edge_index +
+ corner * num_inner_edges_per_ptex_face;
+ const int current_patch_end_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex +
+ num_inner_vertices_per_ptex - 1;
+ const int prev_current_patch_end_vertex_index =
+ start_vertex_index + prev_corner *
+ num_inner_vertices_per_ptex +
+ num_inner_vertices_per_ptex - 1;
+ const int v0 = center_vertex_index;
+ const int v1 = prev_current_patch_end_vertex_index;
+ const int v2 = current_patch_end_vertex_index - 1;
+ const int v3 = current_patch_end_vertex_index;
+ const int e0 = start_center_edge_index + prev_corner;
+ const int e1 = start_boundary_edge +
+ prev_corner * (ptex_face_inner_resolution);
+ const int e2 = corner_edge_index +
+ num_inner_edges_per_ptex_face - 1;
+ const int e3 = start_center_edge_index + corner;
+ const float u = 1.0f - du;
+ const float v = 1.0f - dv;
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index + corner, 2,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ }
+ }
+ /* Loops for faces connecting inner ptex part with boundary. */
+ const MLoop *prev_coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
+ for (int prev_corner = coarse_poly->totloop - 1, corner = 0;
+ corner < coarse_poly->totloop;
+ prev_corner = corner, corner++)
+ {
+ loop_interpolation_from_ptex(ctx,
+ &loop_interpolation,
+ coarse_poly,
+ corner);
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ const int start_edge_vertex = ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ const int corner_vertex_index =
+ start_vertex_index + corner * num_inner_vertices_per_ptex;
+ const int corner_edge_index =
+ start_edge_index + corner * num_inner_edges_per_ptex_face;
+ /* Create loops for polygons along U axis. */
+ int v0 = ctx->vertices_corner_offset + coarse_loop->v;
+ int v3, e3;
+ if (prev_coarse_loop->v == prev_coarse_edge->v1) {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
+ num_subdiv_vertices_per_coarse_edge - 1;
+ e3 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ num_subdiv_edges_per_coarse_edge - 1;
+ }
+ else {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ e3 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
+ }
+ for (int i = 0;
+ i <= ptex_face_inner_resolution;
+ i++, subdiv_loop += 4)
+ {
+ int v1;
+ if (flip) {
+ v1 = start_edge_vertex + (resolution - i - 3);
+ }
+ else {
+ v1 = start_edge_vertex + i;
+ }
+ int v2;
+ if (ptex_face_inner_resolution >= 1) {
+ v2 = corner_vertex_index + i;
+ }
+ else {
+ v2 = center_vertex_index;
+ }
+ int e0;
+ if (flip) {
+ e0 = ctx->edge_boundary_offset +
+ coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ num_subdiv_edges_per_coarse_edge - i - 1;
+ }
+ else {
+ e0 = ctx->edge_boundary_offset +
+ coarse_loop->e * num_subdiv_edges_per_coarse_edge +
+ i;
+ }
+ int e1 = start_edge_index +
+ corner * (2 * ptex_face_inner_resolution + 1);
+ if (ptex_face_resolution >= 3) {
+ e1 += coarse_poly->totloop * (num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution + 1) +
+ i;
+ }
+ int e2 = 0;
+ if (i == 0 && ptex_face_resolution >= 3) {
+ e2 = start_edge_index +
+ coarse_poly->totloop *
+ (num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution + 1) +
+ corner * (2 * ptex_face_inner_resolution + 1) +
+ ptex_face_inner_resolution + 1;
+ }
+ else if (i == 0 && ptex_face_resolution < 3) {
+ e2 = start_edge_index +
+ prev_corner * (2 * ptex_face_inner_resolution + 1);
+ }
+ else {
+ e2 = corner_edge_index + i - 1;
+ }
+ const float u = du * i;
+ const float v = 0.0f;
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index + corner, 0,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ v0 = v1;
+ v3 = v2;
+ e3 = e1;
+ }
+ /* Create loops for polygons along V axis. */
+ const bool flip_prev = (prev_coarse_edge->v2 == coarse_loop->v);
+ v0 = corner_vertex_index;
+ if (prev_coarse_loop->v == prev_coarse_edge->v1) {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
+ num_subdiv_vertices_per_coarse_edge - 1;
+ }
+ else {
+ v3 = ctx->vertices_edge_offset +
+ prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
+ }
+ e3 = start_edge_index +
+ coarse_poly->totloop *
+ (num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution + 1) +
+ corner * (2 * ptex_face_inner_resolution + 1) +
+ ptex_face_inner_resolution + 1;
+ for (int i = 0;
+ i <= ptex_face_inner_resolution - 1;
+ i++, subdiv_loop += 4)
+ {
+ int v1;
+ int e0, e1;
+ if (i == ptex_face_inner_resolution - 1) {
+ v1 = start_vertex_index +
+ prev_corner * num_inner_vertices_per_ptex +
+ ptex_face_inner_resolution;
+ e1 = start_edge_index +
+ coarse_poly->totloop *
+ (num_inner_edges_per_ptex_face +
+ ptex_face_inner_resolution + 1) +
+ prev_corner * (2 * ptex_face_inner_resolution + 1) +
+ ptex_face_inner_resolution;
+ e0 = start_edge_index +
+ coarse_poly->totloop * num_inner_edges_per_ptex_face +
+ prev_corner * ptex_face_inner_resolution;
+ }
+ else {
+ v1 = v0 + ptex_face_inner_resolution + 1;
+ e0 = corner_edge_index + ptex_face_inner_resolution +
+ i * (2 * ptex_face_inner_resolution + 1);
+ e1 = e3 + 1;
+ }
+ int v2 = flip_prev ? v3 - 1 : v3 + 1;
+ int e2;
+ if (flip_prev) {
+ e2 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e *
+ num_subdiv_edges_per_coarse_edge +
+ num_subdiv_edges_per_coarse_edge - 2 - i;
+ }
+ else {
+ e2 = ctx->edge_boundary_offset +
+ prev_coarse_loop->e *
+ num_subdiv_edges_per_coarse_edge + 1 + i;
+ }
+ const float u = 0.0f;
+ const float v = du * (i + 1);
+ subdiv_create_loops_of_poly(
+ ctx, &loop_interpolation, subdiv_loop,
+ ptex_face_index + corner, 1,
+ v0, e0, v1, e1, v2, e2, v3, e3,
+ u, v, du, dv);
+ v0 = v1;
+ v3 = v2;
+ e3 = e1;
+ }
+ prev_coarse_loop = coarse_loop;
+ }
+ loop_interpolation_end(&loop_interpolation);
+}
+
+static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index)
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ if (coarse_poly->totloop == 4) {
+ subdiv_create_loops_regular(ctx, coarse_poly);
+ }
+ else {
+ subdiv_create_loops_special(ctx, coarse_poly);
+ }
+}
+
+/* =============================================================================
+ * Polygons subdivision process.
+ */
+
+static void subdiv_copy_poly_data(const SubdivMeshContext *ctx,
+ MPoly *subdiv_poly,
+ const MPoly *coarse_poly)
+{
+ const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
+ const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
+ CustomData_copy_data(&ctx->coarse_mesh->pdata,
+ &ctx->subdiv_mesh->pdata,
+ coarse_poly_index,
+ subdiv_poly_index,
+ 1);
+}
+
+static void subdiv_create_polys(SubdivMeshContext *ctx, int poly_index)
+{
+ const int resolution = ctx->settings->resolution;
+ const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
+ /* Base/coarse mesh information. */
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ const int num_ptex_faces_per_poly =
+ num_ptex_faces_per_poly_get(coarse_poly);
+ const int ptex_resolution =
+ ptex_face_resolution_get(coarse_poly, resolution);
+ const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution);
+ const int num_loops_per_ptex = 4 * num_polys_per_ptex;
+ const int start_loop_index = 4 * start_poly_index;
+ /* Hi-poly subdivided mesh. */
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
+ MPoly *subdiv_mp = &subdiv_mpoly[start_poly_index];
+ for (int ptex_of_poly_index = 0;
+ ptex_of_poly_index < num_ptex_faces_per_poly;
+ ptex_of_poly_index++)
+ {
+ for (int subdiv_poly_index = 0;
+ subdiv_poly_index < num_polys_per_ptex;
+ subdiv_poly_index++, subdiv_mp++)
+ {
+ subdiv_copy_poly_data(ctx, subdiv_mp, coarse_poly);
+ subdiv_mp->loopstart = start_loop_index +
+ (ptex_of_poly_index * num_loops_per_ptex) +
+ (subdiv_poly_index * 4);
+ subdiv_mp->totloop = 4;
+ }
+ }
+}
+
+/* =============================================================================
+ * Loose elements subdivision process.
+ */
+
+static void subdiv_create_loose_vertices_task(
+ void *__restrict userdata,
+ const int vertex_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SubdivMeshContext *ctx = userdata;
+ if (BLI_BITMAP_TEST_BOOL(ctx->coarse_vertices_used_map, vertex_index)) {
+ /* Vertex is not loose, was handled when handling polygons. */
+ return;
+ }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ const MVert *coarse_vertex = &coarse_mvert[vertex_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ MVert *subdiv_vertex = &subdiv_mvert[
+ ctx->vertices_corner_offset + vertex_index];
+ subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
+}
+
+/* Get neighbor edges of the given one.
+ * - neighbors[0] is an edge adjacent to edge->v1.
+ * - neighbors[1] is an edge adjacent to edge->v1.
+ */
+static void find_edge_neighbors(const SubdivMeshContext *ctx,
+ const MEdge *edge,
+ const MEdge *neighbors[2])
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ neighbors[0] = NULL;
+ neighbors[1] = NULL;
+ for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
+ if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
+ continue;
+ }
+ const MEdge *current_edge = &coarse_medge[edge_index];
+ if (current_edge == edge) {
+ continue;
+ }
+ if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
+ neighbors[0] = current_edge;
+ }
+ if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
+ neighbors[1] = current_edge;
+ }
+ }
+}
+
+static void points_for_loose_edges_interpolation_get(
+ SubdivMeshContext *ctx,
+ const MEdge *coarse_edge,
+ const MEdge *neighbors[2],
+ float points_r[4][3])
+{
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ /* Middle points corresponds to the edge. */
+ copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
+ copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
+ /* Start point, duplicate from edge start if no neighbor. */
+ if (neighbors[0] != NULL) {
+ if (neighbors[0]->v1 == coarse_edge->v1) {
+ copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
+ }
+ else {
+ copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
+ }
+ }
+ else {
+ sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
+ add_v3_v3(points_r[0], points_r[1]);
+ }
+ /* End point, duplicate from edge end if no neighbor. */
+ if (neighbors[1] != NULL) {
+ if (neighbors[1]->v1 == coarse_edge->v2) {
+ copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
+ }
+ else {
+ copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
+ }
+ }
+ else {
+ sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
+ add_v3_v3(points_r[3], points_r[2]);
+ }
+}
+
+static void subdiv_create_vertices_of_loose_edges_task(
+ void *__restrict userdata,
+ const int edge_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SubdivMeshContext *ctx = userdata;
+ if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
+ /* Vertex is not loose, was handled when handling polygons. */
+ return;
+ }
+ const int resolution = ctx->settings->resolution;
+ const int resolution_1 = resolution - 1;
+ const float inv_resolution_1 = 1.0f / (float)resolution_1;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_edge = &coarse_mesh->medge[edge_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ /* Find neighbors of the current loose edge. */
+ const MEdge *neighbors[2];
+ find_edge_neighbors(ctx, coarse_edge, neighbors);
+ /* Get points for b-spline interpolation. */
+ float points[4][3];
+ points_for_loose_edges_interpolation_get(
+ ctx, coarse_edge, neighbors, points);
+ /* Subdivion verticies which corresponds to edge's v1 and v2. */
+ MVert *subdiv_v1 = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_edge->v1];
+ MVert *subdiv_v2 = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_edge->v2];
+ /* First subdivided inner vertex of the edge. */
+ MVert *subdiv_start_vertex = &subdiv_mvert[
+ ctx->vertices_edge_offset +
+ edge_index * num_subdiv_vertices_per_coarse_edge];
+ /* Perform interpolation. */
+ for (int i = 0; i < resolution; i++) {
+ const float u = i * inv_resolution_1;
+ float weights[4];
+ key_curve_position_weights(u, weights, KEY_BSPLINE);
+
+ MVert *subdiv_vertex;
+ if (i == 0) {
+ subdiv_vertex = subdiv_v1;
+ }
+ else if (i == resolution - 1) {
+ subdiv_vertex = subdiv_v2;
+ }
+ else {
+ subdiv_vertex = &subdiv_start_vertex[i - 1];
+ }
+ interp_v3_v3v3v3v3(subdiv_vertex->co,
+ points[0],
+ points[1],
+ points[2],
+ points[3],
+ weights);
+ /* Reset flags and such. */
+ subdiv_vertex->flag = 0;
+ subdiv_vertex->bweight = 0.0f;
+ /* Reset normal. */
+ subdiv_vertex->no[0] = 0.0f;
+ subdiv_vertex->no[1] = 0.0f;
+ subdiv_vertex->no[2] = 1.0f;
+ }
+}
+
+/* =============================================================================
+ * Subdivision process entry points.
+ */
+
+static void subdiv_eval_task(
+ void *__restrict userdata,
+ const int poly_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SubdivMeshContext *ctx = userdata;
+ /* Evaluate hi-poly vertex coordinates and normals. */
+ subdiv_evaluate_vertices(ctx, poly_index);
+ /* Create mesh geometry for the given base poly index. */
+ subdiv_create_edges(ctx, poly_index);
+ subdiv_create_loops(ctx, poly_index);
+ subdiv_create_polys(ctx, poly_index);
+}
+
+static void subdiv_create_boundary_edges_task(
+ void *__restrict userdata,
+ const int edge_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ SubdivMeshContext *ctx = userdata;
+ subdiv_create_boundary_edges(ctx, edge_index);
+}
+
+Mesh *BKE_subdiv_to_mesh(
+ Subdiv *subdiv,
+ const SubdivToMeshSettings *settings,
+ const Mesh *coarse_mesh)
+{
+ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ /* Make sure evaluator is up to date with possible new topology, and that
+ * is is refined for the new positions of coarse vertices.
+ */
+ BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh);
+ SubdivMeshContext ctx = {0};
+ ctx.coarse_mesh = coarse_mesh;
+ ctx.subdiv = subdiv;
+ ctx.settings = settings;
+ subdiv_mesh_ctx_init(&ctx);
+ Mesh *result = BKE_mesh_new_nomain_from_template(
+ coarse_mesh,
+ ctx.num_subdiv_vertices,
+ ctx.num_subdiv_edges,
+ 0,
+ ctx.num_subdiv_loops,
+ ctx.num_subdiv_polygons);
+ ctx.subdiv_mesh = result;
+ subdiv_mesh_ctx_init_result(&ctx);
+ /* Multi-threaded evaluation. */
+ ParallelRangeSettings parallel_range_settings;
+ BKE_subdiv_stats_begin(&subdiv->stats,
+ SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
+ BLI_parallel_range_settings_defaults(&parallel_range_settings);
+ BLI_task_parallel_range(0, coarse_mesh->totpoly,
+ &ctx,
+ subdiv_eval_task,
+ &parallel_range_settings);
+ BLI_task_parallel_range(0, coarse_mesh->totvert,
+ &ctx,
+ subdiv_create_loose_vertices_task,
+ &parallel_range_settings);
+ BLI_task_parallel_range(0, coarse_mesh->totedge,
+ &ctx,
+ subdiv_create_vertices_of_loose_edges_task,
+ &parallel_range_settings);
+ BLI_task_parallel_range(0, coarse_mesh->totedge,
+ &ctx,
+ subdiv_create_boundary_edges_task,
+ &parallel_range_settings);
+ subdiv_mesh_ctx_free(&ctx);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
+ // BKE_mesh_validate(result, true, true);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ return result;
+}
diff --git a/source/blender/blenkernel/intern/subdiv_stats.c b/source/blender/blenkernel/intern/subdiv_stats.c
new file mode 100644
index 00000000000..f2219961ab7
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_stats.c
@@ -0,0 +1,84 @@
+/*
+ * ***** 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) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/subdiv_stats.c
+ * \ingroup bke
+ */
+
+#include "BKE_subdiv.h"
+
+#include <stdio.h>
+
+#include "PIL_time.h"
+
+void BKE_subdiv_stats_init(SubdivStats *stats)
+{
+ stats->topology_refiner_creation_time = 0.0;
+ stats->subdiv_to_mesh_time = 0.0;
+ stats->subdiv_to_mesh_geometry_time = 0.0;
+ stats->evaluator_creation_time = 0.0;
+ stats->evaluator_refine_time = 0.0;
+}
+
+void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
+{
+ stats->begin_timestamp_[value] = PIL_check_seconds_timer();
+}
+
+void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
+{
+ stats->values_[value] =
+ PIL_check_seconds_timer() - stats->begin_timestamp_[value];
+}
+
+void BKE_subdiv_stats_print(const SubdivStats *stats)
+{
+#define STATS_PRINT_TIME(stats, value, description) \
+ do { \
+ if ((stats)->value > 0.0) { \
+ printf(" %s: %f (sec)\n", description, (stats)->value); \
+ } \
+ } while (false)
+
+ printf("Subdivision surface statistics:\n");
+
+ STATS_PRINT_TIME(stats,
+ topology_refiner_creation_time,
+ "Topology refiner creation time");
+ STATS_PRINT_TIME(stats,
+ subdiv_to_mesh_time,
+ "Subdivision to mesh time");
+ STATS_PRINT_TIME(stats,
+ subdiv_to_mesh_geometry_time,
+ " Geometry time");
+ STATS_PRINT_TIME(stats,
+ evaluator_creation_time,
+ "Evaluator creation time");
+ STATS_PRINT_TIME(stats,
+ evaluator_refine_time,
+ "Evaluator refine time");
+
+#undef STATS_PRINT_TIME
+}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 9ea6ef62e4e..cead75ae659 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -280,11 +280,11 @@ static void get_face_uv_map_vert(UvVertMap *vmap, struct MPoly *mpoly, struct ML
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) {
if (v->separate)
nv = v;
- if (v->f == fi)
+ if (v->poly_index == fi)
break;
}
- fverts[j] = SET_UINT_IN_POINTER(mpoly[nv->f].loopstart + nv->tfindex);
+ fverts[j] = SET_UINT_IN_POINTER(mpoly[nv->poly_index].loopstart + nv->loop_of_poly_index);
}
}
@@ -292,7 +292,6 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
{
MPoly *mpoly = dm->getPolyArray(dm);
MLoop *mloop = dm->getLoopArray(dm);
- MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
int totface = dm->getNumPolys(dm);
int i, seam;
@@ -304,13 +303,12 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
BLI_array_declare(fverts);
#endif
EdgeSet *eset;
- float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
/* previous behavior here is without accounting for winding, however this causes stretching in
* UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially
- * intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED
+ * intention is to treat merged vertices from mirror modifier as seams.
* This fixes a very old regression (2.49 was correct here) */
vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
if (!vmap)
@@ -327,12 +325,12 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
if (v->separate)
break;
- seam = (v != NULL) || ((mvert + i)->flag & ME_VERT_MERGED);
+ seam = (v != NULL);
for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
if (v->separate) {
CCGVert *ssv;
- int loopid = mpoly[v->f].loopstart + v->tfindex;
+ int loopid = mpoly[v->poly_index].loopstart + v->loop_of_poly_index;
CCGVertHDL vhdl = SET_INT_IN_POINTER(loopid);
copy_v2_v2(uv, mloopuv[loopid].uv);
@@ -365,18 +363,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
unsigned int v0 = GET_UINT_FROM_POINTER(fverts[j_next]);
unsigned int v1 = GET_UINT_FROM_POINTER(fverts[j]);
- MVert *mv0 = mvert + (ml[j_next].v);
- MVert *mv1 = mvert + (ml[j].v);
if (BLI_edgeset_add(eset, v0, v1)) {
CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
CCGEdgeHDL ehdl = SET_INT_IN_POINTER(mp->loopstart + j_next);
- float crease;
-
- if ((mv0->flag & mv1->flag) & ME_VERT_MERGED)
- crease = creaseFactor;
- else
- crease = ccgSubSurf_getEdgeCrease(orige);
+ float crease = ccgSubSurf_getEdgeCrease(orige);
ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
}
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 173b459f442..0eb209cabeb 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -255,6 +255,7 @@ void BKE_undosys_stack_clear_active(UndoStack *ustack)
static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct Main *bmain)
{
UNDO_NESTED_ASSERT(false);
+ BLI_assert(ustack->step_init == NULL);
CLOG_INFO(&LOG, 1, "'%s'", name);
bContext *C_temp = CTX_create();
CTX_data_main_set(C_temp, bmain);
@@ -442,7 +443,13 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, bContext *C, const char
Main *bmain = G.main;
if (bmain->is_memfile_undo_written == false) {
const char *name_internal = "MemFile Internal";
- if (undosys_stack_push_main(ustack, name_internal, bmain)) {
+ /* Don't let 'step_init' cause issues when adding memfile undo step. */
+ void *step_init = ustack->step_init;
+ ustack->step_init = NULL;
+ const bool ok = undosys_stack_push_main(ustack, name_internal, bmain);
+ /* Restore 'step_init'. */
+ ustack->step_init = step_init;
+ if (ok) {
UndoStep *us = ustack->steps.last;
BLI_assert(STREQ(us->name, name_internal));
us->skip = true;
@@ -865,7 +872,7 @@ ID *BKE_undosys_ID_map_lookup_with_prev(const UndoIDPtrMap *map, ID *id_src, ID
return id_prev_match[1];
}
else {
- ID *id_dst = BKE_undosys_ID_map_lookup(map, id_src);
+ ID *id_dst = (id_src->lib == NULL) ? BKE_undosys_ID_map_lookup(map, id_src) : id_src;
id_prev_match[0] = id_src;
id_prev_match[1] = id_dst;
return id_dst;
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 3e1a9a4f57b..a5a38a6dc12 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -168,4 +168,3 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &wrld->id, true, lib_local);
}
-
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
index 9a510bcfc3b..da03063b245 100644
--- a/source/blender/blenlib/BLI_array_utils.h
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -41,7 +41,7 @@ void _bli_array_permute(
const unsigned int *index, void *arr_temp);
#define BLI_array_permute(arr, arr_len, order) \
_bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL)
-#define BLI_array_permute_ex(arr, arr_len, index, arr_temp) \
+#define BLI_array_permute_ex(arr, arr_len, order, arr_temp) \
_bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp)
int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index 82704e95fdd..03390a0dbcd 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -70,6 +70,12 @@ typedef unsigned int BLI_bitmap;
((_bitmap)[(_index) >> _BITMAP_POWER] & \
(1u << ((_index) & _BITMAP_MASK))))
+#define BLI_BITMAP_TEST_AND_SET_ATOMIC(_bitmap, _index) \
+ (CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
+ (atomic_fetch_and_or_uint32((uint32_t*)&(_bitmap)[(_index) >> _BITMAP_POWER], \
+ (1u << ((_index) & _BITMAP_MASK))) & \
+ (1u << ((_index) & _BITMAP_MASK))))
+
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index) \
(CHECK_TYPE_ANY(_bitmap, BLI_bitmap *, const BLI_bitmap *), \
(BLI_BITMAP_TEST(_bitmap, _index) != 0))
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h
index 0726e3bb343..2b53975a106 100644
--- a/source/blender/blenlib/BLI_compiler_compat.h
+++ b/source/blender/blenlib/BLI_compiler_compat.h
@@ -32,11 +32,7 @@
# define alloca _alloca
#endif
-#if defined(__cplusplus) && ((__cplusplus >= 201103L) || defined(_MSC_VER))
-# define HAS_CPP11_FEATURES
-#endif
-
-#if (defined(__GNUC__) || defined(__clang__)) && defined(HAS_CPP11_FEATURES)
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus)
extern "C++" {
/* Some magic to be sure we don't have reference in the type. */
template<typename T> static inline T decltype_helper(T x) { return x; }
diff --git a/source/blender/blenlib/BLI_hash_mm3.h b/source/blender/blenlib/BLI_hash_mm3.h
new file mode 100644
index 00000000000..93bf963c9a4
--- /dev/null
+++ b/source/blender/blenlib/BLI_hash_mm3.h
@@ -0,0 +1,40 @@
+/*
+ * ***** 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 *****
+ */
+
+#ifndef __BLI_HASH_MM3_H__
+#define __BLI_HASH_MM3_H__
+
+/** \file BLI_hash_mm3.h
+ * \ingroup bli
+ */
+
+#include "BLI_sys_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint32_t BLI_hash_mm3(const unsigned char *data, size_t len, uint32_t seed);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_HASH_MM2A_H__ */
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 20852f8fc82..0a9258f47ac 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -78,6 +78,9 @@ MINLINE void zero_v3_int(int r[3]);
MINLINE void copy_v2_v2_int(int r[2], const int a[2]);
MINLINE void copy_v3_v3_int(int r[3], const int a[3]);
MINLINE void copy_v4_v4_int(int r[4], const int a[4]);
+/* int <-> float */
+MINLINE void copy_v2fl_v2i(float r[2], const int a[2]);
+MINLINE void round_v2i_v2fl(int r[2], const float a[2]);
/* double -> float */
MINLINE void copy_v2fl_v2db(float r[2], const double a[2]);
MINLINE void copy_v3fl_v3db(float r[3], const double a[3]);
@@ -169,6 +172,7 @@ MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) ATTR_WARN_UNUS
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]);
+MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3]);
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]);
@@ -353,6 +357,8 @@ void range_vn_u(unsigned int *array_tar, const int size, const unsigned int star
void range_vn_fl(float *array_tar, const int size, const float start, const float step);
void negate_vn(float *array_tar, const int size);
void negate_vn_vn(float *array_tar, const float *array_src, const int size);
+void mul_vn_vn(float *array_tar, const float *array_src, const int size);
+void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size);
void mul_vn_fl(float *array_tar, const int size, const float f);
void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f);
void add_vn_vn(float *array_tar, const float *array_src, const int size);
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index 612151b7ea2..f7dea562393 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -64,6 +64,9 @@ void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem
/** Note that skipping is as slow as generating n numbers! */
void BLI_rng_skip(struct RNG *rng, int n) ATTR_NONNULL(1);
+/* fill an array with random numbers */
+void BLI_array_frand(float *ar, int count, unsigned int seed);
+
/** Return a pseudo-random (hash) float from an integer value */
float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 61f53f938e2..9621a759f3c 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC
intern/gsqueue.c
intern/hash_md5.c
intern/hash_mm2a.c
+ intern/hash_mm3.c
intern/jitter_2d.c
intern/lasso_2d.c
intern/list_sort_impl.h
@@ -158,6 +159,7 @@ set(SRC
BLI_hash.h
BLI_hash_md5.h
BLI_hash_mm2a.h
+ BLI_hash_mm3.h
BLI_heap.h
BLI_iterator.h
BLI_jitter_2d.h
diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c
index 700000b7717..80a2957d907 100644
--- a/source/blender/blenlib/intern/BLI_kdtree.c
+++ b/source/blender/blenlib/intern/BLI_kdtree.c
@@ -774,7 +774,12 @@ int BLI_kdtree_calc_duplicates_fast(
if (ELEM(duplicates[index], -1, index)) {
p.search = index;
copy_v3_v3(p.search_co, tree->nodes[node_index].co);
+ int found_prev = found;
deduplicate_recursive(&p, tree->root);
+ if (found != found_prev) {
+ /* Prevent chains of doubles. */
+ duplicates[index] = index;
+ }
}
}
MEM_freeN(order);
@@ -786,7 +791,12 @@ int BLI_kdtree_calc_duplicates_fast(
if (ELEM(duplicates[index], -1, index)) {
p.search = index;
copy_v3_v3(p.search_co, tree->nodes[node_index].co);
+ int found_prev = found;
deduplicate_recursive(&p, tree->root);
+ if (found != found_prev) {
+ /* Prevent chains of doubles. */
+ duplicates[index] = index;
+ }
}
}
}
diff --git a/source/blender/blenlib/intern/hash_mm3.c b/source/blender/blenlib/intern/hash_mm3.c
new file mode 100644
index 00000000000..105c1f46832
--- /dev/null
+++ b/source/blender/blenlib/intern/hash_mm3.c
@@ -0,0 +1,147 @@
+/*
+ * ***** 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 *****
+ *
+ * Copyright (C) 2018 Blender Foundation.
+ *
+ */
+
+/** \file blender/blenlib/intern/hash_mm3.c
+ * \ingroup bli
+ *
+ * Functions to compute Murmur3 hash key.
+ *
+ * This Code is based on alShaders/Cryptomatte/MurmurHash3.h:
+ *
+ * MurmurHash3 was written by Austin Appleby, and is placed in the public
+ * domain. The author hereby disclaims copyright to this source code.
+ *
+ */
+
+#include "BLI_compiler_compat.h"
+#include "BLI_compiler_attrs.h"
+#include "BLI_hash_mm3.h" /* own include */
+
+#if defined(_MSC_VER)
+# include <stdlib.h>
+# define ROTL32(x,y) _rotl(x,y)
+# define BIG_CONSTANT(x) (x)
+
+/* Other compilers */
+#else /* defined(_MSC_VER) */
+static inline uint32_t rotl32(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+# define ROTL32(x,y) rotl32(x,y)
+# define BIG_CONSTANT(x) (x##LLU)
+#endif /* !defined(_MSC_VER) */
+
+/* Block read - if your platform needs to do endian-swapping or can only
+ * handle aligned reads, do the conversion here
+ */
+
+BLI_INLINE uint32_t getblock32(const uint32_t * p, int i)
+{
+ return p[i];
+}
+
+BLI_INLINE uint64_t getblock64(const uint64_t * p, int i)
+{
+ return p[i];
+}
+
+/* Finalization mix - force all bits of a hash block to avalanche */
+
+BLI_INLINE uint32_t fmix32(uint32_t h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+BLI_INLINE uint64_t fmix64(uint64_t k)
+{
+ k ^= k >> 33;
+ k *= BIG_CONSTANT(0xff51afd7ed558ccd);
+ k ^= k >> 33;
+ k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
+ k ^= k >> 33;
+
+ return k;
+}
+
+uint32_t BLI_hash_mm3(const unsigned char *in, size_t len, uint32_t seed)
+{
+ const uint8_t *data = (const uint8_t *)in;
+ const int nblocks = len / 4;
+
+ uint32_t h1 = seed;
+
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+
+ /* body */
+
+ const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
+
+ for (int i = -nblocks; i; i++) {
+ uint32_t k1 = getblock32(blocks, i);
+
+ k1 *= c1;
+ k1 = ROTL32(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = ROTL32(h1, 13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ /* tail */
+
+ const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+
+ uint32_t k1 = 0;
+
+ switch (len & 3) {
+ case 3:
+ k1 ^= tail[2] << 16;
+ ATTR_FALLTHROUGH;
+ case 2:
+ k1 ^= tail[1] << 8;
+ ATTR_FALLTHROUGH;
+ case 1:
+ k1 ^= tail[0];
+ k1 *= c1;
+ k1 = ROTL32(k1, 15);
+ k1 *= c2;
+ h1 ^= k1;
+ }
+
+ /* finalization */
+
+ h1 ^= len;
+
+ h1 = fmix32(h1);
+
+ return h1;
+}
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 568448327bd..80b8a8d041c 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -578,6 +578,9 @@ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
Link *link = NULL;
const char *id_iter;
+ if (id == NULL)
+ return NULL;
+
for (link = listbase->first; link; link = link->next) {
id_iter = ((const char *)link) + offset;
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index dd1213bd03c..5055a29b79d 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2763,30 +2763,38 @@ bool isect_ray_aabb_v3(
return true;
}
-/*
- * Test a bounding box (AABB) for ray intersection
- * assumes the ray is already local to the boundbox space
+/**
+ * Test a bounding box (AABB) for ray intersection.
+ * Assumes the ray is already local to the boundbox space.
+ *
+ * \note: \a direction should be normalized if you intend to use the \a tmin or \a tmax distance results!
*/
bool isect_ray_aabb_v3_simple(
const float orig[3], const float dir[3],
const float bb_min[3], const float bb_max[3],
float *tmin, float *tmax)
{
- double t[7];
+ double t[6];
float hit_dist[2];
- t[1] = (double)(bb_min[0] - orig[0]) / dir[0];
- t[2] = (double)(bb_max[0] - orig[0]) / dir[0];
- t[3] = (double)(bb_min[1] - orig[1]) / dir[1];
- t[4] = (double)(bb_max[1] - orig[1]) / dir[1];
- t[5] = (double)(bb_min[2] - orig[2]) / dir[2];
- t[6] = (double)(bb_max[2] - orig[2]) / dir[2];
- hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6]));
- hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6]));
- if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1]))
+ const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX;
+ const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX;
+ const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX;
+ t[0] = (double)(bb_min[0] - orig[0]) * invdirx;
+ t[1] = (double)(bb_max[0] - orig[0]) * invdirx;
+ t[2] = (double)(bb_min[1] - orig[1]) * invdiry;
+ t[3] = (double)(bb_max[1] - orig[1]) * invdiry;
+ t[4] = (double)(bb_min[2] - orig[2]) * invdirz;
+ t[5] = (double)(bb_max[2] - orig[2]) * invdirz;
+ hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));
+ hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));
+ if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) {
return false;
+ }
else {
- if (tmin) *tmin = hit_dist[0];
- if (tmax) *tmax = hit_dist[1];
+ if (tmin)
+ *tmin = hit_dist[0];
+ if (tmax)
+ *tmax = hit_dist[1];
return true;
}
}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index d6e48fa59e7..acb4ee87f69 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -1096,6 +1096,27 @@ void negate_vn_vn(float *array_tar, const float *array_src, const int size)
}
}
+void mul_vn_vn(float *array_tar, const float *array_src, const int size)
+{
+ float *tar = array_tar + (size - 1);
+ const float *src = array_src + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar--) *= *(src--);
+ }
+}
+
+void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
+{
+ float *tar = array_tar + (size - 1);
+ const float *src_a = array_src_a + (size - 1);
+ const float *src_b = array_src_b + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar--) = *(src_a--) * *(src_b--);
+ }
+}
+
void mul_vn_fl(float *array_tar, const int size, const float f)
{
float *array_pt = array_tar + (size - 1);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 4c40921edb6..c4535eacefa 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -192,6 +192,19 @@ MINLINE void copy_v4_v4_int(int r[4], const int a[4])
r[3] = a[3];
}
+/* int <-> float */
+MINLINE void round_v2i_v2fl(int r[2], const float a[2])
+{
+ r[0] = (int)roundf(a[0]);
+ r[1] = (int)roundf(a[1]);
+}
+
+MINLINE void copy_v2fl_v2i(float r[2], const int a[2])
+{
+ r[0] = (float)a[0];
+ r[1] = (float)a[1];
+}
+
/* double -> float */
MINLINE void copy_v2fl_v2db(float r[2], const double a[2])
{
@@ -753,6 +766,16 @@ MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
r[2] = a[0] * b[1] - a[1] * b[0];
}
+/* cross product suffers from severe precision loss when vectors are
+ * nearly parallel or opposite; doing the computation in double helps a lot */
+MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3])
+{
+ BLI_assert(r != a && r != b);
+ r[0] = (float)((double)a[1] * (double)b[2] - (double)a[2] * (double)b[1]);
+ r[1] = (float)((double)a[2] * (double)b[0] - (double)a[0] * (double)b[2]);
+ r[2] = (float)((double)a[0] * (double)b[1] - (double)a[1] * (double)b[0]);
+}
+
/* Newell's Method */
/* excuse this fairly specific function,
* its used for polygon normals all over the place
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 9e56ce6b2cf..8613a0ea6dd 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -265,6 +265,18 @@ void BLI_rng_skip(RNG *rng, int n)
/***/
+/* fill an array with random numbers */
+void BLI_array_frand(float *ar, int count, unsigned int seed)
+{
+ RNG rng;
+
+ BLI_rng_srandom(&rng, seed);
+
+ for (int i = 0; i < count; i++) {
+ ar[i] = BLI_rng_get_float(&rng);
+ }
+}
+
float BLI_hash_frand(unsigned int seed)
{
RNG rng;
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 1251424719a..9040405e537 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -143,8 +143,6 @@ void BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh);
void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname);
-BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, struct ReportList *reports);
-
/* internal function but we need to expose it */
void blo_lib_link_restore(
struct Main *newmain, struct wmWindowManager *curwm,
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
index f6d0be6f5f0..d615514f081 100644
--- a/source/blender/blenloader/BLO_writefile.h
+++ b/source/blender/blenloader/BLO_writefile.h
@@ -44,4 +44,6 @@ extern bool BLO_write_file(
extern bool BLO_write_file_mem(
struct Main *mainvar, struct MemFile *compare, struct MemFile *current, int write_flags);
+bool BLO_main_validate_libraries(struct Main *bmain, struct ReportList *reports);
+
#endif
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 72fa155553d..f2b7f35d353 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -52,7 +52,6 @@ set(SRC
intern/blend_validate.c
intern/readblenentry.c
intern/readfile.c
- intern/runtime.c
intern/undofile.c
intern/versioning_250.c
intern/versioning_260.c
@@ -64,7 +63,6 @@ set(SRC
BLO_blend_defs.h
BLO_readfile.h
- BLO_runtime.h
BLO_undofile.h
BLO_writefile.h
intern/readfile.h
diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c
index 4fb5d0e1286..1bc503719b4 100644
--- a/source/blender/blenloader/intern/blend_validate.c
+++ b/source/blender/blenloader/intern/blend_validate.c
@@ -47,7 +47,7 @@
#include "BKE_report.h"
#include "BLO_readfile.h"
-#include "BLO_runtime.h"
+#include "BLO_writefile.h"
#include "readfile.h"
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 96154e8f55a..9655d69ca4a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -72,7 +72,9 @@
#include "DNA_genfile.h"
#include "DNA_group_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
#include "DNA_hair_types.h"
+#include "DNA_shader_fx_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
@@ -131,6 +133,8 @@
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_library_idmap.h"
@@ -154,6 +158,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "BKE_shader_fx.h"
#include "BKE_outliner_treehash.h"
#include "BKE_sound.h"
#include "BKE_colortools.h"
@@ -267,6 +272,8 @@ static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
#ifdef USE_COLLECTION_COMPAT_28
static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc);
#endif
+static void direct_link_animdata(FileData *fd, AnimData *adt);
+static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt);
/* this function ensures that reports are printed,
* in the case of libraray linking errors this is important!
@@ -334,6 +341,12 @@ static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr,
if (oldaddr==NULL || newaddr==NULL) return;
+ for (int i = 0; i < onm->nentries; i++) {
+ if (onm->entries[i].old == oldaddr && onm->entries[i].newp != newaddr) {
+ abort();
+ }
+ }
+
if (UNLIKELY(onm->nentries == onm->entriessize)) {
onm->entriessize *= 2;
onm->entries = MEM_reallocN(onm->entries, sizeof(*onm->entries) * onm->entriessize);
@@ -1028,20 +1041,6 @@ static int *read_file_thumbnail(FileData *fd)
return blend_thumb;
}
-static int fd_read_from_file(FileData *filedata, void *buffer, unsigned int size)
-{
- int readsize = read(filedata->filedes, buffer, size);
-
- if (readsize < 0) {
- readsize = EOF;
- }
- else {
- filedata->seek += readsize;
- }
-
- return readsize;
-}
-
static int fd_read_gzip_from_file(FileData *filedata, void *buffer, unsigned int size)
{
int readsize = gzread(filedata->gzfiledes, buffer, size);
@@ -2369,6 +2368,7 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
}
/* ************ READ Brush *************** */
+
/* library brush linking after fileread */
static void lib_link_brush(FileData *fd, Main *main)
{
@@ -2384,6 +2384,11 @@ static void lib_link_brush(FileData *fd, Main *main)
brush->toggle_brush = newlibadr(fd, brush->id.lib, brush->toggle_brush);
brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
+ /* link default grease pencil palette */
+ if (brush->gpencil_settings != NULL) {
+ brush->gpencil_settings->material = newlibadr_us(fd, brush->id.lib, brush->gpencil_settings->material);
+ }
+
brush->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -2395,6 +2400,7 @@ static void direct_link_brush(FileData *fd, Brush *brush)
/* fallof curve */
brush->curve = newdataadr(fd, brush->curve);
+
brush->gradient = newdataadr(fd, brush->gradient);
if (brush->curve)
@@ -2402,11 +2408,29 @@ static void direct_link_brush(FileData *fd, Brush *brush)
else
BKE_brush_curve_preset(brush, CURVE_PRESET_SHARP);
+ /* grease pencil */
+ brush->gpencil_settings = newdataadr(fd, brush->gpencil_settings);
+ if (brush->gpencil_settings != NULL) {
+ brush->gpencil_settings->curve_sensitivity = newdataadr(fd, brush->gpencil_settings->curve_sensitivity);
+ brush->gpencil_settings->curve_strength = newdataadr(fd, brush->gpencil_settings->curve_strength);
+ brush->gpencil_settings->curve_jitter = newdataadr(fd, brush->gpencil_settings->curve_jitter);
+
+ if (brush->gpencil_settings->curve_sensitivity)
+ direct_link_curvemapping(fd, brush->gpencil_settings->curve_sensitivity);
+
+ if (brush->gpencil_settings->curve_strength)
+ direct_link_curvemapping(fd, brush->gpencil_settings->curve_strength);
+
+ if (brush->gpencil_settings->curve_jitter)
+ direct_link_curvemapping(fd, brush->gpencil_settings->curve_jitter);
+ }
+
brush->preview = NULL;
brush->icon_imbuf = NULL;
}
/* ************ READ Palette *************** */
+
static void lib_link_palette(FileData *fd, Main *main)
{
/* only link ID pointers */
@@ -2421,6 +2445,7 @@ static void lib_link_palette(FileData *fd, Main *main)
static void direct_link_palette(FileData *fd, Palette *palette)
{
+
/* palette itself has been read */
link_list(fd, &palette->colors);
}
@@ -3344,6 +3369,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
direct_link_curvemapping(fd, node->storage);
else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok = 1;
+ else if (node->type==CMP_NODE_CRYPTOMATTE) {
+ NodeCryptomatte *nc = (NodeCryptomatte *) node->storage;
+ nc->matte_id = newdataadr(fd, nc->matte_id);
+ }
}
else if ( ntree->type==NTREE_TEXTURE) {
if (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME)
@@ -4144,6 +4173,17 @@ static void lib_link_material(FileData *fd, Main *main)
ma->nodetree->id.lib = ma->id.lib;
}
+ /* relink grease pencil settings */
+ if (ma->gp_style != NULL) {
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ if (gp_style->sima != NULL) {
+ gp_style->sima = newlibadr_us(fd, ma->id.lib, gp_style->sima);
+ }
+ if (gp_style->ima != NULL) {
+ gp_style->ima = newlibadr_us(fd, ma->id.lib, gp_style->ima);
+ }
+ }
+
ma->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -4164,6 +4204,8 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
+
+ ma->gp_style = newdataadr(fd, ma->gp_style);
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -4799,7 +4841,7 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
/* ************ READ OBJECT ***************** */
-static void lib_link_modifiers__linkModifiers(
+static void lib_link_modifiers_common(
void *userData, Object *ob, ID **idpoin, int cb_flag)
{
FileData *fd = userData;
@@ -4809,9 +4851,10 @@ static void lib_link_modifiers__linkModifiers(
id_us_plus_no_lib(*idpoin);
}
}
+
static void lib_link_modifiers(FileData *fd, Object *ob)
{
- modifiers_foreachIDLink(ob, lib_link_modifiers__linkModifiers, fd);
+ modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd);
/* If linking from a library, clear 'local' static override flag. */
if (ob->id.lib != NULL) {
@@ -4822,6 +4865,30 @@ static void lib_link_modifiers(FileData *fd, Object *ob)
}
+static void lib_link_gpencil_modifiers(FileData *fd, Object *ob)
+{
+ BKE_gpencil_modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd);
+
+ /* If linking from a library, clear 'local' static override flag. */
+ if (ob->id.lib != NULL) {
+ for (GpencilModifierData *mod = ob->greasepencil_modifiers.first; mod != NULL; mod = mod->next) {
+ mod->flag &= ~eGpencilModifierFlag_StaticOverride_Local;
+ }
+ }
+}
+
+static void lib_link_shaderfxs(FileData *fd, Object *ob)
+{
+ BKE_shaderfx_foreachIDLink(ob, lib_link_modifiers_common, fd);
+
+ /* If linking from a library, clear 'local' static override flag. */
+ if (ob->id.lib != NULL) {
+ for (ShaderFxData *fx = ob->shader_fx.first; fx != NULL; fx = fx->next) {
+ fx->flag &= ~eShaderFxFlag_StaticOverride_Local;
+ }
+ }
+}
+
static void lib_link_object(FileData *fd, Main *main)
{
bool warn = false;
@@ -4958,6 +5025,8 @@ static void lib_link_object(FileData *fd, Main *main)
lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
+ lib_link_gpencil_modifiers(fd, ob);
+ lib_link_shaderfxs(fd, ob);
if (ob->rigidbody_constraint) {
ob->rigidbody_constraint->ob1 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob1);
@@ -5120,6 +5189,9 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
smd->domain->tex = NULL;
smd->domain->tex_shadow = NULL;
smd->domain->tex_flame = NULL;
+ smd->domain->tex_velocity_x = NULL;
+ smd->domain->tex_velocity_y = NULL;
+ smd->domain->tex_velocity_z = NULL;
smd->domain->tex_wt = NULL;
smd->domain->coba = newdataadr(fd, smd->domain->coba);
@@ -5379,6 +5451,61 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
}
}
+static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb)
+{
+ GpencilModifierData *md;
+
+ link_list(fd, lb);
+
+ for (md = lb->first; md; md = md->next) {
+ md->error = NULL;
+
+ /* if modifiers disappear, or for upward compatibility */
+ if (NULL == BKE_gpencil_modifierType_getInfo(md->type))
+ md->type = eModifierType_None;
+
+ if (md->type == eGpencilModifierType_Lattice) {
+ LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData*)md;
+ gpmd->cache_data = NULL;
+ }
+ else if (md->type == eGpencilModifierType_Hook) {
+ HookGpencilModifierData *hmd = (HookGpencilModifierData *)md;
+
+ hmd->curfalloff = newdataadr(fd, hmd->curfalloff);
+ if (hmd->curfalloff) {
+ direct_link_curvemapping(fd, hmd->curfalloff);
+ }
+ }
+ else if (md->type == eGpencilModifierType_Thick) {
+ ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
+
+ gpmd->curve_thickness = newdataadr(fd, gpmd->curve_thickness);
+ if (gpmd->curve_thickness) {
+ direct_link_curvemapping(fd, gpmd->curve_thickness);
+ /* initialize the curve. Maybe this could be moved to modififer logic */
+ curvemapping_initialize(gpmd->curve_thickness);
+ }
+ }
+
+ }
+}
+
+static void direct_link_shaderfxs(FileData *fd, ListBase *lb)
+{
+ ShaderFxData *fx;
+
+ link_list(fd, lb);
+
+ for (fx = lb->first; fx; fx = fx->next) {
+ fx->error = NULL;
+
+ /* if shader disappear, or for upward compatibility */
+ if (NULL == BKE_shaderfxType_getInfo(fx->type))
+ fx->type = eShaderFxType_None;
+
+ }
+}
+
static void direct_link_object(FileData *fd, Object *ob)
{
PartEff *paf;
@@ -5422,6 +5549,8 @@ static void direct_link_object(FileData *fd, Object *ob)
/* do it here, below old data gets converted */
direct_link_modifiers(fd, &ob->modifiers);
+ direct_link_gpencil_modifiers(fd, &ob->greasepencil_modifiers);
+ direct_link_shaderfxs(fd, &ob->shader_fx);
link_list(fd, &ob->effect);
paf= ob->effect.first;
@@ -5568,12 +5697,8 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
BKE_object_runtime_reset(ob);
- BLI_listbase_clear(&ob->gpulamp);
link_list(fd, &ob->pc_ids);
- /* Runtime curve data */
- ob->curve_cache = NULL;
-
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
@@ -5906,6 +6031,7 @@ static void lib_link_scene(FileData *fd, Main *main)
link_paint(fd, sce, &sce->toolsettings->wpaint->paint);
link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
link_paint(fd, sce, &sce->toolsettings->uvsculpt->paint);
+ link_paint(fd, sce, &sce->toolsettings->gp_paint->paint);
if (sce->toolsettings->sculpt)
sce->toolsettings->sculpt->gravity_object =
@@ -6164,6 +6290,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->vpaint);
direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->wpaint);
direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->uvsculpt);
+ direct_link_paint_helper(fd, (Paint**)&sce->toolsettings->gp_paint);
direct_link_paint(fd, &sce->toolsettings->imapaint.paint);
@@ -6173,28 +6300,16 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
- /* relink grease pencil drawing brushes */
- link_list(fd, &sce->toolsettings->gp_brushes);
- for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
- brush->cur_sensitivity = newdataadr(fd, brush->cur_sensitivity);
- if (brush->cur_sensitivity) {
- direct_link_curvemapping(fd, brush->cur_sensitivity);
- }
- brush->cur_strength = newdataadr(fd, brush->cur_strength);
- if (brush->cur_strength) {
- direct_link_curvemapping(fd, brush->cur_strength);
- }
- brush->cur_jitter = newdataadr(fd, brush->cur_jitter);
- if (brush->cur_jitter) {
- direct_link_curvemapping(fd, brush->cur_jitter);
- }
- }
-
/* relink grease pencil interpolation curves */
sce->toolsettings->gp_interpolate.custom_ipo = newdataadr(fd, sce->toolsettings->gp_interpolate.custom_ipo);
if (sce->toolsettings->gp_interpolate.custom_ipo) {
direct_link_curvemapping(fd, sce->toolsettings->gp_interpolate.custom_ipo);
}
+ /* relink grease pencil multiframe falloff curve */
+ sce->toolsettings->gp_sculpt.cur_falloff = newdataadr(fd, sce->toolsettings->gp_sculpt.cur_falloff);
+ if (sce->toolsettings->gp_sculpt.cur_falloff) {
+ direct_link_curvemapping(fd, sce->toolsettings->gp_sculpt.cur_falloff);
+ }
}
if (sce->ed) {
@@ -6402,6 +6517,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
if (sce->master_collection) {
sce->master_collection = newdataadr(fd, sce->master_collection);
direct_link_collection(fd, sce->master_collection);
+ /* Needed because this is an ID outside of Main. */
+ sce->master_collection->id.py_instance = NULL;
}
/* insert into global old-new map for reading without UI (link_global accesses it again) */
@@ -6432,11 +6549,24 @@ static void direct_link_scene(FileData *fd, Scene *sce)
/* relink's grease pencil data's refs */
static void lib_link_gpencil(FileData *fd, Main *main)
{
+ /* Relink all datablock linked by GP datablock */
for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
if (gpd->id.tag & LIB_TAG_NEED_LINK) {
+ /* Layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Layer -> Parent References */
+ gpl->parent = newlibadr(fd, gpd->id.lib, gpl->parent);
+ }
+
+ /* Datablock Stuff */
IDP_LibLinkProperty(gpd->id.properties, fd);
lib_link_animdata(fd, &gpd->id, gpd->adt);
+ /* materials */
+ for (int a = 0; a < gpd->totcol; a++) {
+ gpd->mat[a] = newlibadr_us(fd, gpd->id.lib, gpd->mat[a]);
+ }
+
gpd->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -6458,36 +6588,49 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
gpd->adt = newdataadr(fd, gpd->adt);
direct_link_animdata(fd, gpd->adt);
- /* relink palettes */
+ /* relink palettes (old palettes deprecated, only to convert old files) */
link_list(fd, &gpd->palettes);
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
- link_list(fd, &palette->colors);
+ if (gpd->palettes.first != NULL) {
+ for (palette = gpd->palettes.first; palette; palette = palette->next) {
+ link_list(fd, &palette->colors);
+ }
}
+ /* clear drawing cache */
+ gpd->runtime.batch_cache_data = NULL;
+
+ /* materials */
+ gpd->mat = newdataadr(fd, gpd->mat);
+ test_pointer_array(fd, (void **)&gpd->mat);
+
/* relink layers */
link_list(fd, &gpd->layers);
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* parent */
- gpl->parent = newlibadr(fd, gpd->id.lib, gpl->parent);
/* relink frames */
link_list(fd, &gpl->frames);
+
gpl->actframe = newdataadr(fd, gpl->actframe);
+ gpl->runtime.derived_data = NULL;
+ gpl->runtime.icon_id = 0;
+
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
/* relink strokes (and their points) */
link_list(fd, &gpf->strokes);
for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* relink stroke points array */
gps->points = newdataadr(fd, gps->points);
+ /* relink weight data */
+ gps->dvert = newdataadr(fd, gps->dvert);
+ direct_link_dverts(fd, gps->totpoints, gps->dvert);
+
/* the triangulation is not saved, so need to be recalculated */
gps->triangles = NULL;
gps->tot_triangles = 0;
gps->flag |= GP_STROKE_RECALC_CACHES;
- /* the color pointer is not saved, so need to be recalculated using the color name */
- gps->palcolor = NULL;
- gps->flag |= GP_STROKE_RECALC_COLOR;
}
}
}
@@ -6633,9 +6776,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
v3d->properties_storage = NULL;
/* render can be quite heavy, set to solid on load */
- if (v3d->drawtype == OB_RENDER)
- v3d->drawtype = OB_SOLID;
- v3d->prev_drawtype = OB_SOLID;
+ if (v3d->shading.type == OB_RENDER) {
+ v3d->shading.type = OB_SOLID;
+ }
+ v3d->shading.prev_type = OB_SOLID;
if (v3d->fx_settings.dof)
v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
@@ -7044,7 +7188,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
direct_link_area_map(fd, &win->global_areas);
win->ghostwin = NULL;
- win->gwnctx = NULL;
+ win->gpuctx = NULL;
win->eventstate = NULL;
win->cursor_keymap_status = NULL;
win->tweak = NULL;
@@ -7729,6 +7873,7 @@ static void direct_link_speaker(FileData *fd, Speaker *spk)
static void direct_link_sound(FileData *fd, bSound *sound)
{
+ sound->tags = 0;
sound->handle = NULL;
sound->playback_handle = NULL;
@@ -7740,6 +7885,7 @@ static void direct_link_sound(FileData *fd, bSound *sound)
if (fd->soundmap) {
sound->waveform = newsoundadr(fd, sound->waveform);
+ sound->tags |= SOUND_TAGS_WAVEFORM_NO_RELOAD;
}
else {
sound->waveform = NULL;
@@ -7750,7 +7896,7 @@ static void direct_link_sound(FileData *fd, bSound *sound)
BLI_spin_init(sound->spinlock);
}
/* clear waveform loading flag */
- sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
@@ -8642,6 +8788,11 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
user->walk_navigation.jump_height = 0.4f; /* m */
user->walk_navigation.teleport_time = 0.2f; /* s */
}
+
+ /* grease pencil multisamples */
+ if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "gpencil_multisamples")) {
+ user->gpencil_multisamples = 4;
+ }
}
static void do_versions(FileData *fd, Library *lib, Main *main)
@@ -8720,8 +8871,8 @@ static void lib_link_all(FileData *fd, Main *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_brush(fd, main);
lib_link_palette(fd, main);
+ lib_link_brush(fd, main);
lib_link_paint_curve(fd, main);
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
@@ -9458,6 +9609,9 @@ static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
expand_doit(fd, mainvar, brush->mask_mtex.tex);
expand_doit(fd, mainvar, brush->clone.image);
expand_doit(fd, mainvar, brush->paint_curve);
+ if (brush->gpencil_settings != NULL) {
+ expand_doit(fd, mainvar, brush->gpencil_settings->material);
+ }
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
@@ -9469,6 +9623,12 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
if (ma->nodetree)
expand_nodetree(fd, mainvar, ma->nodetree);
+
+ if (ma->gp_style) {
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ expand_doit(fd, mainvar, gp_style->sima);
+ expand_doit(fd, mainvar, gp_style->ima);
+ }
}
static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
@@ -9645,6 +9805,24 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data);
}
+ /* expand_object_expandModifier() */
+ if (ob->greasepencil_modifiers.first) {
+ struct { FileData *fd; Main *mainvar; } data;
+ data.fd = fd;
+ data.mainvar = mainvar;
+
+ BKE_gpencil_modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data);
+ }
+
+ /* expand_object_expandShaderFx() */
+ if (ob->shader_fx.first) {
+ struct { FileData *fd; Main *mainvar; } data;
+ data.fd = fd;
+ data.mainvar = mainvar;
+
+ BKE_shaderfx_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data);
+ }
+
expand_pose(fd, mainvar, ob->pose);
expand_doit(fd, mainvar, ob->poselib);
expand_constraints(fd, mainvar, &ob->constraints);
@@ -9923,8 +10101,18 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
{
- if (gpd->adt)
+ if (gpd->adt) {
expand_animdata(fd, mainvar, gpd->adt);
+ }
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ expand_doit(fd, mainvar, gpl->parent);
+ }
+
+ for (int a = 0; a < gpd->totcol; a++) {
+ expand_doit(fd, mainvar, gpd->mat[a]);
+ }
+
}
static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace)
@@ -10816,27 +11004,3 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
BKE_main_free(main_newid);
}
-
-/* reading runtime */
-
-BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, ReportList *reports)
-{
- BlendFileData *bfd = NULL;
- FileData *fd = filedata_new();
- fd->filedes = file;
- fd->buffersize = actualsize;
- fd->read = fd_read_from_file;
-
- /* needed for library_append and read_libraries */
- BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
-
- fd = blo_decode_and_check(fd, reports);
- if (!fd)
- return NULL;
-
- fd->reports = reports;
- bfd = blo_read_file_internal(fd, "");
- blo_freefiledata(fd);
-
- return bfd;
-}
diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c
deleted file mode 100644
index 985e8169819..00000000000
--- a/source/blender/blenloader/intern/runtime.c
+++ /dev/null
@@ -1,141 +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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-/**
- * \file runtime.c
- * \brief This file handles the loading of .blend files embedded in runtimes
- * \ingroup blenloader
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifdef WIN32
-# include <io.h> // read, open
-# include "BLI_winstuff.h"
-#else // ! WIN32
-# include <unistd.h> // read
-#endif
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "BLO_readfile.h"
-#include "BLO_runtime.h"
-
-#include "BKE_report.h"
-
-/* Runtime reading */
-
-static int handle_read_msb_int(int handle)
-{
- unsigned char buf[4];
-
- if (read(handle, buf, 4) != 4)
- return -1;
-
- return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0);
-}
-
-int BLO_is_a_runtime(const char *path)
-{
- int res = 0, fd = BLI_open(path, O_BINARY | O_RDONLY, 0);
- int datastart;
- char buf[8];
-
- if (fd == -1)
- goto cleanup;
-
- lseek(fd, -12, SEEK_END);
-
- datastart = handle_read_msb_int(fd);
-
- if (datastart == -1)
- goto cleanup;
- else if (read(fd, buf, 8) != 8)
- goto cleanup;
- else if (memcmp(buf, "BRUNTIME", 8) != 0)
- goto cleanup;
- else
- res = 1;
-
-cleanup:
- if (fd != -1)
- close(fd);
-
- return res;
-}
-
-BlendFileData *BLO_read_runtime(const char *path, ReportList *reports)
-{
- BlendFileData *bfd = NULL;
- size_t actualsize;
- int fd, datastart;
- char buf[8];
-
- fd = BLI_open(path, O_BINARY | O_RDONLY, 0);
-
- if (fd == -1) {
- BKE_reportf(reports, RPT_ERROR, "Unable to open '%s': %s", path, strerror(errno));
- goto cleanup;
- }
-
- actualsize = BLI_file_descriptor_size(fd);
-
- lseek(fd, -12, SEEK_END);
-
- datastart = handle_read_msb_int(fd);
-
- if (datastart == -1) {
- BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (problem seeking)", path);
- goto cleanup;
- }
- else if (read(fd, buf, 8) != 8) {
- BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (truncated header)", path);
- goto cleanup;
- }
- else if (memcmp(buf, "BRUNTIME", 8) != 0) {
- BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (not a blend file)", path);
- goto cleanup;
- }
- else {
- //printf("starting to read runtime from %s at datastart %d\n", path, datastart);
- lseek(fd, datastart, SEEK_SET);
- bfd = blo_read_blendafterruntime(fd, path, actualsize - datastart, reports);
- fd = -1; // file was closed in blo_read_blendafterruntime()
- }
-
-cleanup:
- if (fd != -1)
- close(fd);
-
- return bfd;
-}
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 973591c49da..4b628bf816a 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -545,20 +545,6 @@ static void do_version_constraints_radians_degrees_250(ListBase *lb)
}
}
-/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already */
-static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep)
-{
- Sequence * seq = seqbasep->first;
-
- while (seq) {
- BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq);
- if (seq->seqbase.first) {
- do_versions_seq_unique_name_all_strips(sce, &seq->seqbase);
- }
- seq = seq->next;
- }
-}
-
static void do_version_bone_roll_256(Bone *bone)
{
Bone *child;
@@ -1029,10 +1015,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
if (sce->r.frame_step == 0)
sce->r.frame_step = 1;
- if (sce->ed && sce->ed->seqbase.first) {
- do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase);
- }
-
sce = sce->id.next;
}
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 7a032dc3c90..f2f2e7d7881 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1685,7 +1685,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
case SPACE_VIEW3D:
{
View3D *v3d = (View3D *)sl;
- v3d->flag2 |= V3D_SHOW_GPENCIL;
+ v3d->flag2 |= V3D_SHOW_ANNOTATION;
break;
}
case SPACE_SEQ:
@@ -1709,7 +1709,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
case SPACE_CLIP:
{
SpaceClip *sclip = (SpaceClip *)sl;
- sclip->flag |= SC_SHOW_GPENCIL;
+ sclip->flag |= SC_SHOW_ANNOTATION;
break;
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 7a106611e64..fadf332c850 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -76,6 +76,9 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
#include "BLO_readfile.h"
@@ -87,6 +90,64 @@
#include "MEM_guardedalloc.h"
+/* ************************************************** */
+/* GP Palettes API (Deprecated) */
+
+/* add a new gp-palette */
+static bGPDpalette *BKE_gpencil_palette_addnew(bGPdata *gpd, const char *name)
+{
+ bGPDpalette *palette;
+
+ /* check that list is ok */
+ if (gpd == NULL) {
+ return NULL;
+ }
+
+ /* allocate memory and add to end of list */
+ palette = MEM_callocN(sizeof(bGPDpalette), "bGPDpalette");
+
+ /* add to datablock */
+ BLI_addtail(&gpd->palettes, palette);
+
+ /* set basic settings */
+ /* auto-name */
+ BLI_strncpy(palette->info, name, sizeof(palette->info));
+ BLI_uniquename(&gpd->palettes, palette, DATA_("GP_Palette"), '.', offsetof(bGPDpalette, info),
+ sizeof(palette->info));
+
+ /* return palette */
+ return palette;
+}
+
+/* add a new gp-palettecolor */
+static bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, const char *name)
+{
+ bGPDpalettecolor *palcolor;
+
+ /* check that list is ok */
+ if (palette == NULL) {
+ return NULL;
+ }
+
+ /* allocate memory and add to end of list */
+ palcolor = MEM_callocN(sizeof(bGPDpalettecolor), "bGPDpalettecolor");
+
+ /* add to datablock */
+ BLI_addtail(&palette->colors, palcolor);
+
+ /* set basic settings */
+ copy_v4_v4(palcolor->color, U.gpencil_new_layer_col);
+ ARRAY_SET_ITEMS(palcolor->fill, 1.0f, 1.0f, 1.0f);
+
+ /* auto-name */
+ BLI_strncpy(palcolor->info, name, sizeof(palcolor->info));
+ BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info),
+ sizeof(palcolor->info));
+
+ /* return palette color */
+ return palcolor;
+}
+
/**
* Setup rotation stabilization from ancient single track spec.
* Former Version of 2D stabilization used a single tracking marker to determine the rotation
@@ -1344,8 +1405,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
ToolSettings *ts = scene->toolsettings;
/* initialize use position for sculpt brushes */
ts->gp_sculpt.flag |= GP_BRUSHEDIT_FLAG_APPLY_POSITION;
- /* initialize selected vertices alpha factor */
- ts->gp_sculpt.alpha = 1.0f;
/* new strength sculpt brush */
if (ts->gp_sculpt.brush[0].size >= 11) {
@@ -1358,25 +1417,16 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
}
}
- /* create a default grease pencil drawing brushes set */
- if (!BLI_listbase_is_empty(&bmain->gpencil)) {
- for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
- ToolSettings *ts = scene->toolsettings;
- if (BLI_listbase_is_empty(&ts->gp_brushes)) {
- BKE_gpencil_brush_init_presets(ts);
- }
- }
- }
/* Convert Grease Pencil to new palettes/brushes
* Loop all strokes and create the palette and all colors
*/
for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
if (BLI_listbase_is_empty(&gpd->palettes)) {
/* create palette */
- bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, "GP_Palette", true);
+ bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, "GP_Palette");
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* create color using layer name */
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_addnew(palette, gpl->info, true);
+ bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_addnew(palette, gpl->info);
if (palcolor != NULL) {
/* set color attributes */
copy_v4_v4(palcolor->color, gpl->color);
@@ -1386,7 +1436,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (gpl->flag & GP_LAYER_LOCKED) palcolor->flag |= PC_COLOR_LOCKED;
if (gpl->flag & GP_LAYER_ONIONSKIN) palcolor->flag |= PC_COLOR_ONIONSKIN;
if (gpl->flag & GP_LAYER_VOLUMETRIC) palcolor->flag |= PC_COLOR_VOLUMETRIC;
- if (gpl->flag & GP_LAYER_HQ_FILL) palcolor->flag |= PC_COLOR_HQ_FILL;
/* set layer opacity to 1 */
gpl->opacity = 1.0f;
@@ -1399,8 +1448,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* set stroke to palette and force recalculation */
BLI_strncpy(gps->colorname, gpl->info, sizeof(gps->colorname));
- gps->palcolor = NULL;
- gps->flag |= GP_STROKE_RECALC_COLOR;
gps->thickness = gpl->thickness;
/* set alpha strength to 1 */
@@ -1410,13 +1457,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
-
- /* set thickness to 0 (now it is a factor to override stroke thickness) */
- gpl->thickness = 0.0f;
}
- /* set first color as active */
- if (palette->colors.first)
- BKE_gpencil_palettecolor_setactive(palette, palette->colors.first);
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index b854438ed47..aed1fd8b416 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -54,24 +54,31 @@
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_genfile.h"
+#include "DNA_gpencil_types.h"
#include "DNA_workspace_types.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_customdata.h"
+#include "BKE_colortools.h"
#include "BKE_freestyle.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_sequencer.h"
#include "BKE_studiolight.h"
#include "BKE_workspace.h"
+#include "BKE_gpencil.h"
+#include "BKE_paint.h"
+#include "BKE_object.h"
#include "BLO_readfile.h"
#include "readfile.h"
@@ -111,6 +118,9 @@ static void do_version_workspaces_create_from_screens(Main *bmain)
else {
workspace = BKE_workspace_add(bmain, screen->id.name + 2);
}
+ if (workspace == NULL) {
+ continue; /* Not much we can do.. */
+ }
BKE_workspace_layout_add(bmain, workspace, screen, screen->id.name + 2);
}
}
@@ -486,27 +496,15 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene)
nlc->flag |= LAYER_COLLECTION_EXCLUDE;
}
}
- else if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) ||
- (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer)))
- {
+ else {
if (srl->lay_zmask & (1 << layer)) {
have_override = true;
-
- BKE_override_layer_collection_boolean_add(
- lc,
- ID_OB,
- "cycles.is_holdout",
- true);
+ lc->flag |= LAYER_COLLECTION_HOLDOUT;
}
if ((srl->lay & (1 << layer)) == 0) {
have_override = true;
-
- BKE_override_layer_collection_boolean_add(
- lc,
- ID_OB,
- "cycles_visibility.camera",
- false);
+ lc->flag |= LAYER_COLLECTION_INDIRECT_ONLY;
}
}
}
@@ -751,6 +749,19 @@ void do_versions_after_linking_280(Main *bmain)
}
}
#endif
+
+}
+
+/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already.
+ * But in 2.79 another case generating non-unique names was discovered (see T55668, involving Meta strips)... */
+static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep)
+{
+ for (Sequence *seq = seqbasep->first; seq != NULL; seq = seq->next) {
+ BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq);
+ if (seq->seqbase.first != NULL) {
+ do_versions_seq_unique_name_all_strips(sce, &seq->seqbase);
+ }
+ }
}
void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
@@ -804,10 +815,10 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "contact_dist")) {
for (Lamp *la = bmain->lamp.first; la; la = la->id.next) {
- la->contact_dist = 1.0f;
+ la->contact_dist = 0.2f;
la->contact_bias = 0.03f;
la->contact_spread = 0.2f;
- la->contact_thickness = 0.5f;
+ la->contact_thickness = 0.2f;
}
}
@@ -865,10 +876,10 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
} FOREACH_NODETREE_END
- if (error & NTREE_DOVERSION_NEED_OUTPUT) {
- BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
- printf("You need to connect Principled and Eevee Specular shader nodes to new material output nodes.\n");
- }
+ if (error & NTREE_DOVERSION_NEED_OUTPUT) {
+ BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
+ printf("You need to connect Principled and Eevee Specular shader nodes to new material output nodes.\n");
+ }
if (error & NTREE_DOVERSION_TRANSPARENCY_EMISSION) {
BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
@@ -892,6 +903,68 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
#endif
+
+ {
+ /* Grease pencil sculpt and paint cursors */
+ if (!DNA_struct_elem_find(fd->filesdna, "GP_BrushEdit_Settings", "int", "weighttype")) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ /* sculpt brushes */
+ GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
+ if (gset) {
+ gset->weighttype = GP_EDITBRUSH_TYPE_WEIGHT;
+ }
+ }
+ }
+
+ {
+ float curcolor_add[3], curcolor_sub[3];
+ ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
+ ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
+ GP_EditBrush_Data *gp_brush;
+
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ ToolSettings *ts = scene->toolsettings;
+ /* sculpt brushes */
+ GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
+ for (int i = 0; i < TOT_GP_EDITBRUSH_TYPES; ++i) {
+ gp_brush = &gset->brush[i];
+ gp_brush->flag |= GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
+ copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
+ }
+ }
+ }
+
+ /* Init grease pencil edit line color */
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "float", "line_color[4]")) {
+ for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
+ ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
+ }
+ }
+
+ /* Init grease pencil pixel size factor */
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDdata", "int", "pixfactor")) {
+ for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
+ gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ }
+ }
+
+ /* Grease pencil multiframe falloff curve */
+ if (!DNA_struct_elem_find(fd->filesdna, "GP_BrushEdit_Settings", "CurveMapping", "cur_falloff")) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ /* sculpt brushes */
+ GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
+ if ((gset) && (gset->cur_falloff == NULL)) {
+ gset->cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ curvemapping_initialize(gset->cur_falloff);
+ curvemap_reset(gset->cur_falloff->cm,
+ &gset->cur_falloff->clipr,
+ CURVE_PRESET_GAUSS,
+ CURVEMAP_SLOPE_POSITIVE);
+ }
+ }
+ }
+ }
}
#ifdef USE_COLLECTION_COMPAT_28
@@ -911,6 +984,26 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
#endif
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
+ /* init grease pencil grids and paper */
+ if (!DNA_struct_elem_find(fd->filesdna, "gp_paper_opacity", "float", "gpencil_paper_color[3]")) {
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_grid_scale = 1.0f; // Scale
+ v3d->overlay.gpencil_grid_lines = GP_DEFAULT_GRID_LINES; // NUmber of lines
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ v3d->overlay.gpencil_grid_axis = V3D_GP_GRID_AXIS_Y;
+ v3d->overlay.gpencil_grid_opacity = 0.9f;
+ }
+ }
+ }
+ }
+ }
+ }
+
if (!MAIN_VERSION_ATLEAST(bmain, 280, 6)) {
if (DNA_struct_elem_find(fd->filesdna, "SpaceOops", "int", "filter") == false) {
bScreen *sc;
@@ -1013,6 +1106,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
tex->type = 0;
}
}
+
}
if (!MAIN_VERSION_ATLEAST(bmain, 280, 11)) {
@@ -1200,7 +1294,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
scene->eevee.flag =
SCE_EEVEE_VOLUMETRIC_LIGHTS |
- SCE_EEVEE_VOLUMETRIC_COLORED |
SCE_EEVEE_GTAO_BENT_NORMALS |
SCE_EEVEE_GTAO_BOUNCE |
SCE_EEVEE_TAA_REPROJECTION |
@@ -1258,7 +1351,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS);
EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS);
- EEVEE_GET_BOOL(props, volumetric_colored_transmittance, SCE_EEVEE_VOLUMETRIC_COLORED);
EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED);
EEVEE_GET_BOOL(props, gtao_use_bent_normals, SCE_EEVEE_GTAO_BENT_NORMALS);
EEVEE_GET_BOOL(props, gtao_bounce, SCE_EEVEE_GTAO_BOUNCE);
@@ -1524,7 +1616,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
- {
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 21)) {
+ for (Scene *sce = bmain->scene.first; sce != NULL; sce = sce->id.next) {
+ if (sce->ed != NULL && sce->ed->seqbase.first != NULL) {
+ do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase);
+ }
+ }
+
if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "texture_paint_mode_opacity")) {
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
@@ -1541,6 +1639,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShadeing", "short", "background_type")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ copy_v3_fl(v3d->shading.background_color, 0.05f);
+ }
+ }
+ }
+ }
+ }
+
if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_cubemap_draw_size")) {
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
scene->eevee.gi_irradiance_draw_size = 0.1f;
@@ -1599,5 +1710,132 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "short", "type")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->drawtype == OB_RENDER) {
+ v3d->drawtype = OB_SOLID;
+ }
+ v3d->shading.type = v3d->drawtype;
+ v3d->shading.prev_type = OB_SOLID;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "View3DShading", "shading")) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ BKE_screen_view3d_shading_init(&scene->display.shading);
+ }
+ }
+ /* initialize grease pencil view data */
+ if (!DNA_struct_elem_find(fd->filesdna, "SpaceView3D", "float", "vertex_opacity")) {
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->vertex_opacity = 1.0f;
+ v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+ }
+ }
+ }
+ }
+ }
+
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 22)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "annotate_v3d_align")) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ scene->toolsettings->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
+ scene->toolsettings->annotate_thickness = 3;
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "short", "line_change")) {
+ for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->line_change = gpl->thickness;
+ if ((gpl->thickness < 1) || (gpl->thickness > 10)) {
+ gpl->thickness = 3;
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_grid_scale")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_grid_scale = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_paper_opacity")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_grid_opacity")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_grid_opacity = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "int", "gpencil_grid_axis")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_grid_axis = V3D_GP_GRID_AXIS_Y;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "int", "gpencil_grid_lines")) {
+ for (bScreen *screen = bmain->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_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.gpencil_grid_lines = GP_DEFAULT_GRID_LINES;
+ }
+ }
+ }
+ }
+ }
+ /* default loc axis */
+ if (!DNA_struct_elem_find(fd->filesdna, "GP_BrushEdit_Settings", "int", "lock_axis")) {
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ /* lock axis */
+ GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
+ if (gset) {
+ gset->lock_axis = GP_LOCKAXIS_Y;
+ }
+ }
+ }
+ }
+
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index bd7334516ca..c120eed695c 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -170,46 +170,77 @@ void BLO_update_defaults_startup_blend(Main *bmain)
if (ts->gp_sculpt.brush[0].size == 0) {
GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
GP_EditBrush_Data *brush;
+ float curcolor_add[3], curcolor_sub[3];
+ ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
+ ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
+
+ /* default sculpt brush */
+ gset->brushtype = GP_EDITBRUSH_TYPE_PUSH;
+ /* default weight paint brush */
+ gset->weighttype = GP_EDITBRUSH_TYPE_WEIGHT;
brush = &gset->brush[GP_EDITBRUSH_TYPE_SMOOTH];
brush->size = 25;
brush->strength = 0.3f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_THICKNESS];
brush->size = 25;
brush->strength = 0.5f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_STRENGTH];
brush->size = 25;
brush->strength = 0.5f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_GRAB];
brush->size = 50;
brush->strength = 0.3f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_PUSH];
brush->size = 25;
brush->strength = 0.3f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_TWIST];
brush->size = 50;
brush->strength = 0.3f; // XXX?
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_PINCH];
brush->size = 50;
brush->strength = 0.5f; // XXX?
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
brush = &gset->brush[GP_EDITBRUSH_TYPE_RANDOMIZE];
brush->size = 25;
brush->strength = 0.5f;
- brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
+
+ brush = &gset->brush[GP_EDITBRUSH_TYPE_WEIGHT];
+ brush->size = 25;
+ brush->strength = 0.5f;
+ brush->flag = GP_EDITBRUSH_FLAG_USE_FALLOFF | GP_EDITBRUSH_FLAG_ENABLE_CURSOR;
+ copy_v3_v3(brush->curcolor_add, curcolor_add);
+ copy_v3_v3(brush->curcolor_sub, curcolor_sub);
}
ts->gpencil_v3d_align = GP_PROJECT_VIEWSPACE;
@@ -217,6 +248,9 @@ void BLO_update_defaults_startup_blend(Main *bmain)
ts->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
ts->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+ ts->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
+ ts->annotate_thickness = 3;
+
ParticleEditSettings *pset = &ts->particle;
for (int a = 0; a < ARRAY_SIZE(pset->brush); a++) {
pset->brush[a].strength = 0.5f;
@@ -408,4 +442,21 @@ void BLO_update_defaults_startup_blend(Main *bmain)
la->energy = 10.0;
}
}
+ /* default grease pencil settings */
+ {
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+ v3d->gp_flag |= V3D_GP_SHOW_MULTIEDIT_LINES;
+ v3d->gp_flag |= V3D_GP_SHOW_ONION_SKIN;
+ v3d->vertex_opacity = 0.9f;
+ break;
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 0467e59d63b..f5ee0bdb244 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -118,6 +118,8 @@
#include "DNA_genfile.h"
#include "DNA_group_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_shader_fx_types.h"
#include "DNA_fileglobal_types.h"
#include "DNA_hair_types.h"
#include "DNA_key_types.h"
@@ -166,6 +168,7 @@
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
+#include "BKE_gpencil_modifier.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
#include "BKE_library.h" // for set_listbasepointers
@@ -174,6 +177,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_sequencer.h"
+#include "BKE_shader_fx.h"
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
#include "BKE_fcurve.h"
@@ -188,7 +192,6 @@
#include "BLO_writefile.h"
#include "BLO_readfile.h"
-#include "BLO_runtime.h"
#include "BLO_undofile.h"
#include "BLO_blend_defs.h"
@@ -1104,6 +1107,13 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
}
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
+ else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_CRYPTOMATTE)) {
+ NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
+ if (nc->matte_id) {
+ writedata(wd, DATA, strlen(nc->matte_id) + 1, nc->matte_id);
+ }
+ writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ }
else {
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
@@ -1141,7 +1151,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
*/
static void current_screen_compat(
Main *mainvar, bool use_active_win,
- bScreen **r_screen, Scene **r_scene, ViewLayer **r_render_layer)
+ bScreen **r_screen, Scene **r_scene, ViewLayer **r_view_layer)
{
wmWindowManager *wm;
wmWindow *window = NULL;
@@ -1171,7 +1181,7 @@ static void current_screen_compat(
*r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL;
*r_scene = (window) ? window->scene : NULL;
- *r_render_layer = (window && *r_scene) ? BKE_view_layer_find(*r_scene, window->view_layer_name) : NULL;
+ *r_view_layer = (window && *r_scene) ? BKE_view_layer_find(*r_scene, window->view_layer_name) : NULL;
}
typedef struct RenderInfo {
@@ -1187,11 +1197,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
{
bScreen *curscreen;
Scene *sce, *curscene = NULL;
- ViewLayer *render_layer;
+ ViewLayer *view_layer;
RenderInfo data;
/* XXX in future, handle multiple windows with multiple screens? */
- current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer);
+ current_screen_compat(mainvar, false, &curscreen, &curscene, &view_layer);
for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
@@ -1806,6 +1816,57 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
}
}
+static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
+{
+ GpencilModifierData *md;
+
+ if (modbase == NULL) {
+ return;
+ }
+
+ for (md = modbase->first; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ if (mti == NULL) {
+ return;
+ }
+
+ writestruct_id(wd, DATA, mti->struct_name, 1, md);
+
+ if (md->type == eGpencilModifierType_Thick) {
+ ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
+
+ if (gpmd->curve_thickness) {
+ write_curvemapping(wd, gpmd->curve_thickness);
+ }
+ }
+ else if (md->type == eGpencilModifierType_Hook) {
+ HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
+
+ if (gpmd->curfalloff) {
+ write_curvemapping(wd, gpmd->curfalloff);
+ }
+ }
+ }
+}
+
+static void write_shaderfxs(WriteData *wd, ListBase *fxbase)
+{
+ ShaderFxData *fx;
+
+ if (fxbase == NULL) {
+ return;
+ }
+
+ for (fx = fxbase->first; fx; fx = fx->next) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
+ if (fxi == NULL) {
+ return;
+ }
+
+ writestruct_id(wd, DATA, fxi->struct_name, 1, fx);
+ }
+}
+
static void write_object(WriteData *wd, Object *ob)
{
if (ob->id.us > 0 || wd->use_memfile) {
@@ -1860,6 +1921,8 @@ static void write_object(WriteData *wd, Object *ob)
write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);
+ write_gpencil_modifiers(wd, &ob->greasepencil_modifiers);
+ write_shaderfxs(wd, &ob->shader_fx);
writelist(wd, DATA, LinkData, &ob->pc_ids);
writelist(wd, DATA, LodLevel, &ob->lodlevels);
@@ -2278,6 +2341,11 @@ static void write_material(WriteData *wd, Material *ma)
}
write_previews(wd, ma->preview);
+
+ /* grease pencil settings */
+ if (ma->gp_style) {
+ writestruct(wd, DATA, MaterialGPencilStyle, 1, ma->gp_style);
+ }
}
}
@@ -2481,24 +2549,18 @@ static void write_scene(WriteData *wd, Scene *sce)
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);
- }
- if (brush->cur_strength) {
- write_curvemapping(wd, brush->cur_strength);
- }
- if (brush->cur_jitter) {
- write_curvemapping(wd, brush->cur_jitter);
- }
+ if (tos->gp_paint) {
+ writestruct(wd, DATA, GpPaint, 1, tos->gp_paint);
+ write_paint(wd, &tos->gp_paint->paint);
}
/* write grease-pencil custom ipo curve to file */
if (tos->gp_interpolate.custom_ipo) {
write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
}
-
+ /* write grease-pencil multiframe falloff curve to file */
+ if (tos->gp_sculpt.cur_falloff) {
+ write_curvemapping(wd, tos->gp_sculpt.cur_falloff);
+ }
write_paint(wd, &tos->imapaint.paint);
@@ -2672,6 +2734,8 @@ static void write_gpencil(WriteData *wd, bGPdata *gpd)
write_animdata(wd, gpd->adt);
}
+ writedata(wd, DATA, sizeof(void *) * gpd->totcol, gpd->mat);
+
/* write grease-pencil layers to file */
writelist(wd, DATA, bGPDlayer, &gpd->layers);
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -2682,15 +2746,10 @@ static void write_gpencil(WriteData *wd, bGPdata *gpd)
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_dverts(wd, gps->totpoints, gps->dvert);
}
}
}
-
- /* 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);
- }
}
}
@@ -3177,6 +3236,20 @@ static void write_brush(WriteData *wd, Brush *brush)
if (brush->curve) {
write_curvemapping(wd, brush->curve);
}
+
+ if (brush->gpencil_settings) {
+ writestruct(wd, DATA, BrushGpencilSettings, 1, brush->gpencil_settings);
+
+ if (brush->gpencil_settings->curve_sensitivity) {
+ write_curvemapping(wd, brush->gpencil_settings->curve_sensitivity);
+ }
+ if (brush->gpencil_settings->curve_strength) {
+ write_curvemapping(wd, brush->gpencil_settings->curve_strength);
+ }
+ if (brush->gpencil_settings->curve_jitter) {
+ write_curvemapping(wd, brush->gpencil_settings->curve_jitter);
+ }
+ }
if (brush->gradient) {
writestruct(wd, DATA, ColorBand, 1, brush->gradient);
}
@@ -3704,7 +3777,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
FileGlobal fg;
bScreen *screen;
Scene *scene;
- ViewLayer *render_layer;
+ ViewLayer *view_layer;
char subvstr[8];
/* prevent mem checkers from complaining */
@@ -3713,12 +3786,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
memset(fg.build_hash, 0, sizeof(fg.build_hash));
fg.pad1 = NULL;
- current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer);
+ current_screen_compat(mainvar, is_undo, &screen, &scene, &view_layer);
/* XXX still remap G */
fg.curscreen = screen;
fg.curscene = scene;
- fg.cur_view_layer = render_layer;
+ fg.cur_view_layer = view_layer;
/* prevent to save this, is not good convention, and feature with concerns... */
fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME);
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 10e2892c5a5..70884454ce5 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -38,6 +38,8 @@ struct BMEdge;
struct BMLoop;
struct BMFace;
+struct MLoopNorSpaceArray;
+
struct BLI_mempool;
/* note: it is very important for BMHeader to start with two
@@ -236,6 +238,9 @@ typedef struct BMesh {
struct BLI_mempool *looplistpool;
#endif
+ struct MLoopNorSpaceArray *lnor_spacearr;
+ char spacearr_dirty;
+
/* should be copy of scene select mode */
/* stored in BMEditMesh too, this is a bit confusing,
* make sure they're in sync!
@@ -263,9 +268,33 @@ enum {
BM_FACE = 8
};
+typedef struct BMLoopNorEditData {
+ int loop_index;
+ BMLoop *loop;
+ float niloc[3];
+ float nloc[3];
+ float *loc;
+ short *clnors_data;
+} BMLoopNorEditData;
+
+typedef struct BMLoopNorEditDataArray {
+ BMLoopNorEditData *lnor_editdata;
+ /* This one has full amount of loops, used to map loop index to actual BMLoopNorEditData struct. */
+ BMLoopNorEditData **lidx_to_lnor_editdata;
+
+ int cd_custom_normal_offset;
+ int totloop;
+} BMLoopNorEditDataArray;
+
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
+enum {
+ BM_SPACEARR_DIRTY = 1 << 0,
+ BM_SPACEARR_DIRTY_ALL = 1 << 1,
+ BM_SPACEARR_BMO_SET = 1 << 2,
+};
+
/* args for _Generic */
#define _BM_GENERIC_TYPE_ELEM_NONCONST \
void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 442cd9275ec..a454fb7e948 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -30,6 +30,7 @@
#include "DNA_listBase.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_linklist_stack.h"
#include "BLI_listbase.h"
@@ -260,6 +261,11 @@ void BM_mesh_data_free(BMesh *bm)
BLI_freelistN(&bm->selected);
+ if (bm->lnor_spacearr) {
+ BKE_lnor_spacearr_free(bm->lnor_spacearr);
+ MEM_freeN(bm->lnor_spacearr);
+ }
+
BMO_error_clear(bm);
}
@@ -313,6 +319,9 @@ void BM_mesh_free(BMesh *bm)
* Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos
*/
+/* We use that existing internal API flag, assuming no other tool using it would run concurrently to clnors editing. */
+#define BM_LNORSPACE_UPDATE _FLAG_MF
+
typedef struct BMEdgesCalcVectorsData {
/* Read-only data. */
const float (*vcos)[3];
@@ -638,7 +647,8 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
* Will use first clnors_data array, and fallback to cd_loop_clnors_offset (use NULL and -1 to not use clnors). */
static void bm_mesh_loops_calc_normals(
BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3],
- MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2],
+ const int cd_loop_clnors_offset, const bool do_rebuild)
{
BMIter fiter;
BMFace *f_curr;
@@ -694,6 +704,11 @@ static void bm_mesh_loops_calc_normals(
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
+ if (do_rebuild && !BM_ELEM_API_FLAG_TEST(l_curr, BM_LNORSPACE_UPDATE) &&
+ !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL))
+ {
+ continue;
+ }
/* 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. */
@@ -894,7 +909,10 @@ static void bm_mesh_loops_calc_normals(
clnors_avg[0] /= clnors_nbr;
clnors_avg[1] /= clnors_nbr;
/* Fix/update all clnors of this fan with computed average value. */
- printf("Invalid clnors in this fan!\n");
+
+ /* Prints continuously when merge custom normals, so commenting. */
+ /* printf("Invalid clnors in this fan!\n"); */
+
while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
//print_v2("org clnor", clnor);
clnor[0] = (short)clnors_avg[0];
@@ -1009,7 +1027,8 @@ void BM_mesh_loop_normals_update(
void BM_loops_calc_normal_vcos(
BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3],
const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
- MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
+ MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2],
+ const int cd_loop_clnors_offset, const bool do_rebuild)
{
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
@@ -1019,7 +1038,8 @@ void BM_loops_calc_normal_vcos(
bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false);
/* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
- bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+ bm_mesh_loops_calc_normals(
+ bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild);
}
else {
BLI_assert(!r_lnors_spacearr);
@@ -1041,6 +1061,422 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true);
}
+void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3])
+{
+ BLI_assert(bm->lnor_spacearr != NULL);
+
+ if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_loops_calc_normal_vcos(
+ bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, false);
+ bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
+}
+
+#define CLEAR_SPACEARRAY_THRESHOLD(x) ((x) / 2)
+
+void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all)
+{
+ if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ return;
+ }
+ if (do_invalidate_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ return;
+ }
+ if (bm->lnor_spacearr == NULL) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ return;
+ }
+
+ BMVert *v;
+ BMLoop *l;
+ BMIter viter, liter;
+ /* Note: we could use temp tag of BMItem for that, but probably better not use it in such a low-level func?
+ * --mont29 */
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* When we affect a given vertex, we may affect following smooth fans:
+ * - all smooth fans of said vertex;
+ * - all smooth fans of all immediate loop-neighbors vertices;
+ * This can be simplified as 'all loops of selected vertices and their immediate neighbors'
+ * need to be tagged for update.
+ */
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l, BM_LNORSPACE_UPDATE);
+
+ /* Note that we only handle unselected neighbor vertices here, main loop will take care of
+ * selected ones. */
+ if ((!BM_elem_flag_test(l->prev->v, BM_ELEM_SELECT)) &&
+ !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->prev->v)))
+ {
+
+ BMLoop *l_prev;
+ BMIter liter_prev;
+ BM_ITER_ELEM(l_prev, &liter_prev, l->prev->v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l_prev, BM_LNORSPACE_UPDATE);
+ }
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_prev->v));
+ }
+
+ if ((!BM_elem_flag_test(l->next->v, BM_ELEM_SELECT)) &&
+ !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->next->v)))
+ {
+
+ BMLoop *l_next;
+ BMIter liter_next;
+ BM_ITER_ELEM(l_next, &liter_next, l->next->v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l_next, BM_LNORSPACE_UPDATE);
+ }
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_next->v));
+ }
+ }
+
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(v));
+ }
+ }
+
+ MEM_freeN(done_verts);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY;
+}
+
+void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
+{
+ BLI_assert(bm->lnor_spacearr != NULL);
+
+ if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) {
+ return;
+ }
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__);
+ float(*oldnors)[3] = preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : NULL;
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+
+ if (preserve_clnor) {
+ BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
+
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+ int l_index = BM_elem_index_get(l);
+
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], *clnor,
+ oldnors[l_index]);
+ }
+ }
+ }
+ }
+
+ if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ BKE_lnor_spacearr_clear(bm->lnor_spacearr);
+ }
+ BM_loops_calc_normal_vcos(
+ bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, true);
+ MEM_freeN(r_lnors);
+
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ if (preserve_clnor) {
+ short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+ int l_index = BM_elem_index_get(l);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], oldnors[l_index],
+ *clnor);
+ }
+ BM_ELEM_API_FLAG_DISABLE(l, BM_LNORSPACE_UPDATE);
+ }
+ }
+ }
+
+ MEM_SAFE_FREE(oldnors);
+ bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
+
+#ifndef NDEBUG
+ BM_lnorspace_err(bm);
+#endif
+}
+
+void BM_lnorspace_update(BMesh *bm)
+{
+ if (bm->lnor_spacearr == NULL) {
+ bm->lnor_spacearr = MEM_callocN(sizeof(*bm->lnor_spacearr), __func__);
+ }
+ if (bm->lnor_spacearr->lspacearr == NULL) {
+ float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
+
+ BM_lnorspacearr_store(bm, lnors);
+
+ MEM_freeN(lnors);
+ }
+ else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) {
+ BM_lnorspace_rebuild(bm, false);
+ }
+}
+
+void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
+{
+ BMFace *f;
+ BMEdge *e;
+ BMIter fiter, eiter;
+ BMLoop *l_curr, *l_first;
+
+ if (do_edges) {
+ int index_edge;
+ BM_ITER_MESH_INDEX(e, &eiter, bm, BM_EDGES_OF_MESH, index_edge) {
+ BMLoop *l_a, *l_b;
+
+ BM_elem_index_set(e, index_edge); /* set_inline */
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+ }
+
+ int index_face, index_loop = 0;
+ BM_ITER_MESH_INDEX(f, &fiter, bm, BM_FACES_OF_MESH, index_face) {
+ BM_elem_index_set(f, index_face); /* set_inline */
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ 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);
+}
+
+/**
+* Auxillary function only used by rebuild to detect if any spaces were not marked as invalid.
+* Reports error if any of the lnor spaces change after rebuilding, meaning that all the possible
+* lnor spaces to be rebuilt were not correctly marked.
+*/
+#ifndef NDEBUG
+void BM_lnorspace_err(BMesh *bm)
+{
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ bool clear = true;
+
+ MLoopNorSpaceArray *temp = MEM_callocN(sizeof(*temp), __func__);
+ temp->lspacearr = NULL;
+
+ BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
+ BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, M_PI, lnors, temp, NULL, cd_loop_clnors_offset, true);
+
+ for (int i = 0; i < bm->totloop; i++) {
+ int j = 0;
+ j += compare_ff(temp->lspacearr[i]->ref_alpha, bm->lnor_spacearr->lspacearr[i]->ref_alpha, 1e-4f);
+ j += compare_ff(temp->lspacearr[i]->ref_beta, bm->lnor_spacearr->lspacearr[i]->ref_beta, 1e-4f);
+ j += compare_v3v3(temp->lspacearr[i]->vec_lnor, bm->lnor_spacearr->lspacearr[i]->vec_lnor, 1e-4f);
+ j += compare_v3v3(temp->lspacearr[i]->vec_ortho, bm->lnor_spacearr->lspacearr[i]->vec_ortho, 1e-4f);
+ j += compare_v3v3(temp->lspacearr[i]->vec_ref, bm->lnor_spacearr->lspacearr[i]->vec_ref, 1e-4f);
+
+ if (j != 5) {
+ clear = false;
+ break;
+ }
+ }
+ BKE_lnor_spacearr_free(temp);
+ MEM_freeN(temp);
+ MEM_freeN(lnors);
+ BLI_assert(clear);
+
+ bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL;
+}
+#endif
+
+static void bm_loop_normal_mark_indiv_do_loop(
+ BMLoop *l, BLI_bitmap *loops, MLoopNorSpaceArray *lnor_spacearr, int *totloopsel)
+{
+ if (l != NULL) {
+ const int l_idx = BM_elem_index_get(l);
+
+ if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
+ /* If vert and face selected share a loop, mark it for editing. */
+ BLI_BITMAP_ENABLE(loops, l_idx);
+ (*totloopsel)++;
+
+ /* Mark all loops in same loop normal space (aka smooth fan). */
+ if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
+ for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) {
+ const int lfan_idx = BM_elem_index_get((BMLoop *)node->link);
+ if (!BLI_BITMAP_TEST(loops, lfan_idx)) {
+ BLI_BITMAP_ENABLE(loops, lfan_idx);
+ (*totloopsel)++;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Mark the individual clnors to be edited, if multiple selection methods are used. */
+static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
+{
+ BMEditSelection *ese, *ese_prev;
+ int totloopsel = 0;
+
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+
+ BLI_assert(bm->lnor_spacearr != NULL);
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+
+ /* Goes from last selected to the first selected element. */
+ for (ese = bm->selected.last; ese; ese = ese->prev) {
+ if (ese->htype == BM_FACE) {
+ ese_prev = ese;
+ /* If current face is selected, then any verts to be edited must have been selected before it. */
+ while ((ese_prev = ese_prev->prev)) {
+ if (ese_prev->htype == BM_VERT) {
+ bm_loop_normal_mark_indiv_do_loop(
+ BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele),
+ loops, bm->lnor_spacearr, &totloopsel);
+ }
+ else if (ese_prev->htype == BM_EDGE) {
+ bm_loop_normal_mark_indiv_do_loop(
+ BM_face_vert_share_loop((BMFace *)ese->ele, ((BMEdge *)ese_prev->ele)->v1),
+ loops, bm->lnor_spacearr, &totloopsel);
+
+ bm_loop_normal_mark_indiv_do_loop(
+ BM_face_vert_share_loop((BMFace *)ese->ele, ((BMEdge *)ese_prev->ele)->v2),
+ loops, bm->lnor_spacearr, &totloopsel);
+ }
+ }
+ }
+ }
+
+ return totloopsel;
+}
+
+static void loop_normal_editdata_init(BMesh *bm, BMLoopNorEditData *lnor_ed, BMVert *v, BMLoop *l, const int offset)
+{
+ BLI_assert(bm->lnor_spacearr != NULL);
+ BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
+
+ const int l_index = BM_elem_index_get(l);
+ short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, offset);
+
+ lnor_ed->loop_index = l_index;
+ lnor_ed->loop = l;
+
+ float custom_normal[3];
+ BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], clnors_data, custom_normal);
+
+ lnor_ed->clnors_data = clnors_data;
+ copy_v3_v3(lnor_ed->nloc, custom_normal);
+ copy_v3_v3(lnor_ed->niloc, custom_normal);
+
+ lnor_ed->loc = v->co;
+}
+
+BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm)
+{
+ BMLoop *l;
+ BMVert *v;
+ BMIter liter, viter;
+
+ bool verts = (bm->selectmode & SCE_SELECT_VERTEX) != 0;
+ bool edges = (bm->selectmode & SCE_SELECT_EDGE) != 0;
+ bool faces = (bm->selectmode & SCE_SELECT_FACE) != 0;
+ int totloopsel = 0;
+
+ BLI_assert(bm->spacearr_dirty == 0);
+
+ BMLoopNorEditDataArray *lnors_ed_arr = MEM_mallocN(
+ sizeof(*lnors_ed_arr), __func__);
+ lnors_ed_arr->lidx_to_lnor_editdata = MEM_callocN(
+ sizeof(*lnors_ed_arr->lidx_to_lnor_editdata) * bm->totloop, __func__);
+
+ if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+ const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+
+ BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__);
+ if (faces && (verts || edges)) {
+ /* More than one selection mode, check for individual normals to edit. */
+ totloopsel = bm_loop_normal_mark_indiv(bm, loops);
+ }
+
+ if (totloopsel) {
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(sizeof(*lnor_ed) * totloopsel, __func__);
+
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
+ loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset);
+ lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed;
+ lnor_ed++;
+ }
+ }
+ }
+ lnors_ed_arr->totloop = totloopsel;
+ }
+ else { /* If multiple selection modes are inactive OR no such loop is found, fall back to editing all loops. */
+ totloopsel = BM_total_loop_select(bm);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(sizeof(*lnor_ed) * totloopsel, __func__);
+
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+ loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset);
+ lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed;
+ lnor_ed++;
+ }
+ }
+ }
+ lnors_ed_arr->totloop = totloopsel;
+ }
+
+ MEM_freeN(loops);
+ lnors_ed_arr->cd_custom_normal_offset = cd_custom_normal_offset;
+ return lnors_ed_arr;
+}
+
+void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr)
+{
+ MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata);
+ MEM_SAFE_FREE(lnors_ed_arr->lidx_to_lnor_editdata);
+ MEM_freeN(lnors_ed_arr);
+}
+
+int BM_total_loop_select(BMesh *bm)
+{
+ int r_sel = 0;
+ BMVert *v;
+ BMIter viter;
+
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ r_sel += BM_vert_face_count(v);
+ }
+ }
+ return r_sel;
+}
+
/**
* \brief BMesh Begin Edit
*
@@ -1089,6 +1525,7 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
/* compute normals, clear temp flags and flush selections */
if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
BM_mesh_normals_update(bm);
}
@@ -1105,6 +1542,9 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
bm->selected = select_history;
}
+ if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ }
}
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4])
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index af7745e4c9f..c7192590b79 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -29,6 +29,7 @@
struct BMAllocTemplate;
struct MLoopNorSpaceArray;
+struct BMLoopNorEditDataArray;
void BM_mesh_elem_toolflags_ensure(BMesh *bm);
void BM_mesh_elem_toolflags_clear(BMesh *bm);
@@ -48,11 +49,25 @@ void BM_mesh_clear(BMesh *bm);
void BM_mesh_normals_update(BMesh *bm);
void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]);
void BM_loops_calc_normal_vcos(
- BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*pnos)[3],
- const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
- struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset);
+ BMesh *bm, const float(*vcos)[3], const float(*vnos)[3], const float(*pnos)[3],
+ const bool use_split_normals, const float split_angle, float(*r_lnos)[3],
+ struct MLoopNorSpaceArray *r_lnors_spacearr, short(*clnors_data)[2],
+ const int cd_loop_clnors_offset, const bool do_rebuild);
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
+void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3]);
+void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all);
+void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
+void BM_lnorspace_update(BMesh *bm);
+void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges);
+#ifndef NDEBUG
+void BM_lnorspace_err(BMesh *bm);
+#endif
+
+/* Loop Generics */
+struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm);
+void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr);
+int BM_total_loop_select(BMesh *bm);
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index b5e6fe168e5..d9093e774e6 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1736,12 +1736,17 @@ static BMOpDefine bmo_bevel_def = {
{"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */
{"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
{"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */
+ {"mark_seam", BMO_OP_SLOT_BOOL}, /* extend edge data to allow seams to run across bevels */
+ {"mark_sharp", BMO_OP_SLOT_BOOL}, /* extend edge data to allow sharp edges to run across bevels */
+ {"strength", BMO_OP_SLOT_FLT}, /* strength of calculated normal in range (0, 1) for custom clnors */
+ {"hnmode", BMO_OP_SLOT_INT}, /* harden normals mode used in bevel if enabled */
{{'\0'}},
},
/* slots_out */
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {"normals.out", BMO_OP_SLOT_MAPPING}, /* output normals per vertex for beveled edges */
{{'\0'}},
},
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 30cd1df9c4e..de87da71e8d 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -244,6 +244,7 @@ typedef enum {
BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1),
BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2),
BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3),
+ BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL = (1 << 4),
} BMOpTypeFlag;
typedef struct BMOperator {
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 80b57eb3565..6d518545967 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -127,6 +127,13 @@ enum {
BEVEL_AMT_PERCENT
};
+enum {
+ BEVEL_HN_NONE, /* Disable harden normals */
+ BEVEL_HN_FACE, /* harden normals according to face area */
+ BEVEL_HN_ADJ, /* harden normals according to adjacent 'beveled' faces */
+ BEVEL_HN_FIX_SHA, /* Special mode to fix normal shading continuity */
+};
+
extern const BMOpDefine *bmo_opdefines[];
extern const int bmo_opdefines_total;
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 2ae87b64286..8bc219d8421 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -43,6 +43,9 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
const bool clamp_overlap = BMO_slot_bool_get(op->slots_in, "clamp_overlap");
const int material = BMO_slot_int_get(op->slots_in, "material");
const bool loop_slide = BMO_slot_bool_get(op->slots_in, "loop_slide");
+ const bool mark_seam = BMO_slot_bool_get(op->slots_in, "mark_seam");
+ const bool mark_sharp = BMO_slot_bool_get(op->slots_in, "mark_sharp");
+ const int hnmode = BMO_slot_int_get(op->slots_in, "hnmode");
if (offset > 0) {
BMOIter siter;
@@ -63,7 +66,9 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide);
+ BM_mesh_bevel(
+ bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material,
+ loop_slide, mark_seam, mark_sharp, hnmode, op);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 33380cee18e..0415526574d 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -34,6 +34,7 @@
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "BLI_array.h"
#include "BLI_alloca.h"
@@ -43,6 +44,7 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
+#include "BKE_mesh.h"
#include "eigen_capi.h"
@@ -150,6 +152,8 @@ typedef struct BoundVert {
Profile profile; /* edge profile between this and next BoundVert */
bool any_seam; /* are any of the edges attached here seams? */
bool visited; /* used during delta adjust pass */
+ int seam_len; /* length of seam starting from current boundvert to next boundvert with ccw ordering */
+ int sharp_len; /* Same as seam_len but defines length of sharp edges */
// int _pad;
} BoundVert;
@@ -188,6 +192,8 @@ typedef struct BevelParams {
/* hash of BevVert for each vertex involved in bevel
* GHash: (key=(BMVert *), value=(BevVert *)) */
GHash *vert_hash;
+ /* Hash set used to store resultant beveled faces for VMesh when poly is ring */
+ GHash *faceHash;
MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */
ProfileSpacing pro_spacing; /* parameter values for evenly spaced profiles */
@@ -200,9 +206,12 @@ typedef struct BevelParams {
bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
bool limit_offset; /* should offsets be limited by collisions? */
bool offset_adjust; /* should offsets be adjusted to try to get even widths? */
+ bool mark_seam;
+ bool mark_sharp;
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
+ int hnmode;
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
@@ -767,6 +776,11 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
}
+ else {
+ /* shup up 'maybe unused' warnings */
+ zero_v3(dir1n);
+ zero_v3(dir2p);
+ }
ang = angle_v3v3(dir1, dir2);
if (ang < BEVEL_EPSILON_ANG) {
@@ -1522,8 +1536,219 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
co[2] = z;
}
+#define BEV_EXTEND_EDGE_DATA_CHECK(eh, flag) (BM_elem_flag_test(eh->e, flag))
+
+static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
+{
+ EdgeHalf *e = &bv->edges[0], *efirst = &bv->edges[0];
+
+ /* First first edge with seam or sharp edge data */
+ while ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
+ e = e->next;
+ if (e == efirst)
+ break;
+ }
+
+ /* If no such edge found, return */
+ if ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag)))
+ return;
+
+ /* Set efirst to this first encountered edge. */
+ efirst = e;
+
+ do {
+ int flag_count = 0;
+ EdgeHalf *ne = e->next;
+
+ while (((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(ne, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(ne, flag))) &&
+ ne != efirst)
+ {
+ if (ne->is_bev)
+ flag_count++;
+ ne = ne->next;
+ }
+ if (ne == e || (ne == efirst && ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag)) ||
+ (neg && BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag)))))
+ {
+ break;
+ }
+ /* Set seam_len / sharp_len of starting edge */
+ if (flag == BM_ELEM_SEAM) {
+ e->rightv->seam_len = flag_count;
+ }
+ else if (flag == BM_ELEM_SMOOTH) {
+ e->rightv->sharp_len = flag_count;
+ }
+ e = ne;
+ } while (e != efirst);
+}
+
+static void bevel_extend_edge_data(BevVert *bv)
+{
+ VMesh *vm = bv->vmesh;
+
+ BoundVert *bcur = bv->vmesh->boundstart, *start = bcur;
+
+ do {
+ /* If current boundvert has a seam length > 0 then it has a seam running along its edges */
+ if (bcur->seam_len) {
+ if (!bv->vmesh->boundstart->seam_len && start == bv->vmesh->boundstart)
+ start = bcur; /* set start to first boundvert with seam_len > 0 */
+
+ /* Now for all the mesh_verts starting at current index and ending at idxlen
+ * We go through outermost ring and through all its segments and add seams
+ * for those edges */
+ int idxlen = bcur->index + bcur->seam_len;
+ for (int i = bcur->index; i < idxlen; i++) {
+ BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
+ BMEdge *e;
+ for (int k = 1; k < vm->seg; k++) {
+ v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
+
+ /* Here v1 & v2 are current and next BMverts, we find common edge and set its edge data */
+ e = v1->e;
+ while (e->v1 != v2 && e->v2 != v2) {
+ if (e->v1 == v1)
+ e = e->v1_disk_link.next;
+ else
+ e = e->v2_disk_link.next;
+ }
+ BM_elem_flag_set(e, BM_ELEM_SEAM, true);
+ v1 = v2;
+ }
+ BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
+ e = v1->e; //Do same as above for first and last vert
+ while (e->v1 != v3 && e->v2 != v3) {
+ if (e->v1 == v1)
+ e = e->v1_disk_link.next;
+ else
+ e = e->v2_disk_link.next;
+ }
+ BM_elem_flag_set(e, BM_ELEM_SEAM, true);
+ bcur = bcur->next;
+ }
+ }
+ else
+ bcur = bcur->next;
+ } while (bcur != start);
+
+
+ bcur = bv->vmesh->boundstart;
+ start = bcur;
+ do {
+ if (bcur->sharp_len) {
+ if (!bv->vmesh->boundstart->sharp_len && start == bv->vmesh->boundstart)
+ start = bcur;
+
+ int idxlen = bcur->index + bcur->sharp_len;
+ for (int i = bcur->index; i < idxlen; i++) {
+ BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
+ BMEdge *e;
+ for (int k = 1; k < vm->seg; k++) {
+ v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
+
+ e = v1->e;
+ while (e->v1 != v2 && e->v2 != v2) {
+ if (e->v1 == v1)
+ e = e->v1_disk_link.next;
+ else
+ e = e->v2_disk_link.next;
+ }
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
+ v1 = v2;
+ }
+ BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
+ e = v1->e;
+ while (e->v1 != v3 && e->v2 != v3) {
+ if (e->v1 == v1)
+ e = e->v1_disk_link.next;
+ else
+ e = e->v2_disk_link.next;
+ }
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
+ bcur = bcur->next;
+ }
+ }
+ else
+ bcur = bcur->next;
+ } while (bcur != start);
+}
+
+static void bevel_harden_normals_mode(BevelParams *bp, BevVert *bv, BMOperator *op)
+{
+ if (bp->hnmode == BEVEL_HN_NONE)
+ return;
+
+ VMesh *vm = bv->vmesh;
+ BoundVert *bcur = vm->boundstart, *bstart = bcur;
+
+ BMEdge *e;
+ BMIter eiter;
+
+ BMOpSlot *nslot = BMO_slot_get(op->slots_out, "normals.out");
+ float n_final[3] = { 0.0f, 0.0f, 0.0f };
+
+ if (bp->hnmode == BEVEL_HN_FACE) {
+ GHash *tempfaceHash = BLI_ghash_int_new(__func__);
+
+ /* Iterate through all faces of current BMVert and add their normal*face_area to n_final */
+ BM_ITER_ELEM(e, &eiter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+
+ BMFace *f_a, *f_b;
+ BM_edge_face_pair(e, &f_a, &f_b);
+
+ if (f_a && !BLI_ghash_haskey(tempfaceHash, SET_UINT_IN_POINTER(BM_elem_index_get(f_a)))) {
+ int f_area = BM_face_calc_area(f_a);
+ float f_no[3];
+ copy_v3_v3(f_no, f_a->no);
+ mul_v3_fl(f_no, f_area);
+ add_v3_v3(n_final, f_no);
+ BLI_ghash_insert(tempfaceHash, SET_UINT_IN_POINTER(BM_elem_index_get(f_a)), NULL);
+ }
+ if (f_b && !BLI_ghash_haskey(tempfaceHash, SET_UINT_IN_POINTER(BM_elem_index_get(f_b)))) {
+ int f_area = BM_face_calc_area(f_b);
+ float f_no[3];
+ copy_v3_v3(f_no, f_b->no);
+ mul_v3_fl(f_no, f_area);
+ add_v3_v3(n_final, f_no);
+ BLI_ghash_insert(tempfaceHash, SET_UINT_IN_POINTER(BM_elem_index_get(f_b)), NULL);
+ }
+ }
+ }
+ BLI_ghash_free(tempfaceHash, NULL, NULL);
+ normalize_v3(n_final);
+ }
+ else if (bp->hnmode == BEVEL_HN_ADJ) {
+ BM_ITER_ELEM(e, &eiter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ if (e->v1 == bv->v) {
+ add_v3_v3(n_final, e->v2->no);
+ }
+ else {
+ add_v3_v3(n_final, e->v1->no);
+ }
+ }
+ }
+ normalize_v3(n_final);
+ }
+
+ do {
+ /* Set normals.out for vertices as computed earlier */
+ if (BMO_slot_map_contains(nslot, bcur->nv.v) != true) {
+
+ float(*vert_normal) = MEM_callocN(sizeof(*vert_normal) * 3, __func__);
+ add_v3_v3(vert_normal, n_final);
+ normalize_v3(vert_normal);
+
+ BMO_slot_map_insert(op, nslot, bcur->nv.v, vert_normal);
+ }
+ bcur = bcur->next;
+ } while (bcur != bstart);
+}
+
/* Set the any_seam property for a BevVert and all its BoundVerts */
-static void set_bound_vert_seams(BevVert *bv)
+static void set_bound_vert_seams(BevVert *bv, bool mark_seam, bool mark_sharp)
{
BoundVert *v;
EdgeHalf *e;
@@ -1539,6 +1764,13 @@ static void set_bound_vert_seams(BevVert *bv)
}
bv->any_seam |= v->any_seam;
} while ((v = v->next) != bv->vmesh->boundstart);
+
+ if (mark_seam) {
+ check_edge_data_seam_sharp_edges(bv, BM_ELEM_SEAM, false);
+ }
+ if (mark_sharp) {
+ check_edge_data_seam_sharp_edges(bv, BM_ELEM_SMOOTH, true);
+ }
}
static int count_bound_vert_seams(BevVert *bv)
@@ -1609,7 +1841,7 @@ static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool constr
calculate_vm_profiles(bp, bv, vm);
if (construct) {
- set_bound_vert_seams(bv);
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
if (vm->count == 2)
vm->mesh_kind = M_NONE;
else if (bp->seg == 1)
@@ -1664,7 +1896,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
e->next->leftv = e->next->rightv = v;
/* could use M_POLY too, but tri-fan looks nicer)*/
vm->mesh_kind = M_TRI_FAN;
- set_bound_vert_seams(bv);
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
}
else {
adjust_bound_vert(e->next->leftv, co);
@@ -1723,7 +1955,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
}
if (construct) {
- set_bound_vert_seams(bv);
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
if (vm->count == 2 && bv->edgecount == 3) {
vm->mesh_kind = M_NONE;
@@ -1865,7 +2097,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
calculate_vm_profiles(bp, bv, vm);
if (construct) {
- set_bound_vert_seams(bv);
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
if (vm->count == 2) {
vm->mesh_kind = M_NONE;
@@ -2919,29 +3151,34 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
}
/* Is this a good candidate for using tri_corner_adj_vmesh? */
-static bool tri_corner_test(BevelParams *bp, BevVert *bv)
+static int tri_corner_test(BevelParams *bp, BevVert *bv)
{
float ang, totang, angdiff;
EdgeHalf *e;
int i;
+ int in_plane_e = 0;
- if (bv->edgecount != 3 || bv->selcount != 3)
- return false;
totang = 0.0f;
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < bv->edgecount; i++) {
e = &bv->edges[i];
ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f);
- if (ang <= (float) M_PI_4 || ang >= 3.0f * (float) M_PI_4)
- return false;
+ if (ang <= M_PI_4)
+ in_plane_e++;
+ else if (ang >= 3.0f * (float) M_PI_4)
+ return -1;
totang += ang;
}
+ if (in_plane_e != bv->edgecount - 3)
+ return -1;
angdiff = fabsf(totang - 3.0f * (float)M_PI_2);
if ((bp->pro_super_r == PRO_SQUARE_R && angdiff > (float)M_PI / 16.0f) ||
(angdiff > (float)M_PI_4))
{
- return false;
+ return -1;
}
- return true;
+ if (bv->edgecount != 3 || bv->selcount != 3)
+ return 0;
+ return 1;
}
static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
@@ -2952,7 +3189,7 @@ static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
VMesh *vm;
BoundVert *bndv;
- BLI_assert(bv->edgecount == 3 && bv->selcount == 3);
+ /*BLI_assert(bv->edgecount == 3 && bv->selcount == 3); Add support for in plane edges */
bndv = bv->vmesh->boundstart;
copy_v3_v3(co0, bndv->nv.co);
bndv = bndv->next;
@@ -2985,9 +3222,14 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
BoundVert *bndv;
MemArena *mem_arena = bp->mem_arena;
float r, fac, fullness;
+ n = bv->vmesh->count;
+
+ /* Same bevel as that of 3 edges of vert in a cube */
+ if (n == 3 && tri_corner_test(bp, bv) != -1 && bp->pro_super_r != PRO_SQUARE_IN_R) {
+ return tri_corner_adj_vmesh(bp, bv);
+ }
/* First construct an initial control mesh, with nseg==2 */
- n = bv->vmesh->count;
ns = bv->vmesh->seg;
vm0 = new_adj_vmesh(mem_arena, n, 2, bv->vmesh->boundstart);
@@ -3430,7 +3672,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
VMesh *vm1, *vm;
BoundVert *v;
BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- BMFace *f, *f2;
+ BMFace *f, *f2, *r_f;
BMEdge *bme, *bme1, *bme2, *bme3;
EdgeHalf *e;
BoundVert *vpipe;
@@ -3442,6 +3684,17 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
odd = ns % 2;
BLI_assert(n >= 3 && ns > 1);
+ /* Add support for profiles in vertex only in-plane bevels */
+ if (bp->vertex_only) {
+ v = bv->vmesh->boundstart;
+ do {
+ Profile *pro = &v->profile;
+ pro->super_r = bp->pro_super_r;
+ copy_v3_v3(pro->midco, bv->v->co);
+ calculate_profile(bp, v);
+ v = v->next;
+ } while (v != bv->vmesh->boundstart);
+ }
vpipe = pipe_test(bv);
@@ -3451,7 +3704,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
else if (vpipe) {
vm1 = pipe_adj_vmesh(bp, bv, vpipe);
}
- else if (tri_corner_test(bp, bv)) {
+ else if (tri_corner_test(bp, bv) == 1) {
vm1 = tri_corner_adj_vmesh(bp, bv);
/* the PRO_SQUARE_IN_R profile has boundary edges that merge
* and no internal ring polys except possibly center ngon */
@@ -3464,6 +3717,8 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
vm1 = adj_vmesh(bp, bv);
}
+ bool do_fix_shading_bv = bp->faceHash != NULL;
+
/* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */
vm = bv->vmesh;
for (i = 0; i < n; i++) {
@@ -3505,24 +3760,24 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
if (bp->vertex_only) {
if (j < k) {
if (k == ns2 && j == ns2 - 1) {
- bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
+ r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
NULL, NULL, v->next->efirst->e, bme, mat_nr);
}
else {
- bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
}
}
else if (j > k) {
- bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
}
else { /* j == k */
/* only one edge attached to v, since vertex_only */
if (e->is_seam) {
- bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
+ r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
bme, NULL, bme, NULL, mat_nr);
}
else {
- bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f,
+ r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f,
bme, NULL, bme, NULL, mat_nr);
}
}
@@ -3531,25 +3786,27 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
if (odd) {
if (k == ns2) {
if (e->is_seam) {
- bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
+ r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
NULL, bme, bme, NULL, mat_nr);
}
else {
- bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
}
}
else {
- bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, mat_nr);
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, mat_nr);
}
}
else {
bme1 = k == ns2 - 1 ? bme : NULL;
bme3 = j == ns2 - 1 ? v->prev->ebev->e : NULL;
bme2 = bme1 != NULL ? bme1 : bme3;
- bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
+ r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
NULL, bme1, bme2, bme3, mat_nr);
}
}
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, r_f, NULL);
}
}
} while ((v = v->next) != vm->boundstart);
@@ -3622,6 +3879,8 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
+ bool do_fix_shading_bv = bp->faceHash != NULL;
+
if (bv->any_seam) {
frep = boundvert_rep_face(vm->boundstart, &frep2);
if (frep2 && frep && is_bad_uv_poly(bv, frep)) {
@@ -3667,6 +3926,8 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
} while ((v = v->next) != vm->boundstart);
if (n > 2) {
f = bev_create_ngon(bm, vv, n, vf, frep, ve, bp->mat_nr, true);
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, f, NULL);
}
else {
f = NULL;
@@ -3681,6 +3942,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
{
BMFace *f;
BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1);
+ bool do_fix_shading_bv = bp->faceHash != NULL;
f = bevel_build_poly(bp, bm, bv);
@@ -3689,6 +3951,11 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
BMVert *v_fan = l_fan->v;
+ if (f->len == 3) {
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, f, NULL);
+ }
+
while (f->len > 3) {
BMLoop *l_new;
BMFace *f_new;
@@ -3709,6 +3976,8 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; }
else { BLI_assert(0); }
}
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, f_new, NULL);
}
}
}
@@ -3717,6 +3986,7 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
{
BMFace *f;
BLI_assert(bv->selcount == 2);
+ bool do_fix_shading_bv = bp->faceHash != NULL;
f = bevel_build_poly(bp, bm, bv);
@@ -3728,6 +3998,11 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
BMLoop *l_b = BM_face_vert_share_loop(f, eh_b->leftv->nv.v);
int split_count = bv->vmesh->seg + 1; /* ensure we don't walk past the segments */
+ if (f->len == 4) {
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, f, NULL);
+ }
+
while (f->len > 4 && split_count > 0) {
BMLoop *l_new;
BLI_assert(l_a->f == f);
@@ -3746,6 +4021,9 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
/* walk around the new face to get the next verts to split */
l_a = l_new->prev;
l_b = l_new->next->next;
+
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, f, NULL);
}
split_count--;
}
@@ -3808,6 +4086,13 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
flag_out_edge(bm, bme);
}
}
+ else if (bp->faceHash) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_ELEM(f, &fiter, bv->v, BM_FACES_OF_VERT) {
+ BLI_ghash_insert(bp->faceHash, f, NULL);
+ }
+ }
}
/* Given that the boundary is built, now make the actual BMVerts
@@ -4722,13 +5007,15 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
VMesh *vm1, *vm2;
EdgeHalf *e1, *e2;
BMEdge *bme1, *bme2, *center_bme;
- BMFace *f1, *f2, *f;
+ BMFace *f1, *f2, *f, *r_f;
BMVert *verts[4];
BMFace *faces[4];
BMEdge *edges[4];
int k, nseg, i1, i2, odd, mid;
int mat_nr = bp->mat_nr;
+ bool do_fix_shading_bv = bp->faceHash != NULL;
+
if (!BM_edge_is_manifold(bme))
return;
@@ -4784,18 +5071,18 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
/* straddles a seam: choose to interpolate in f1 and snap right edge to bme */
edges[0] = edges[1] = NULL;
edges[2] = edges[3] = bme;
- bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
}
else {
/* straddles but not a seam: interpolate left half in f1, right half in f2 */
- bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
}
}
else if (!odd && k == mid) {
/* left poly that touches an even center line on right */
edges[0] = edges[1] = NULL;
edges[2] = edges[3] = bme;
- bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
center_bme = BM_edge_exists(verts[2], verts[3]);
BLI_assert(center_bme != NULL);
}
@@ -4803,13 +5090,15 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
/* right poly that touches an even center line on left */
edges[0] = edges[1] = bme;
edges[2] = edges[3] = NULL;
- bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
}
else {
/* doesn't cross or touch the center line, so interpolate in appropriate f1 or f2 */
f = (k <= mid) ? f1 : f2;
- bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
}
+ if (do_fix_shading_bv)
+ BLI_ghash_insert(bp->faceHash, r_f, NULL);
verts[0] = verts[3];
verts[1] = verts[2];
}
@@ -4930,7 +5219,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
double sum;
double temp;
- bool precision_reached;
+ bool precision_reached = true;
bool seg_odd = seg % 2;
bool rbig;
@@ -5349,7 +5638,8 @@ void BM_mesh_bevel(
const float segments, const float profile,
const bool vertex_only, const bool use_weights, const bool limit_offset,
const struct MDeformVert *dvert, const int vertex_group, const int mat,
- const bool loop_slide)
+ const bool loop_slide, const bool mark_seam, const bool mark_sharp,
+ const int hnmode, void *mod_bmop_customdata)
{
BMIter iter;
BMVert *v, *v_next;
@@ -5358,6 +5648,9 @@ void BM_mesh_bevel(
BevelParams bp = {NULL};
GHashIterator giter;
+ BMOperator *op = NULL;
+ BevelModNorEditData *clnordata;
+
bp.offset = offset;
bp.offset_type = offset_type;
bp.seg = segments;
@@ -5370,8 +5663,12 @@ void BM_mesh_bevel(
bp.dvert = dvert;
bp.vertex_group = vertex_group;
bp.mat_nr = mat;
+ bp.mark_seam = mark_seam;
+ bp.mark_sharp = mark_sharp;
+ bp.hnmode = hnmode;
+ bp.faceHash = NULL;
- if (profile >= 0.999f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */
+ if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */
bp.pro_super_r = PRO_SQUARE_R;
}
@@ -5382,6 +5679,15 @@ void BM_mesh_bevel(
BLI_memarena_use_calloc(bp.mem_arena);
set_profile_spacing(&bp);
+ /* Stores BMOp if executed through tool else stores BevelModNorEditData */
+ if (bm->use_toolflags)
+ op = mod_bmop_customdata;
+ else {
+ clnordata = mod_bmop_customdata;
+ clnordata->faceHash = BLI_ghash_ptr_new(__func__);
+ bp.faceHash = clnordata->faceHash;
+ }
+
/* Analyze input vertices, sorting edges and assigning initial new vertex positions */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
@@ -5426,6 +5732,15 @@ void BM_mesh_bevel(
}
}
+ /* Extend edge data like sharp edges and precompute normals for harden */
+ GHASH_ITER(giter, bp.vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ bevel_extend_edge_data(bv);
+ if (bm->use_toolflags) {
+ bevel_harden_normals_mode(&bp, bv, op);
+ }
+ }
+
/* Rebuild face polygons around affected vertices */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index 386dc8a1fce..f8a77d431cc 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -33,6 +33,7 @@ void BM_mesh_bevel(
BMesh *bm, const float offset, const int offset_type, const float segments,
const float profile, const bool vertex_only, const bool use_weights,
const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
- const int mat, const bool loop_slide);
+ const int mat, const bool loop_slide, const bool mark_seam, const bool mark_sharp,
+ const int hnmode, void *mod_bmop_customdata);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 47d8f4f52bb..248c780102c 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -69,6 +69,7 @@ void SceneExporter::exportHierarchy(bContext *C, Depsgraph *depsgraph, Scene *sc
case OB_CAMERA:
case OB_LAMP:
case OB_EMPTY:
+ case OB_GPENCIL:
case OB_ARMATURE:
base_objects.push_back(ob);
break;
@@ -122,6 +123,7 @@ void SceneExporter::writeNodes(bContext *C, Depsgraph *depsgraph, Object *ob, Sc
case OB_CAMERA:
case OB_LAMP:
case OB_EMPTY:
+ case OB_GPENCIL:
case OB_ARMATURE:
if (bc_is_marked(cob))
child_objects.push_back(cob);
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index a141495e5ae..261a1218d2d 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -183,6 +183,11 @@ set(SRC
operations/COM_SunBeamsOperation.cpp
operations/COM_SunBeamsOperation.h
+ nodes/COM_CryptomatteNode.cpp
+ nodes/COM_CryptomatteNode.h
+ operations/COM_CryptomatteOperation.cpp
+ operations/COM_CryptomatteOperation.h
+
nodes/COM_CornerPinNode.cpp
nodes/COM_CornerPinNode.h
nodes/COM_PlaneTrackDeformNode.cpp
diff --git a/source/blender/compositor/intern/COM_CPUDevice.h b/source/blender/compositor/intern/COM_CPUDevice.h
index f98a75e5978..b938b5fc588 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.h
+++ b/source/blender/compositor/intern/COM_CPUDevice.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CPUDevice_h
-#define _COM_CPUDevice_h
+#ifndef __COM_CPUDEVICE_H__
+#define __COM_CPUDEVICE_H__
#include "COM_Device.h"
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.h b/source/blender/compositor/intern/COM_ChunkOrder.h
index 4728b771e3c..f61816c6511 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.h
+++ b/source/blender/compositor/intern/COM_ChunkOrder.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ChunkOrder_h_
-#define _COM_ChunkOrder_h_
+#ifndef __COM_CHUNKORDER_H__
+#define __COM_CHUNKORDER_H__
#include "COM_ChunkOrderHotspot.h"
class ChunkOrder {
diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
index 09e9fa44c3b..620980518ef 100644
--- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
+++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ChunkOrderHotSpot_h_
-#define _COM_ChunkOrderHotSpot_h_
+#ifndef __COM_CHUNKORDERHOTSPOT_H__
+#define __COM_CHUNKORDERHOTSPOT_H__
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 1c702503915..b43e163870c 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CompositorContext_h
-#define _COM_CompositorContext_h
+#ifndef __COM_COMPOSITORCONTEXT_H__
+#define __COM_COMPOSITORCONTEXT_H__
#include <vector>
#include <string>
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 58e0da04e5e..c9181905908 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -55,6 +55,7 @@ extern "C" {
#include "COM_Converter.h"
#include "COM_CornerPinNode.h"
#include "COM_CropNode.h"
+#include "COM_CryptomatteNode.h"
#include "COM_DefocusNode.h"
#include "COM_DespeckleNode.h"
#include "COM_DifferenceMatteNode.h"
@@ -406,6 +407,9 @@ Node *Converter::convert(bNode *b_node)
case CMP_NODE_SUNBEAMS:
node = new SunBeamsNode(b_node);
break;
+ case CMP_NODE_CRYPTOMATTE:
+ node = new CryptomatteNode(b_node);
+ break;
}
return node;
}
diff --git a/source/blender/compositor/intern/COM_Converter.h b/source/blender/compositor/intern/COM_Converter.h
index b57220351e8..d0b888e24a0 100644
--- a/source/blender/compositor/intern/COM_Converter.h
+++ b/source/blender/compositor/intern/COM_Converter.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_Converter_h
-#define _COM_Converter_h
+#ifndef __COM_CONVERTER_H__
+#define __COM_CONVERTER_H__
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
index f5db93e8825..8a5014afb96 100644
--- a/source/blender/compositor/intern/COM_Debug.h
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_Debug_h
-#define _COM_Debug_h
+#ifndef __COM_DEBUG_H__
+#define __COM_DEBUG_H__
#include <map>
#include <string>
diff --git a/source/blender/compositor/intern/COM_Device.h b/source/blender/compositor/intern/COM_Device.h
index 4ab6e1e2f96..202ca1d0b4f 100644
--- a/source/blender/compositor/intern/COM_Device.h
+++ b/source/blender/compositor/intern/COM_Device.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_Device_h
-#define _COM_Device_h
+#ifndef __COM_DEVICE_H__
+#define __COM_DEVICE_H__
#include "COM_WorkPackage.h"
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 20ffbeaa357..88c702b8477 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ExecutionGroup_h
-#define _COM_ExecutionGroup_h
+#ifndef __COM_EXECUTIONGROUP_H__
+#define __COM_EXECUTIONGROUP_H__
#include "COM_Node.h"
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index acde4a9b772..0990df31c55 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -22,8 +22,8 @@
class ExecutionGroup;
-#ifndef _COM_ExecutionSystem_h
-#define _COM_ExecutionSystem_h
+#ifndef __COM_EXECUTIONSYSTEM_H__
+#define __COM_EXECUTIONSYSTEM_H__
#include "DNA_color_types.h"
#include "DNA_node_types.h"
@@ -185,4 +185,4 @@ private:
#endif
};
-#endif /* _COM_ExecutionSystem_h */
+#endif /* __COM_EXECUTIONSYSTEM_H__ */
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index be948b3e99b..5f6485475d0 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -22,8 +22,8 @@
class MemoryBuffer;
-#ifndef _COM_MemoryBuffer_h_
-#define _COM_MemoryBuffer_h_
+#ifndef __COM_MEMORYBUFFER_H__
+#define __COM_MEMORYBUFFER_H__
#include "COM_ExecutionGroup.h"
#include "COM_MemoryProxy.h"
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h
index b732db37db2..a628c09fa1f 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.h
+++ b/source/blender/compositor/intern/COM_MemoryProxy.h
@@ -23,8 +23,8 @@
class MemoryProxy;
-#ifndef _COM_MemoryProxy_h_
-#define _COM_MemoryProxy_h_
+#ifndef __COM_MEMORYPROXY_H__
+#define __COM_MEMORYPROXY_H__
#include "COM_ExecutionGroup.h"
class ExecutionGroup;
diff --git a/source/blender/compositor/intern/COM_NodeConverter.h b/source/blender/compositor/intern/COM_NodeConverter.h
index 825c26bb7af..4fb6b70ad1b 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.h
+++ b/source/blender/compositor/intern/COM_NodeConverter.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_NodeCompiler_h
-#define _COM_NodeCompiler_h
+#ifndef __COM_NODECONVERTER_H__
+#define __COM_NODECONVERTER_H__
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
@@ -118,4 +118,4 @@ private:
#endif
};
-#endif /* _COM_NodeCompiler_h */
+#endif /* __COM_NODECONVERTER_H__ */
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
index 7c6322d2a42..4513a7721d6 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.h
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_NodeGraph_h
-#define _COM_NodeGraph_h
+#ifndef __COM_NODEGRAPH_H__
+#define __COM_NODEGRAPH_H__
#include <map>
#include <set>
@@ -113,4 +113,4 @@ protected:
#endif
};
-#endif /* _COM_NodeGraph_h */
+#endif /* __COM_NODEGRAPH_H__ */
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 5ee3cc22b53..9ab9156e7e4 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_Operation_h
-#define _COM_Operation_h
+#ifndef __COM_NODEOPERATION_H__
+#define __COM_NODEOPERATION_H__
#include <list>
#include <string>
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
index 0eafd27b46a..71622b1e9bb 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_NodeCompilerImpl_h
-#define _COM_NodeCompilerImpl_h
+#ifndef __COM_NODEOPERATIONBUILDER_H__
+#define __COM_NODEOPERATIONBUILDER_H__
#include <map>
#include <set>
@@ -167,4 +167,4 @@ private:
#endif
};
-#endif /* _COM_NodeCompilerImpl_h */
+#endif /* __COM_NODEOPERATIONBUILDER_H__ */
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index fa358f65ddf..a3a5cd36902 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -22,8 +22,8 @@
class OpenCLDevice;
-#ifndef _COM_OpenCLDevice_h
-#define _COM_OpenCLDevice_h
+#ifndef __COM_OPENCLDEVICE_H__
+#define __COM_OPENCLDEVICE_H__
#include "COM_Device.h"
#include "clew.h"
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.h b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
index e0dc06ef733..b582e47dba7 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.h
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SingleThreadedOperation_h
-#define _COM_SingleThreadedOperation_h
+#ifndef __COM_SINGLETHREADEDOPERATION_H__
+#define __COM_SINGLETHREADEDOPERATION_H__
#include "COM_NodeOperation.h"
class SingleThreadedOperation : public NodeOperation {
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index ff72d925184..af6b891e7ab 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SocketReader_h
-#define _COM_SocketReader_h
+#ifndef __COM_SOCKETREADER_H__
+#define __COM_SOCKETREADER_H__
#include "BLI_rect.h"
#include "COM_defines.h"
@@ -121,4 +121,4 @@ public:
#endif
};
-#endif /* _COM_SocketReader_h */
+#endif /* __COM_SOCKETREADER_H__ */
diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h
index 970a69b38d8..b0a74a1b0ee 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.h
+++ b/source/blender/compositor/intern/COM_WorkPackage.h
@@ -22,8 +22,8 @@
class WorkPackage;
-#ifndef _COM_WorkPackage_h_
-#define _COM_WorkPackage_h_
+#ifndef __COM_WORKPACKAGE_H__
+#define __COM_WORKPACKAGE_H__
class ExecutionGroup;
#include "COM_ExecutionGroup.h"
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h
index 14b02e70913..a08b3856a8b 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.h
+++ b/source/blender/compositor/intern/COM_WorkScheduler.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_WorkScheduler_h_
-#define _COM_WorkScheduler_h_
+#ifndef __COM_WORKSCHEDULER_H__
+#define __COM_WORKSCHEDULER_H__
#include "COM_ExecutionGroup.h"
extern "C" {
@@ -120,4 +120,4 @@ public:
#endif
};
-#endif /* _COM_WorkScheduler_h_ */
+#endif /* __COM_WORKSCHEDULER_H__ */
diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.h b/source/blender/compositor/nodes/COM_AlphaOverNode.h
index b1fe85cf800..0af2ea3310d 100644
--- a/source/blender/compositor/nodes/COM_AlphaOverNode.h
+++ b/source/blender/compositor/nodes/COM_AlphaOverNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_AlphaOverNode_h_
-#define _COM_AlphaOverNode_h_
+#ifndef __COM_ALPHAOVERNODE_H__
+#define __COM_ALPHAOVERNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BilateralBlurNode.h b/source/blender/compositor/nodes/COM_BilateralBlurNode.h
index 6d13cd5b96a..babb558e0d1 100644
--- a/source/blender/compositor/nodes/COM_BilateralBlurNode.h
+++ b/source/blender/compositor/nodes/COM_BilateralBlurNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BilateralBlurNode_h_
-#define _COM_BilateralBlurNode_h_
+#ifndef __COM_BILATERALBLURNODE_H__
+#define __COM_BILATERALBLURNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BlurNode.h b/source/blender/compositor/nodes/COM_BlurNode.h
index fecba9c0eef..9a5f5ea1efd 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.h
+++ b/source/blender/compositor/nodes/COM_BlurNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BlurNode_h_
-#define _COM_BlurNode_h_
+#ifndef __COM_BLURNODE_H__
+#define __COM_BLURNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.h b/source/blender/compositor/nodes/COM_BokehBlurNode.h
index 2c8d52ad277..48cd661a7bf 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.h
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BokehBlurNode_h_
-#define _COM_BokehBlurNode_h_
+#ifndef __COM_BOKEHBLURNODE_H__
+#define __COM_BOKEHBLURNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.h b/source/blender/compositor/nodes/COM_BokehImageNode.h
index 36ee1300661..70f363b8cf6 100644
--- a/source/blender/compositor/nodes/COM_BokehImageNode.h
+++ b/source/blender/compositor/nodes/COM_BokehImageNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BokehImageNode_h_
-#define _COM_BokehImageNode_h_
+#ifndef __COM_BOKEHIMAGENODE_H__
+#define __COM_BOKEHIMAGENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BoxMaskNode.h b/source/blender/compositor/nodes/COM_BoxMaskNode.h
index 8229aa58ac1..01557229be9 100644
--- a/source/blender/compositor/nodes/COM_BoxMaskNode.h
+++ b/source/blender/compositor/nodes/COM_BoxMaskNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BoxMaskNode_h_
-#define _COM_BoxMaskNode_h_
+#ifndef __COM_BOXMASKNODE_H__
+#define __COM_BOXMASKNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.h b/source/blender/compositor/nodes/COM_BrightnessNode.h
index bacd3510517..27155e27774 100644
--- a/source/blender/compositor/nodes/COM_BrightnessNode.h
+++ b/source/blender/compositor/nodes/COM_BrightnessNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BrightnessNode_h_
-#define _COM_BrightnessNode_h_
+#ifndef __COM_BRIGHTNESSNODE_H__
+#define __COM_BRIGHTNESSNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.h b/source/blender/compositor/nodes/COM_ChannelMatteNode.h
index f528578e6dd..c5f062cb215 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ChannelMatteNode_h_
-#define _COM_ChannelMatteNode_h_
+#ifndef __COM_CHANNELMATTENODE_H__
+#define __COM_CHANNELMATTENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.h b/source/blender/compositor/nodes/COM_ChromaMatteNode.h
index d1eb3a907ef..7d0b34ecf5d 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ChromaMatteNode_h_
-#define _COM_ChromaMatteNode_h_
+#ifndef __COM_CHROMAMATTENODE_H__
+#define __COM_CHROMAMATTENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.h b/source/blender/compositor/nodes/COM_ColorBalanceNode.h
index 1244dbbb7c5..d203fef20f4 100644
--- a/source/blender/compositor/nodes/COM_ColorBalanceNode.h
+++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorBalanceNode_h_
-#define _COM_ColorBalanceNode_h_
+#ifndef __COM_COLORBALANCENODE_H__
+#define __COM_COLORBALANCENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.h b/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
index d943136ceb8..fcbd7631cb4 100644
--- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
+++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorCorrectionNode_h_
-#define _COM_ColorCorrectionNode_h_
+#ifndef __COM_COLORCORRECTIONNODE_H__
+#define __COM_COLORCORRECTIONNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.h b/source/blender/compositor/nodes/COM_ColorCurveNode.h
index 0f99625e31a..ad51611d1cf 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.h
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorCurveNode_h_
-#define _COM_ColorCurveNode_h_
+#ifndef __COM_COLORCURVENODE_H__
+#define __COM_COLORCURVENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.h b/source/blender/compositor/nodes/COM_ColorMatteNode.h
index c17d3eb6c4e..f2c3c08beea 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ColorMatteNode_h_
-#define _COM_ColorMatteNode_h_
+#ifndef __COM_COLORMATTENODE_H__
+#define __COM_COLORMATTENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorNode.h b/source/blender/compositor/nodes/COM_ColorNode.h
index d03c910bfd2..205f4d07135 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.h
+++ b/source/blender/compositor/nodes/COM_ColorNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorNode_h_
-#define _COM_ColorNode_h_
+#ifndef __COM_COLORNODE_H__
+#define __COM_COLORNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.h b/source/blender/compositor/nodes/COM_ColorRampNode.h
index c5e6b2f6154..4332d831e31 100644
--- a/source/blender/compositor/nodes/COM_ColorRampNode.h
+++ b/source/blender/compositor/nodes/COM_ColorRampNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorRampNode_h_
-#define _COM_ColorRampNode_h_
+#ifndef __COM_COLORRAMPNODE_H__
+#define __COM_COLORRAMPNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.h b/source/blender/compositor/nodes/COM_ColorSpillNode.h
index 7442d2b0261..cb2cd8a2ea3 100644
--- a/source/blender/compositor/nodes/COM_ColorSpillNode.h
+++ b/source/blender/compositor/nodes/COM_ColorSpillNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorSpillNode_h_
-#define _COM_ColorSpillNode_h_
+#ifndef __COM_COLORSPILLNODE_H__
+#define __COM_COLORSPILLNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.h b/source/blender/compositor/nodes/COM_ColorToBWNode.h
index 350ab88513d..05f937eb555 100644
--- a/source/blender/compositor/nodes/COM_ColorToBWNode.h
+++ b/source/blender/compositor/nodes/COM_ColorToBWNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorToBWNode_h_
-#define _COM_ColorToBWNode_h_
+#ifndef __COM_COLORTOBWNODE_H__
+#define __COM_COLORTOBWNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.h b/source/blender/compositor/nodes/COM_CombineColorNode.h
index d5439e0056c..030224e16f9 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.h
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.h
@@ -21,8 +21,8 @@
* Lukas Toenne
*/
-#ifndef _COM_CombineColorNode_h_
-#define _COM_CombineColorNode_h_
+#ifndef __COM_COMBINECOLORNODE_H__
+#define __COM_COMBINECOLORNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.h b/source/blender/compositor/nodes/COM_CompositorNode.h
index 4e96eb63776..a21013f2ce2 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.h
+++ b/source/blender/compositor/nodes/COM_CompositorNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CompositorNode_h_
-#define _COM_CompositorNode_h_
+#ifndef __COM_COMPOSITORNODE_H__
+#define __COM_COMPOSITORNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.h b/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
index 5bc5169b6d9..37482d66269 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ConvertAlphaNode_h_
-#define _COM_ConvertAlphaNode_h_
+#ifndef __COM_CONVERTALPHANODE_H__
+#define __COM_CONVERTALPHANODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.h b/source/blender/compositor/nodes/COM_CornerPinNode.h
index 70e48e41d6b..63428fa653b 100644
--- a/source/blender/compositor/nodes/COM_CornerPinNode.h
+++ b/source/blender/compositor/nodes/COM_CornerPinNode.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_CornerPinNode_h
-#define _COM_CornerPinNode_h
+#ifndef __COM_CORNERPINNODE_H__
+#define __COM_CORNERPINNODE_H__
#include "COM_Node.h"
@@ -38,4 +38,4 @@ public:
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
-#endif /* _COM_CornerPinNode_h */
+#endif /* __COM_CORNERPINNODE_H__ */
diff --git a/source/blender/compositor/nodes/COM_CropNode.h b/source/blender/compositor/nodes/COM_CropNode.h
index d33243b915a..a7d529c426f 100644
--- a/source/blender/compositor/nodes/COM_CropNode.h
+++ b/source/blender/compositor/nodes/COM_CropNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CropNode_h_
-#define _COM_CropNode_h_
+#ifndef __COM_CROPNODE_H__
+#define __COM_CROPNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cpp b/source/blender/compositor/nodes/COM_CryptomatteNode.cpp
new file mode 100644
index 00000000000..648ea4556ad
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2018, 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:
+ * Lukas Stockner
+ * Stefan Werner
+ */
+
+#include "COM_CryptomatteNode.h"
+#include "COM_CryptomatteOperation.h"
+#include "COM_SetAlphaOperation.h"
+#include "COM_ConvertOperation.h"
+#include "BLI_string.h"
+#include "BLI_hash_mm3.h"
+#include "BLI_assert.h"
+#include <iterator>
+
+CryptomatteNode::CryptomatteNode(bNode *editorNode) : Node(editorNode)
+{
+ /* pass */
+}
+
+/* This is taken from the Cryptomatte specification 1.0. */
+static inline float hash_to_float(uint32_t hash)
+{
+ uint32_t mantissa = hash & (( 1 << 23) - 1);
+ uint32_t exponent = (hash >> 23) & ((1 << 8) - 1);
+ exponent = max(exponent, (uint32_t) 1);
+ exponent = min(exponent, (uint32_t) 254);
+ exponent = exponent << 23;
+ uint32_t sign = (hash >> 31);
+ sign = sign << 31;
+ uint32_t float_bits = sign | exponent | mantissa;
+ float f;
+ /* Bit casting relies on equal size for both types. */
+ BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size")
+ ::memcpy(&f, &float_bits, sizeof(float));
+ return f;
+}
+
+void CryptomatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
+{
+ NodeInput *inputSocketImage = this->getInputSocket(0);
+ NodeOutput *outputSocketImage = this->getOutputSocket(0);
+ NodeOutput *outputSocketMatte = this->getOutputSocket(1);
+ NodeOutput *outputSocketPick = this->getOutputSocket(2);
+
+ bNode *node = this->getbNode();
+ NodeCryptomatte *cryptoMatteSettings = (NodeCryptomatte *)node->storage;
+
+ CryptomatteOperation *operation = new CryptomatteOperation(getNumberOfInputSockets() - 1);
+ if (cryptoMatteSettings) {
+ if (cryptoMatteSettings->matte_id) {
+ /* Split the string by commas, ignoring white space. */
+ std::string input = cryptoMatteSettings->matte_id;
+ std::istringstream ss(input);
+ while (ss.good()) {
+ std::string token;
+ getline(ss, token, ',');
+ /* Ignore empty tokens. */
+ if (token.length() > 0) {
+ size_t first = token.find_first_not_of(' ');
+ size_t last = token.find_last_not_of(' ');
+ if (first == std::string::npos || last == std::string::npos) {
+ break;
+ }
+ token = token.substr(first, (last - first + 1));
+ if (*token.begin() == '<' && *(--token.end()) == '>') {
+ operation->addObjectIndex(atof(token.substr(1, token.length() - 2).c_str()));
+ }
+ else {
+ uint32_t hash = BLI_hash_mm3((const unsigned char *)token.c_str(), token.length(), 0);
+ operation->addObjectIndex(hash_to_float(hash));
+ }
+ }
+ }
+ }
+ }
+
+ converter.addOperation(operation);
+
+ for (int i = 0; i < getNumberOfInputSockets() - 1; ++i) {
+ converter.mapInputSocket(this->getInputSocket(i + 1), operation->getInputSocket(i));
+ }
+
+ SeparateChannelOperation *separateOperation = new SeparateChannelOperation;
+ separateOperation->setChannel(3);
+ converter.addOperation(separateOperation);
+
+ SetAlphaOperation *operationAlpha = new SetAlphaOperation();
+ converter.addOperation(operationAlpha);
+
+ converter.addLink(operation->getOutputSocket(0), separateOperation->getInputSocket(0));
+ converter.addLink(separateOperation->getOutputSocket(0), operationAlpha->getInputSocket(1));
+
+ SetAlphaOperation *clearAlphaOperation = new SetAlphaOperation();
+ converter.addOperation(clearAlphaOperation);
+ converter.addInputValue(clearAlphaOperation->getInputSocket(1), 1.0f);
+
+ converter.addLink(operation->getOutputSocket(0), clearAlphaOperation->getInputSocket(0));
+
+ converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
+ converter.mapOutputSocket(outputSocketMatte, separateOperation->getOutputSocket(0));
+ converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket(0));
+ converter.mapOutputSocket(outputSocketPick, clearAlphaOperation->getOutputSocket(0));
+
+}
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.h b/source/blender/compositor/nodes/COM_CryptomatteNode.h
new file mode 100644
index 00000000000..2e1784dedb9
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018, 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:
+ * Lukas Stockner
+ */
+
+#ifndef __COM_CRYPTOMATTENODE_H__
+#define __COM_CRYPTOMATTENODE_H__
+
+#include "COM_Node.h"
+
+/**
+ * @brief CryptomatteNode
+ * @ingroup Node
+ */
+class CryptomatteNode : public Node {
+public:
+ CryptomatteNode(bNode *editorNode);
+ void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+};
+
+#endif
diff --git a/source/blender/compositor/nodes/COM_DefocusNode.h b/source/blender/compositor/nodes/COM_DefocusNode.h
index 917499ee93a..99efdd15b37 100644
--- a/source/blender/compositor/nodes/COM_DefocusNode.h
+++ b/source/blender/compositor/nodes/COM_DefocusNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DefocusNode_h_
-#define _COM_DefocusNode_h_
+#ifndef __COM_DEFOCUSNODE_H__
+#define __COM_DEFOCUSNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.h b/source/blender/compositor/nodes/COM_DespeckleNode.h
index 64d99db7ded..e8097be35dd 100644
--- a/source/blender/compositor/nodes/COM_DespeckleNode.h
+++ b/source/blender/compositor/nodes/COM_DespeckleNode.h
@@ -18,8 +18,8 @@
* Contributor: Campbell Barton
*/
-#ifndef _COM_DespeckleNode_h_
-#define _COM_DespeckleNode_h_
+#ifndef __COM_DESPECKLENODE_H__
+#define __COM_DESPECKLENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
index 98fb917e152..ea3da8d2fca 100644
--- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
+++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DifferenceMatteNode_h_
-#define _COM_DifferenceMatteNode_h_
+#ifndef __COM_DIFFERENCEMATTENODE_H__
+#define __COM_DIFFERENCEMATTENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.h b/source/blender/compositor/nodes/COM_DilateErodeNode.h
index 560087da30a..aff3ecbb4b0 100644
--- a/source/blender/compositor/nodes/COM_DilateErodeNode.h
+++ b/source/blender/compositor/nodes/COM_DilateErodeNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DilateErodeNode_h_
-#define _COM_DilateErodeNode_h_
+#ifndef __COM_DILATEERODENODE_H__
+#define __COM_DILATEERODENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DirectionalBlurNode.h b/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
index 720ac32005e..eef51e140bc 100644
--- a/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
+++ b/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DirectionalBlurNode_h_
-#define _COM_DirectionalBlurNode_h_
+#ifndef __COM_DIRECTIONALBLURNODE_H__
+#define __COM_DIRECTIONALBLURNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DisplaceNode.h b/source/blender/compositor/nodes/COM_DisplaceNode.h
index 6eb894077fc..28105fd5963 100644
--- a/source/blender/compositor/nodes/COM_DisplaceNode.h
+++ b/source/blender/compositor/nodes/COM_DisplaceNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DisplaceNode_h_
-#define _COM_DisplaceNode_h_
+#ifndef __COM_DISPLACENODE_H__
+#define __COM_DISPLACENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.h b/source/blender/compositor/nodes/COM_DistanceMatteNode.h
index e7a514b79c4..e7bd3c57dfa 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.h
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DistanceMatteNode_h_
-#define _COM_DistanceMatteNode_h_
+#ifndef __COM_DISTANCEMATTENODE_H__
+#define __COM_DISTANCEMATTENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
index 4ee58e18c9b..91a23005128 100644
--- a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
+++ b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DoubleEdgeMaskNode_h_
-#define _COM_DoubleEdgeMaskNode_h_
+#ifndef __COM_DOUBLEEDGEMASKNODE_H__
+#define __COM_DOUBLEEDGEMASKNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_EllipseMaskNode.h b/source/blender/compositor/nodes/COM_EllipseMaskNode.h
index 50c578c2d7b..e5e9861b2d9 100644
--- a/source/blender/compositor/nodes/COM_EllipseMaskNode.h
+++ b/source/blender/compositor/nodes/COM_EllipseMaskNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_EllipseMaskNode_h_
-#define _COM_EllipseMaskNode_h_
+#ifndef __COM_ELLIPSEMASKNODE_H__
+#define __COM_ELLIPSEMASKNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_FlipNode.h b/source/blender/compositor/nodes/COM_FlipNode.h
index 033f893ab76..8c9a78df85d 100644
--- a/source/blender/compositor/nodes/COM_FlipNode.h
+++ b/source/blender/compositor/nodes/COM_FlipNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_FlipNode_h_
-#define _COM_FlipNode_h_
+#ifndef __COM_FLIPNODE_H__
+#define __COM_FLIPNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_GammaNode.h b/source/blender/compositor/nodes/COM_GammaNode.h
index 3b8a530edd9..8b6434b9c6a 100644
--- a/source/blender/compositor/nodes/COM_GammaNode.h
+++ b/source/blender/compositor/nodes/COM_GammaNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GammaNode_h_
-#define _COM_GammaNode_h_
+#ifndef __COM_GAMMANODE_H__
+#define __COM_GAMMANODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_GlareNode.h b/source/blender/compositor/nodes/COM_GlareNode.h
index afc9ad3e6f3..93f92313835 100644
--- a/source/blender/compositor/nodes/COM_GlareNode.h
+++ b/source/blender/compositor/nodes/COM_GlareNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareNode_h_
-#define _COM_GlareNode_h_
+#ifndef __COM_GLARENODE_H__
+#define __COM_GLARENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
index cc425626608..f940a20e0da 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_HueSaturationValueCorrectNode_h_
-#define _COM_HueSaturationValueCorrectNode_h_
+#ifndef __COM_HUESATURATIONVALUECORRECTNODE_H__
+#define __COM_HUESATURATIONVALUECORRECTNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.h b/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
index 669cb6d2cff..f09164de34f 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_HueSaturationValueNode_h_
-#define _COM_HueSaturationValueNode_h_
+#ifndef __COM_HUESATURATIONVALUENODE_H__
+#define __COM_HUESATURATIONVALUENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.h b/source/blender/compositor/nodes/COM_IDMaskNode.h
index 120d173e5c3..8a6e55a946e 100644
--- a/source/blender/compositor/nodes/COM_IDMaskNode.h
+++ b/source/blender/compositor/nodes/COM_IDMaskNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_IDMaskNode_h_
-#define _COM_IDMaskNode_h_
+#ifndef __COM_IDMASKNODE_H__
+#define __COM_IDMASKNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_InpaintNode.h b/source/blender/compositor/nodes/COM_InpaintNode.h
index 6c167ed90ff..dcc563234be 100644
--- a/source/blender/compositor/nodes/COM_InpaintNode.h
+++ b/source/blender/compositor/nodes/COM_InpaintNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_InpaintNode_h_
-#define _COM_InpaintNode_h_
+#ifndef __COM_INPAINTNODE_H__
+#define __COM_INPAINTNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_InvertNode.h b/source/blender/compositor/nodes/COM_InvertNode.h
index a946799ce67..9ca774e7600 100644
--- a/source/blender/compositor/nodes/COM_InvertNode.h
+++ b/source/blender/compositor/nodes/COM_InvertNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_InvertNode_h_
-#define _COM_InvertNode_h_
+#ifndef __COM_INVERTNODE_H__
+#define __COM_INVERTNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.h b/source/blender/compositor/nodes/COM_LensDistortionNode.h
index 231de6a5175..ee0f9f1bc06 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.h
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_LensDistortionNode_h_
-#define _COM_LensDistortionNode_h_
+#ifndef __COM_LENSDISTORTIONNODE_H__
+#define __COM_LENSDISTORTIONNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_MapUVNode.h b/source/blender/compositor/nodes/COM_MapUVNode.h
index 286ec4205f1..245a31ce83c 100644
--- a/source/blender/compositor/nodes/COM_MapUVNode.h
+++ b/source/blender/compositor/nodes/COM_MapUVNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_MapUVNode_h_
-#define _COM_MapUVNode_h_
+#ifndef __COM_MAPUVNODE_H__
+#define __COM_MAPUVNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_MathNode.h b/source/blender/compositor/nodes/COM_MathNode.h
index 4c84dc2a331..cf92765f6da 100644
--- a/source/blender/compositor/nodes/COM_MathNode.h
+++ b/source/blender/compositor/nodes/COM_MathNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MathNode_h_
-#define _COM_MathNode_h_
+#ifndef __COM_MATHNODE_H__
+#define __COM_MATHNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_MixNode.h b/source/blender/compositor/nodes/COM_MixNode.h
index e5424c2f4e5..10954080a51 100644
--- a/source/blender/compositor/nodes/COM_MixNode.h
+++ b/source/blender/compositor/nodes/COM_MixNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MixNode_h_
-#define _COM_MixNode_h_
+#ifndef __COM_MIXNODE_H__
+#define __COM_MIXNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_MovieDistortionNode.h b/source/blender/compositor/nodes/COM_MovieDistortionNode.h
index 5ef0115bbaa..97cfaec57c8 100644
--- a/source/blender/compositor/nodes/COM_MovieDistortionNode.h
+++ b/source/blender/compositor/nodes/COM_MovieDistortionNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MovieDistortionNode_h_
-#define _COM_MovieDistortionNode_h_
+#ifndef __COM_MOVIEDISTORTIONNODE_H__
+#define __COM_MOVIEDISTORTIONNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_NormalNode.h b/source/blender/compositor/nodes/COM_NormalNode.h
index c9b37580eca..4e1dbe55360 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.h
+++ b/source/blender/compositor/nodes/COM_NormalNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_NormalNode_h_
-#define _COM_NormalNode_h_
+#ifndef __COM_NORMALNODE_H__
+#define __COM_NORMALNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_NormalizeNode.h b/source/blender/compositor/nodes/COM_NormalizeNode.h
index a0eb7c9f5a9..02f413c6ae4 100644
--- a/source/blender/compositor/nodes/COM_NormalizeNode.h
+++ b/source/blender/compositor/nodes/COM_NormalizeNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_NormalizeNode_h_
-#define _COM_NormalizeNode_h_
+#ifndef __COM_NORMALIZENODE_H__
+#define __COM_NORMALIZENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.h b/source/blender/compositor/nodes/COM_OutputFileNode.h
index b321572d638..b246dd2a541 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.h
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.h
@@ -21,8 +21,8 @@
* Lukas Tönne
*/
-#ifndef _COM_OutputFileNode_h_
-#define _COM_OutputFileNode_h_
+#ifndef __COM_OUTPUTFILENODE_H__
+#define __COM_OUTPUTFILENODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_PixelateNode.h b/source/blender/compositor/nodes/COM_PixelateNode.h
index 06ac886c843..b43c15b01da 100644
--- a/source/blender/compositor/nodes/COM_PixelateNode.h
+++ b/source/blender/compositor/nodes/COM_PixelateNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_PixelateNode_h_
-#define _COM_PixelateNode_h_
+#ifndef __COM_PIXELATENODE_H__
+#define __COM_PIXELATENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_RotateNode.h b/source/blender/compositor/nodes/COM_RotateNode.h
index e897c9a49df..e3c9710891b 100644
--- a/source/blender/compositor/nodes/COM_RotateNode.h
+++ b/source/blender/compositor/nodes/COM_RotateNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_RotateNode_h_
-#define _COM_RotateNode_h_
+#ifndef __COM_ROTATENODE_H__
+#define __COM_ROTATENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ScaleNode.h b/source/blender/compositor/nodes/COM_ScaleNode.h
index 614866d2318..b1695aab966 100644
--- a/source/blender/compositor/nodes/COM_ScaleNode.h
+++ b/source/blender/compositor/nodes/COM_ScaleNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ScaleNode_h_
-#define _COM_ScaleNode_h_
+#ifndef __COM_SCALENODE_H__
+#define __COM_SCALENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.h b/source/blender/compositor/nodes/COM_SeparateColorNode.h
index 0e47a98a1aa..a1ec23b71c7 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.h
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.h
@@ -21,8 +21,8 @@
* Lukas Toenne
*/
-#ifndef _COM_SeparateColorNode_h_
-#define _COM_SeparateColorNode_h_
+#ifndef __COM_SEPARATECOLORNODE_H__
+#define __COM_SEPARATECOLORNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.h b/source/blender/compositor/nodes/COM_SetAlphaNode.h
index efc8ccf1f27..f71d743c1d4 100644
--- a/source/blender/compositor/nodes/COM_SetAlphaNode.h
+++ b/source/blender/compositor/nodes/COM_SetAlphaNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetAlphaNode_h_
-#define _COM_SetAlphaNode_h_
+#ifndef __COM_SETALPHANODE_H__
+#define __COM_SETALPHANODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.h b/source/blender/compositor/nodes/COM_SocketProxyNode.h
index faa458492cb..ce19a9abd7d 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.h
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SocketProxyNode_h_
-#define _COM_SocketProxyNode_h_
+#ifndef __COM_SOCKETPROXYNODE_H__
+#define __COM_SOCKETPROXYNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.h b/source/blender/compositor/nodes/COM_SplitViewerNode.h
index 674067696ea..c073713f21f 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.h
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SplitViewerNode_h_
-#define _COM_SplitViewerNode_h_
+#ifndef __COM_SPLITVIEWERNODE_H__
+#define __COM_SPLITVIEWERNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.h b/source/blender/compositor/nodes/COM_Stabilize2dNode.h
index d0b5f6e96f6..2859432fac7 100644
--- a/source/blender/compositor/nodes/COM_Stabilize2dNode.h
+++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_Stabilize2dNode_h_
-#define _COM_Stabilize2dNode_h_
+#ifndef __COM_STABILIZE2DNODE_H__
+#define __COM_STABILIZE2DNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.h b/source/blender/compositor/nodes/COM_SunBeamsNode.h
index 4024eb276bc..425b97061ca 100644
--- a/source/blender/compositor/nodes/COM_SunBeamsNode.h
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_SunBeamsNode_h_
-#define _COM_SunBeamsNode_h_
+#ifndef __COM_SUNBEAMSNODE_H__
+#define __COM_SUNBEAMSNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_SwitchNode.h b/source/blender/compositor/nodes/COM_SwitchNode.h
index 37ba73528f3..5967bbd5dd0 100644
--- a/source/blender/compositor/nodes/COM_SwitchNode.h
+++ b/source/blender/compositor/nodes/COM_SwitchNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SwitchNode_h_
-#define _COM_SwitchNode_h_
+#ifndef __COM_SWITCHNODE_H__
+#define __COM_SWITCHNODE_H__
#include "COM_Node.h"
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.h b/source/blender/compositor/nodes/COM_SwitchViewNode.h
index 6ab5145bed5..f4171940880 100644
--- a/source/blender/compositor/nodes/COM_SwitchViewNode.h
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_SwitchViewNode_h_
-#define _COM_SwitchViewNode_h_
+#ifndef __COM_SWITCHVIEWNODE_H__
+#define __COM_SWITCHVIEWNODE_H__
#include "COM_Node.h"
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/nodes/COM_TimeNode.h b/source/blender/compositor/nodes/COM_TimeNode.h
index 065c55f2780..7ebc6f2cc67 100644
--- a/source/blender/compositor/nodes/COM_TimeNode.h
+++ b/source/blender/compositor/nodes/COM_TimeNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_TimeNode_h_
-#define _COM_TimeNode_h_
+#ifndef __COM_TIMENODE_H__
+#define __COM_TIMENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_TonemapNode.h b/source/blender/compositor/nodes/COM_TonemapNode.h
index e504db4c014..13e51acf3fe 100644
--- a/source/blender/compositor/nodes/COM_TonemapNode.h
+++ b/source/blender/compositor/nodes/COM_TonemapNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_TonemapNode_h_
-#define _COM_TonemapNode_h_
+#ifndef __COM_TONEMAPNODE_H__
+#define __COM_TONEMAPNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.h b/source/blender/compositor/nodes/COM_TranslateNode.h
index 484f28b1089..51d969dbb04 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.h
+++ b/source/blender/compositor/nodes/COM_TranslateNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_TranslateNode_h_
-#define _COM_TranslateNode_h_
+#ifndef __COM_TRANSLATENODE_H__
+#define __COM_TRANSLATENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ValueNode.h b/source/blender/compositor/nodes/COM_ValueNode.h
index b88c502be7f..e1b13c2d8aa 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.h
+++ b/source/blender/compositor/nodes/COM_ValueNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ValueNode_h_
-#define _COM_ValueNode_h_
+#ifndef __COM_VALUENODE_H__
+#define __COM_VALUENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_VectorBlurNode.h b/source/blender/compositor/nodes/COM_VectorBlurNode.h
index 0e7ad015cc5..5f741ff0852 100644
--- a/source/blender/compositor/nodes/COM_VectorBlurNode.h
+++ b/source/blender/compositor/nodes/COM_VectorBlurNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_VectorBlurNode_h_
-#define _COM_VectorBlurNode_h_
+#ifndef __COM_VECTORBLURNODE_H__
+#define __COM_VECTORBLURNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_VectorCurveNode.h b/source/blender/compositor/nodes/COM_VectorCurveNode.h
index 8cf76cff206..d8a2121a7c6 100644
--- a/source/blender/compositor/nodes/COM_VectorCurveNode.h
+++ b/source/blender/compositor/nodes/COM_VectorCurveNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_VectorCurveNode_h_
-#define _COM_VectorCurveNode_h_
+#ifndef __COM_VECTORCURVENODE_H__
+#define __COM_VECTORCURVENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.h b/source/blender/compositor/nodes/COM_ViewLevelsNode.h
index c56c6b0cef1..7fca060389a 100644
--- a/source/blender/compositor/nodes/COM_ViewLevelsNode.h
+++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ViewLevelsNode_h_
-#define _COM_ViewLevelsNode_h_
+#ifndef __COM_VIEWLEVELSNODE_H__
+#define __COM_VIEWLEVELSNODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.h b/source/blender/compositor/nodes/COM_ViewerNode.h
index 1f2cb02dcd6..67d6387a17c 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.h
+++ b/source/blender/compositor/nodes/COM_ViewerNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ViewerNode_h_
-#define _COM_ViewerNode_h_
+#ifndef __COM_VIEWERNODE_H__
+#define __COM_VIEWERNODE_H__
#include "COM_Node.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.h b/source/blender/compositor/nodes/COM_ZCombineNode.h
index 9a438d6dde3..8e166ddf168 100644
--- a/source/blender/compositor/nodes/COM_ZCombineNode.h
+++ b/source/blender/compositor/nodes/COM_ZCombineNode.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ZCombineNode_h_
-#define _COM_ZCombineNode_h_
+#ifndef __COM_ZCOMBINENODE_H__
+#define __COM_ZCOMBINENODE_H__
#include "COM_Node.h"
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
index 144c60f2966..569c18888d8 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_AlphaOverKeyOperation_h
-#define _COM_AlphaOverKeyOperation_h
+#ifndef __COM_ALPHAOVERKEYOPERATION_H__
+#define __COM_ALPHAOVERKEYOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
index a76bf12481d..a5174f0839a 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_AlphaOverMixedOperation_h_
-#define _COM_AlphaOverMixedOperation_h_
+#ifndef __COM_ALPHAOVERMIXEDOPERATION_H__
+#define __COM_ALPHAOVERMIXEDOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
index 8551dba7b7c..e52971222ab 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_AlphaOverPremultiplyOperation_h
-#define _COM_AlphaOverPremultiplyOperation_h
+#ifndef __COM_ALPHAOVERPREMULTIPLYOPERATION_H__
+#define __COM_ALPHAOVERPREMULTIPLYOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.h b/source/blender/compositor/operations/COM_AntiAliasOperation.h
index a6f74eb214c..34243cd34b6 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.h
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_AntiAliasOperation_h
-#define _COM_AntiAliasOperation_h
+#ifndef __COM_ANTIALIASOPERATION_H__
+#define __COM_ANTIALIASOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h
index 1a57b170c9a..8b3cfcafcef 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.h
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BlurBaseOperation_h
-#define _COM_BlurBaseOperation_h
+#ifndef __COM_BLURBASEOPERATION_H__
+#define __COM_BLURBASEOPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h
index 6f2001566ea..c6ca7054352 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.h
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BokehImageOperation_h
-#define _COM_BokehImageOperation_h
+#ifndef __COM_BOKEHIMAGEOPERATION_H__
+#define __COM_BOKEHIMAGEOPERATION_H__
#include "COM_NodeOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.h b/source/blender/compositor/operations/COM_BoxMaskOperation.h
index 292e3a9391f..399b7dd393b 100644
--- a/source/blender/compositor/operations/COM_BoxMaskOperation.h
+++ b/source/blender/compositor/operations/COM_BoxMaskOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BoxMaskOperation_h
-#define _COM_BoxMaskOperation_h
+#ifndef __COM_BOXMASKOPERATION_H__
+#define __COM_BOXMASKOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h
index 8bda13ea418..1ebccf761a7 100644
--- a/source/blender/compositor/operations/COM_BrightnessOperation.h
+++ b/source/blender/compositor/operations/COM_BrightnessOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_BrightnessOperation_h
-#define _COM_BrightnessOperation_h
+#ifndef __COM_BRIGHTNESSOPERATION_H__
+#define __COM_BRIGHTNESSOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.h b/source/blender/compositor/operations/COM_CalculateMeanOperation.h
index d7d927791b2..1872cb738b2 100644
--- a/source/blender/compositor/operations/COM_CalculateMeanOperation.h
+++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CalculateMeanOperation_h
-#define _COM_CalculateMeanOperation_h
+#ifndef __COM_CALCULATEMEANOPERATION_H__
+#define __COM_CALCULATEMEANOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
index dfeaa7297a8..7089e40b210 100644
--- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
+++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CalculateStandardDeviationOperation_h
-#define _COM_CalculateStandardDeviationOperation_h
+#ifndef __COM_CALCULATESTANDARDDEVIATIONOPERATION_H__
+#define __COM_CALCULATESTANDARDDEVIATIONOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_CalculateMeanOperation.h"
diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
index 9685a298607..16c4a0cca07 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ChangeHSVOperation_h
-#define _COM_ChangeHSVOperation_h
+#ifndef __COM_CHANGEHSVOPERATION_H__
+#define __COM_CHANGEHSVOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
index 58b467e7892..46ef7809492 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ChannelMatteOperation_h
-#define _COM_ChannelMatteOperation_h
+#ifndef __COM_CHANNELMATTEOPERATION_H__
+#define __COM_CHANNELMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
index a68790838c0..ba7f207b1c6 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ChromaMatteOperation_h
-#define _COM_ChromaMatteOperation_h
+#ifndef __COM_CHROMAMATTEOPERATION_H__
+#define __COM_CHROMAMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
index 44981a2c957..77a5dd55cd9 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorBalanceASCCDLOperation_h
-#define _COM_ColorBalanceASCCDLOperation_h
+#ifndef __COM_COLORBALANCEASCCDLOPERATION_H__
+#define __COM_COLORBALANCEASCCDLOPERATION_H__
#include "COM_NodeOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
index 97fc8b6f870..3dbe2e11058 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorBalanceLGGOperation_h
-#define _COM_ColorBalanceLGGOperation_h
+#ifndef __COM_COLORBALANCELGGOPERATION_H__
+#define __COM_COLORBALANCELGGOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
index 7c7ccf2db9b..9b691dcb050 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorCorrectionOperation_h
-#define _COM_ColorCorrectionOperation_h
+#ifndef __COM_COLORCORRECTIONOPERATION_H__
+#define __COM_COLORCORRECTIONOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.h b/source/blender/compositor/operations/COM_ColorCurveOperation.h
index 17c94feed5f..16e3455ceec 100644
--- a/source/blender/compositor/operations/COM_ColorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCurveOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorCurveOperation_h
-#define _COM_ColorCurveOperation_h
+#ifndef __COM_COLORCURVEOPERATION_H__
+#define __COM_COLORCURVEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_color_types.h"
#include "COM_CurveBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h
index 53bbe8f6466..0ceedd23efd 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ColorMatteOperation_h
-#define _COM_ColorMatteOperation_h
+#ifndef __COM_COLORMATTEOPERATION_H__
+#define __COM_COLORMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.h b/source/blender/compositor/operations/COM_ColorRampOperation.h
index 2d1919bb4b5..ff6d32fc4e6 100644
--- a/source/blender/compositor/operations/COM_ColorRampOperation.h
+++ b/source/blender/compositor/operations/COM_ColorRampOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorRampOperation_h
-#define _COM_ColorRampOperation_h
+#ifndef __COM_COLORRAMPOPERATION_H__
+#define __COM_COLORRAMPOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.h b/source/blender/compositor/operations/COM_ColorSpillOperation.h
index 5971db9fa76..519e9a22335 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.h
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ColorSpillOperation_h
-#define _COM_ColorSpillOperation_h
+#ifndef __COM_COLORSPILLOPERATION_H__
+#define __COM_COLORSPILLOPERATION_H__
#include "COM_NodeOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h
index e7f2bc7d2c6..19ed3180ace 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.h
+++ b/source/blender/compositor/operations/COM_CompositorOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CompositorOperation_h
-#define _COM_CompositorOperation_h
+#ifndef __COM_COMPOSITOROPERATION_H__
+#define __COM_COMPOSITOROPERATION_H__
#include "COM_NodeOperation.h"
#include "BLI_rect.h"
#include "BLI_string.h"
diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
index 47f9f20f393..3dc7b67df8d 100644
--- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ConvertColorProfileOperation_h
-#define _COM_ConvertColorProfileOperation_h
+#ifndef __COM_CONVERTCOLORPROFILEOPERATION_H__
+#define __COM_CONVERTCOLORPROFILEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
index 65db1cf45d9..5294d04352e 100644
--- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ConvertDepthToRadiusOperation_h
-#define _COM_ConvertDepthToRadiusOperation_h
+#ifndef __COM_CONVERTDEPTHTORADIUSOPERATION_H__
+#define __COM_CONVERTDEPTHTORADIUSOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_object_types.h"
#include "COM_FastGaussianBlurOperation.h"
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
index 9c23cc9bda7..2bbe14d6c17 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ConvertOperation_h
-#define _COM_ConvertOperation_h
+#ifndef __COM_CONVERTOPERATION_H__
+#define __COM_CONVERTOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
index 650d3ddda58..4689a5b34f1 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ConvolutionEdgeFilterOperation_h_
-#define _COM_ConvolutionEdgeFilterOperation_h_
+#ifndef __COM_CONVOLUTIONEDGEFILTEROPERATION_H__
+#define __COM_CONVOLUTIONEDGEFILTEROPERATION_H__
#include "COM_ConvolutionFilterOperation.h"
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
index 99e6fc52ddc..20b8be3278d 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ConvolutionFilterOperation_h_
-#define _COM_ConvolutionFilterOperation_h_
+#ifndef __COM_CONVOLUTIONFILTEROPERATION_H__
+#define __COM_CONVOLUTIONFILTEROPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h
index f73b4c602f6..0e0f25a2bf6 100644
--- a/source/blender/compositor/operations/COM_CropOperation.h
+++ b/source/blender/compositor/operations/COM_CropOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CropOperation_h_
-#define _COM_CropOperation_h_
+#ifndef __COM_CROPOPERATION_H__
+#define __COM_CROPOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cpp b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp
new file mode 100644
index 00000000000..9a1cbdd7a00
--- /dev/null
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018, 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: Lukas Stockner, Stefan Werner
+ */
+
+#include "COM_CryptomatteOperation.h"
+
+CryptomatteOperation::CryptomatteOperation(size_t num_inputs) : NodeOperation()
+{
+ for (size_t i = 0; i < num_inputs; i++) {
+ this->addInputSocket(COM_DT_COLOR);
+ }
+ inputs.resize(num_inputs);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->setComplex(true);
+}
+
+void CryptomatteOperation::initExecution()
+{
+ for (size_t i = 0; i < inputs.size(); i++) {
+ inputs[i] = this->getInputSocketReader(i);
+ }
+}
+
+void CryptomatteOperation::addObjectIndex(float objectIndex)
+{
+ if (objectIndex != 0.0f) {
+ m_objectIndex.push_back(objectIndex);
+ }
+}
+
+void CryptomatteOperation::executePixel(float output[4],
+ int x,
+ int y,
+ void *data)
+{
+ float input[4];
+ output[0] = output[1] = output[2] = output[3] = 0.0f;
+ for (size_t i = 0; i < inputs.size(); i++) {
+ inputs[i]->read(input, x, y, data);
+ if (i == 0) {
+ /* Write the frontmost object as false color for picking. */
+ output[0] = input[0];
+ uint32_t m3hash;
+ ::memcpy(&m3hash, &input[0], sizeof(uint32_t));
+ /* Since the red channel is likely to be out of display range,
+ * setting green and blue gives more meaningful images. */
+ output[1] = ((float) ((m3hash << 8)) / (float) UINT32_MAX);
+ output[2] = ((float) ((m3hash << 16)) / (float) UINT32_MAX);
+ }
+ for (size_t i = 0; i < m_objectIndex.size(); i++) {
+ if (m_objectIndex[i] == input[0]) {
+ output[3] += input[1];
+ }
+ if (m_objectIndex[i] == input[2]) {
+ output[3] += input[3];
+ }
+ }
+ }
+}
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.h b/source/blender/compositor/operations/COM_CryptomatteOperation.h
new file mode 100644
index 00000000000..250c5ab8a49
--- /dev/null
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018, 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: Lukas Stockner, Stefan Werner
+ */
+
+#ifndef __COM_CRYPTOMATTEOPERATION_H__
+#define __COM_CRYPTOMATTEOPERATION_H__
+#include "COM_NodeOperation.h"
+
+
+class CryptomatteOperation : public NodeOperation {
+private:
+ std::vector<float> m_objectIndex;
+public:
+ std::vector<SocketReader *> inputs;
+
+ CryptomatteOperation(size_t num_inputs = 6);
+
+ void initExecution();
+ void executePixel(float output[4], int x, int y, void *data);
+
+ void addObjectIndex(float objectIndex);
+
+};
+#endif
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.h b/source/blender/compositor/operations/COM_CurveBaseOperation.h
index 191cf7f5307..1eb943dcc51 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.h
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_CurveBaseOperation_h
-#define _COM_CurveBaseOperation_h
+#ifndef __COM_CURVEBASEOPERATION_H__
+#define __COM_CURVEBASEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_color_types.h"
diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h
index 00c5463c17a..4ae0e8525d1 100644
--- a/source/blender/compositor/operations/COM_DespeckleOperation.h
+++ b/source/blender/compositor/operations/COM_DespeckleOperation.h
@@ -18,8 +18,8 @@
* Contributor: Campbell Barton
*/
-#ifndef _COM_DespeckleOperation_h
-#define _COM_DespeckleOperation_h
+#ifndef __COM_DESPECKLEOPERATION_H__
+#define __COM_DESPECKLEOPERATION_H__
#include "COM_NodeOperation.h"
class DespeckleOperation : public NodeOperation {
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
index 3766f85444d..3ea27f85eb6 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DifferenceMatteOperation_h
-#define _COM_DifferenceMatteOperation_h
+#ifndef __COM_DIFFERENCEMATTEOPERATION_H__
+#define __COM_DIFFERENCEMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h
index 92c453d9d85..56dcbb9b4a6 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.h
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DilateErodeOperation_h
-#define _COM_DilateErodeOperation_h
+#ifndef __COM_DILATEERODEOPERATION_H__
+#define __COM_DILATEERODEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.h b/source/blender/compositor/operations/COM_DisplaceOperation.h
index 680f2606692..5a30f897203 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DisplaceOperation_h
-#define _COM_DisplaceOperation_h
+#ifndef __COM_DISPLACEOPERATION_H__
+#define __COM_DISPLACEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
index b3da61722ec..c0bd6bacdd4 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DisplaceSimpleOperation_h
-#define _COM_DisplaceSimpleOperation_h
+#ifndef __COM_DISPLACESIMPLEOPERATION_H__
+#define __COM_DISPLACESIMPLEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
index 22bc10b7bc3..0b45b0b75e9 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DistanceRGBMatteOperation_h
-#define _COM_DistanceRGBMatteOperation_h
+#ifndef __COM_DISTANCERGBMATTEOPERATION_H__
+#define __COM_DISTANCERGBMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
index 27025188d49..afff1414d7a 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_DistanceYCCMatteOperation_h
-#define _COM_DistanceYCCMatteOperation_h
+#ifndef __COM_DISTANCEYCCMATTEOPERATION_H__
+#define __COM_DISTANCEYCCMATTEOPERATION_H__
#include "COM_MixOperation.h"
#include "COM_DistanceRGBMatteOperation.h"
diff --git a/source/blender/compositor/operations/COM_DotproductOperation.h b/source/blender/compositor/operations/COM_DotproductOperation.h
index 0fbefd716eb..43e38ee7c78 100644
--- a/source/blender/compositor/operations/COM_DotproductOperation.h
+++ b/source/blender/compositor/operations/COM_DotproductOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DotproductOperation_h_
-#define _COM_DotproductOperation_h_
+#ifndef __COM_DOTPRODUCTOPERATION_H__
+#define __COM_DOTPRODUCTOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
index 4574454dd02..1e5a3bb52a5 100644
--- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
+++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_DoubleEdgeMaskOperation_h
-#define _COM_DoubleEdgeMaskOperation_h
+#ifndef __COM_DOUBLEEDGEMASKOPERATION_H__
+#define __COM_DOUBLEEDGEMASKOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.h b/source/blender/compositor/operations/COM_EllipseMaskOperation.h
index 9de9fb3e11c..59451d2046a 100644
--- a/source/blender/compositor/operations/COM_EllipseMaskOperation.h
+++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_EllipseMaskOperation_h
-#define _COM_EllipseMaskOperation_h
+#ifndef __COM_ELLIPSEMASKOPERATION_H__
+#define __COM_ELLIPSEMASKOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
index ae92b1ee095..840849d6126 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_FastGaussianBlurOperation_h
-#define _COM_FastGaussianBlurOperation_h
+#ifndef __COM_FASTGAUSSIANBLUROPERATION_H__
+#define __COM_FASTGAUSSIANBLUROPERATION_H__
#include "COM_BlurBaseOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_FlipOperation.h b/source/blender/compositor/operations/COM_FlipOperation.h
index e577259fea4..039f3af5064 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.h
+++ b/source/blender/compositor/operations/COM_FlipOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_FlipOperation_h_
-#define _COM_FlipOperation_h_
+#ifndef __COM_FLIPOPERATION_H__
+#define __COM_FLIPOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.h b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
index aabfe09fbf2..e9b6691349b 100644
--- a/source/blender/compositor/operations/COM_GammaCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GammaCorrectOperation_h
-#define _COM_GammaCorrectOperation_h
+#ifndef __COM_GAMMACORRECTOPERATION_H__
+#define __COM_GAMMACORRECTOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_GammaOperation.h b/source/blender/compositor/operations/COM_GammaOperation.h
index ce221965eb5..b51c86f7fd3 100644
--- a/source/blender/compositor/operations/COM_GammaOperation.h
+++ b/source/blender/compositor/operations/COM_GammaOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GammaOperation_h
-#define _COM_GammaOperation_h
+#ifndef __COM_GAMMAOPERATION_H__
+#define __COM_GAMMAOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
index 651e8d9e658..985f56e3ef6 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
@@ -21,8 +21,8 @@
* Campbell Barton
*/
-#ifndef _COM_GaussianAlphaXBlurOperation_h
-#define _COM_GaussianAlphaXBlurOperation_h
+#ifndef __COM_GAUSSIANALPHAXBLUROPERATION_H__
+#define __COM_GAUSSIANALPHAXBLUROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_BlurBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
index dc9e5607ae6..3935dcd6568 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
@@ -21,8 +21,8 @@
* Campbell Barton
*/
-#ifndef _COM_GaussianAlphaYBlurOperation_h
-#define _COM_GaussianAlphaYBlurOperation_h
+#ifndef __COM_GAUSSIANALPHAYBLUROPERATION_H__
+#define __COM_GAUSSIANALPHAYBLUROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_BlurBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
index 4ad57bda742..88d8ed44de6 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GaussianXBlurOperation_h
-#define _COM_GaussianXBlurOperation_h
+#ifndef __COM_GAUSSIANXBLUROPERATION_H__
+#define __COM_GAUSSIANXBLUROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_BlurBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
index da1adbd0ea7..5df77eb28ce 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GaussianYBlurOperation_h
-#define _COM_GaussianYBlurOperation_h
+#ifndef __COM_GAUSSIANYBLUROPERATION_H__
+#define __COM_GAUSSIANYBLUROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_BlurBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h
index 3f0893d895f..3fa676f4d31 100644
--- a/source/blender/compositor/operations/COM_GlareBaseOperation.h
+++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareBaseOperation_h
-#define _COM_GlareBaseOperation_h
+#ifndef __COM_GLAREBASEOPERATION_H__
+#define __COM_GLAREBASEOPERATION_H__
#include "COM_SingleThreadedOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
index 1231185a21a..5bfe40d3a23 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareFogGlowOperation_h
-#define _COM_GlareFogGlowOperation_h
+#ifndef __COM_GLAREFOGGLOWOPERATION_H__
+#define __COM_GLAREFOGGLOWOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_GlareBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.h b/source/blender/compositor/operations/COM_GlareGhostOperation.h
index 7ce1048efe9..bff13d1bcce 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.h
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareGhostOperation_h
-#define _COM_GlareGhostOperation_h
+#ifndef __COM_GLAREGHOSTOPERATION_H__
+#define __COM_GLAREGHOSTOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_GlareBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
index 440f3ba147a..7f0cf7be46a 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareSimpleStarOperation_h
-#define _COM_GlareSimpleStarOperation_h
+#ifndef __COM_GLARESIMPLESTAROPERATION_H__
+#define __COM_GLARESIMPLESTAROPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_GlareBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.h b/source/blender/compositor/operations/COM_GlareStreaksOperation.h
index e629ac11623..0671c0b2557 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.h
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareStreaksOperation_h
-#define _COM_GlareStreaksOperation_h
+#ifndef __COM_GLARESTREAKSOPERATION_H__
+#define __COM_GLARESTREAKSOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_GlareBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.h b/source/blender/compositor/operations/COM_GlareThresholdOperation.h
index 647cf74cdcf..9a922a5889c 100644
--- a/source/blender/compositor/operations/COM_GlareThresholdOperation.h
+++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_GlareScaleOperation_h
-#define _COM_GlareScaleOperation_h
+#ifndef __COM_GLARETHRESHOLDOPERATION_H__
+#define __COM_GLARETHRESHOLDOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_lamp_types.h"
diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
index 97bfc836ae2..2a749fef1f8 100644
--- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_HueSaturationValueCorrectOperation_h
-#define _COM_HueSaturationValueCorrectOperation_h
+#ifndef __COM_HUESATURATIONVALUECORRECTOPERATION_H__
+#define __COM_HUESATURATIONVALUECORRECTOPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_CurveBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.h b/source/blender/compositor/operations/COM_IDMaskOperation.h
index 89f9855303c..53c2fd154a0 100644
--- a/source/blender/compositor/operations/COM_IDMaskOperation.h
+++ b/source/blender/compositor/operations/COM_IDMaskOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_IDMaskOperation_h
-#define _COM_IDMaskOperation_h
+#ifndef __COM_IDMASKOPERATION_H__
+#define __COM_IDMASKOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h
index 8ab93c2ba64..60172eb6413 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.h
+++ b/source/blender/compositor/operations/COM_ImageOperation.h
@@ -21,8 +21,8 @@
*/
-#ifndef _COM_ImageOperation_h
-#define _COM_ImageOperation_h
+#ifndef __COM_IMAGEOPERATION_H__
+#define __COM_IMAGEOPERATION_H__
#include "COM_NodeOperation.h"
#include "BLI_listbase.h"
diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h
index fe8e2dd2a19..bd430a3690c 100644
--- a/source/blender/compositor/operations/COM_InpaintOperation.h
+++ b/source/blender/compositor/operations/COM_InpaintOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_InpaintOperation_h
-#define _COM_InpaintOperation_h
+#ifndef __COM_INPAINTOPERATION_H__
+#define __COM_INPAINTOPERATION_H__
#include "COM_NodeOperation.h"
class InpaintSimpleOperation : public NodeOperation {
diff --git a/source/blender/compositor/operations/COM_InvertOperation.h b/source/blender/compositor/operations/COM_InvertOperation.h
index 4528895c282..2aeb33a76f5 100644
--- a/source/blender/compositor/operations/COM_InvertOperation.h
+++ b/source/blender/compositor/operations/COM_InvertOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_InvertOperation_h
-#define _COM_InvertOperation_h
+#ifndef __COM_INVERTOPERATION_H__
+#define __COM_INVERTOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.h b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
index a1c56cc9c07..2bea3ca8616 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
@@ -21,8 +21,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_KeyingBlurOperation_h
-#define _COM_KeyingBlurOperation_h
+#ifndef __COM_KEYINGBLUROPERATION_H__
+#define __COM_KEYINGBLUROPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h
index d79bd14b900..e0571bf15cd 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h
@@ -21,8 +21,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_KeyingClipOperation_h
-#define _COM_KeyingClipOperation_h
+#ifndef __COM_KEYINGCLIPOPERATION_H__
+#define __COM_KEYINGCLIPOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.h b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
index da9924d5b4b..6b7fc82367b 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
@@ -21,8 +21,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_KeyingDespillOperation_h
-#define _COM_KeyingDespillOperation_h
+#ifndef __COM_KEYINGDESPILLOPERATION_H__
+#define __COM_KEYINGDESPILLOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h
index e4542e2c6dd..a9f3034f6d1 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingOperation.h
@@ -22,8 +22,8 @@
*/
-#ifndef _COM_KeyingOperation_h
-#define _COM_KeyingOperation_h
+#ifndef __COM_KEYINGOPERATION_H__
+#define __COM_KEYINGOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
index 45195b1e98d..25a3dcb6897 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
@@ -22,8 +22,8 @@
*/
-#ifndef _COM_KeyingScreenOperation_h
-#define _COM_KeyingScreenOperation_h
+#ifndef __COM_KEYINGSCREENOPERATION_H__
+#define __COM_KEYINGSCREENOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
index 951c054d241..64d4638c5cd 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_LuminanceMatteOperation_h
-#define _COM_LuminanceMatteOperation_h
+#ifndef __COM_LUMINANCEMATTEOPERATION_H__
+#define __COM_LUMINANCEMATTEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h
index 405faf3fb2c..6598c89a09c 100644
--- a/source/blender/compositor/operations/COM_MapRangeOperation.h
+++ b/source/blender/compositor/operations/COM_MapRangeOperation.h
@@ -20,8 +20,8 @@
* Daniel Salazar
*/
-#ifndef _COM_MapRangeOperation_h
-#define _COM_MapRangeOperation_h
+#ifndef __COM_MAPRANGEOPERATION_H__
+#define __COM_MAPRANGEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.h b/source/blender/compositor/operations/COM_MapUVOperation.h
index 1bb26bf14f0..599a07e1afa 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.h
+++ b/source/blender/compositor/operations/COM_MapUVOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_MapUVOperation_h
-#define _COM_MapUVOperation_h
+#ifndef __COM_MAPUVOPERATION_H__
+#define __COM_MAPUVOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_MapValueOperation.h b/source/blender/compositor/operations/COM_MapValueOperation.h
index 97528efca19..33513c6f39c 100644
--- a/source/blender/compositor/operations/COM_MapValueOperation.h
+++ b/source/blender/compositor/operations/COM_MapValueOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MapValueOperation_h
-#define _COM_MapValueOperation_h
+#ifndef __COM_MAPVALUEOPERATION_H__
+#define __COM_MAPVALUEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h
index 522b873e167..a586a91682e 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.h
+++ b/source/blender/compositor/operations/COM_MaskOperation.h
@@ -21,8 +21,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_MaskOperation_h
-#define _COM_MaskOperation_h
+#ifndef __COM_MASKOPERATION_H__
+#define __COM_MASKOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h
index 5435cc82ba7..54fd3c5d2b9 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MathBaseOperation_h
-#define _COM_MathBaseOperation_h
+#ifndef __COM_MATHBASEOPERATION_H__
+#define __COM_MATHBASEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
index fa13a486657..9063635fda0 100644
--- a/source/blender/compositor/operations/COM_MixOperation.h
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MixBaseOperation_h
-#define _COM_MixBaseOperation_h
+#ifndef __COM_MIXOPERATION_H__
+#define __COM_MIXOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
index 436b89a0dfb..9ac38da55d3 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_MovieClipAttributeOperation_h
-#define _COM_MovieClipAttributeOperation_h
+#ifndef __COM_MOVIECLIPATTRIBUTEOPERATION_H__
+#define __COM_MOVIECLIPATTRIBUTEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_movieclip_types.h"
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.h b/source/blender/compositor/operations/COM_MovieClipOperation.h
index 28e6c0d0c3a..2b696cd5df6 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.h
@@ -21,8 +21,8 @@
*/
-#ifndef _COM_ImageOperation_h
-#define _COM_ImageOperation_h
+#ifndef __COM_MOVIECLIPOPERATION_H__
+#define __COM_MOVIECLIPOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_movieclip_types.h"
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index 689fcfe11ad..f09e9c29d01 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -21,8 +21,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_MovieDistortionOperation_h_
-#define _COM_MovieDistortionOperation_h_
+#ifndef __COM_MOVIEDISTORTIONOPERATION_H__
+#define __COM_MOVIEDISTORTIONOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_movieclip_types.h"
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index 2e68f922dd9..4074b80374f 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -22,8 +22,8 @@
*/
-#ifndef _COM_MultilayerImageOperation_h
-#define _COM_MultilayerImageOperation_h
+#ifndef __COM_MULTILAYERIMAGEOPERATION_H__
+#define __COM_MULTILAYERIMAGEOPERATION_H__
#include "COM_ImageOperation.h"
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.h b/source/blender/compositor/operations/COM_NormalizeOperation.h
index 32f39a4d9ca..de1a23926f4 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.h
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_NormalizeOperation_h
-#define _COM_NormalizeOperation_h
+#ifndef __COM_NORMALIZEOPERATION_H__
+#define __COM_NORMALIZEOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
index 25ed8816399..74ba8ff2226 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -22,8 +22,8 @@
* Dalai Felinto
*/
-#ifndef _COM_OutputFileMultiViewOperation_h
-#define _COM_OutputFileMultiViewOperation_h
+#ifndef __COM_OUTPUTFILEMULTIVIEWOPERATION_H__
+#define __COM_OUTPUTFILEMULTIVIEWOPERATION_H__
#include "COM_NodeOperation.h"
#include "BLI_rect.h"
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index 32c9b5ab5b8..cc800ca222a 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -21,8 +21,8 @@
* Lukas Tönne
*/
-#ifndef _COM_OutputFileOperation_h
-#define _COM_OutputFileOperation_h
+#ifndef __COM_OUTPUTFILEOPERATION_H__
+#define __COM_OUTPUTFILEOPERATION_H__
#include "COM_NodeOperation.h"
#include "BLI_rect.h"
diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h
index 8e60baf7f05..5b08cb429f4 100644
--- a/source/blender/compositor/operations/COM_PixelateOperation.h
+++ b/source/blender/compositor/operations/COM_PixelateOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_PixelateOperation_h_
-#define _COM_PixelateOperation_h_
+#ifndef __COM_PIXELATEOPERATION_H__
+#define __COM_PIXELATEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
index a9bd18299eb..980f57c4cea 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
@@ -20,8 +20,8 @@
* Lukas Toenne
*/
-#ifndef _COM_CornerPinWarpImageOperation_h
-#define _COM_CornerPinWarpImageOperation_h
+#ifndef __COM_PLANECORNERPINOPERATION_H__
+#define __COM_PLANECORNERPINOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
index fc5dd1ff7d8..adf13685b4a 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
@@ -20,8 +20,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_PlaneTrackCommonOperation_h
-#define _COM_PlaneTrackCommonOperation_h
+#ifndef __COM_PLANEDISTORTCOMMONOPERATION_H__
+#define __COM_PLANEDISTORTCOMMONOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
index 41761493e12..493d9cb3be1 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
@@ -20,8 +20,8 @@
* Sergey Sharybin
*/
-#ifndef _COM_PlaneTrackWarpImageOperation_h
-#define _COM_PlaneTrackWarpImageOperation_h
+#ifndef __COM_PLANETRACKOPERATION_H__
+#define __COM_PLANETRACKOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index 907a6c8997f..75317748897 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_PreviewOperation_h
-#define _COM_PreviewOperation_h
+#ifndef __COM_PREVIEWOPERATION_H__
+#define __COM_PREVIEWOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_image_types.h"
#include "DNA_color_types.h"
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
index 12efff14839..79bd5586d8f 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ProjectorLensDistortionOperation_h
-#define _COM_ProjectorLensDistortionOperation_h
+#ifndef __COM_PROJECTORLENSDISTORTIONOPERATION_H__
+#define __COM_PROJECTORLENSDISTORTIONOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.h b/source/blender/compositor/operations/COM_QualityStepHelper.h
index 9076e5a0776..67419cfbc87 100644
--- a/source/blender/compositor/operations/COM_QualityStepHelper.h
+++ b/source/blender/compositor/operations/COM_QualityStepHelper.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_QualityStepHelper_h
-#define _COM_QualityStepHelper_h
+#ifndef __COM_QUALITYSTEPHELPER_H__
+#define __COM_QUALITYSTEPHELPER_H__
#include "COM_defines.h"
typedef enum QualityHelper {
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index c42de32b9e9..c73acbaf300 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ReadBufferOperation_h
-#define _COM_ReadBufferOperation_h
+#ifndef __COM_READBUFFEROPERATION_H__
+#define __COM_READBUFFEROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_MemoryProxy.h"
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 90d57d422e3..2a0f7efc9f8 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -21,8 +21,8 @@
*/
-#ifndef _COM_RenderLayersBaseProg_h
-#define _COM_RenderLayersBaseProg_h
+#ifndef __COM_RENDERLAYERSPROG_H__
+#define __COM_RENDERLAYERSPROG_H__
#include "COM_NodeOperation.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/compositor/operations/COM_RotateOperation.h b/source/blender/compositor/operations/COM_RotateOperation.h
index d332f7208b5..59fb92054e1 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.h
+++ b/source/blender/compositor/operations/COM_RotateOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_RotateOperation_h_
-#define _COM_RotateOperation_h_
+#ifndef __COM_ROTATEOPERATION_H__
+#define __COM_ROTATEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h
index 93f9827aabf..b4aecb1515d 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.h
+++ b/source/blender/compositor/operations/COM_ScaleOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ScaleOperation_h_
-#define _COM_ScaleOperation_h_
+#ifndef __COM_SCALEOPERATION_H__
+#define __COM_SCALEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
index e1e276d0dc4..c9ecfa9fb7b 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ScreenLensDistortionOperation_h
-#define _COM_ScreenLensDistortionOperation_h
+#ifndef __COM_SCREENLENSDISTORTIONOPERATION_H__
+#define __COM_SCREENLENSDISTORTIONOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_SetAlphaOperation.h b/source/blender/compositor/operations/COM_SetAlphaOperation.h
index c4e12a367a5..90deb69a67d 100644
--- a/source/blender/compositor/operations/COM_SetAlphaOperation.h
+++ b/source/blender/compositor/operations/COM_SetAlphaOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetAlphaOperation_h
-#define _COM_SetAlphaOperation_h
+#ifndef __COM_SETALPHAOPERATION_H__
+#define __COM_SETALPHAOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h
index f9fa06f5132..9a509f6fb0c 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.h
+++ b/source/blender/compositor/operations/COM_SetColorOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetColorOperation_h
-#define _COM_SetColorOperation_h
+#ifndef __COM_SETCOLOROPERATION_H__
+#define __COM_SETCOLOROPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.h b/source/blender/compositor/operations/COM_SetSamplerOperation.h
index 6d97b20769d..24b14a3ce48 100644
--- a/source/blender/compositor/operations/COM_SetSamplerOperation.h
+++ b/source/blender/compositor/operations/COM_SetSamplerOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetSamplerOperation_h
-#define _COM_SetSamplerOperation_h
+#ifndef __COM_SETSAMPLEROPERATION_H__
+#define __COM_SETSAMPLEROPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h
index a0867a3bc9c..4e274816f27 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.h
+++ b/source/blender/compositor/operations/COM_SetValueOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetValueOperation_h
-#define _COM_SetValueOperation_h
+#ifndef __COM_SETVALUEOPERATION_H__
+#define __COM_SETVALUEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h
index 79b55bb7d91..ca35784ff9a 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.h
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SetVectorOperation_h
-#define _COM_SetVectorOperation_h
+#ifndef __COM_SETVECTOROPERATION_H__
+#define __COM_SETVECTOROPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h
index 55cf6d376b7..61575ac6b2c 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.h
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SocketProxyOperation_h_
-#define _COM_SocketProxyOperation_h_
+#ifndef __COM_SOCKETPROXYOPERATION_H__
+#define __COM_SOCKETPROXYOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_SplitOperation.h b/source/blender/compositor/operations/COM_SplitOperation.h
index 4375c760963..a7c7146ddea 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.h
+++ b/source/blender/compositor/operations/COM_SplitOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_SplitOperation_h
-#define _COM_SplitOperation_h
+#ifndef __COM_SPLITOPERATION_H__
+#define __COM_SPLITOPERATION_H__
#include "COM_NodeOperation.h"
class SplitOperation : public NodeOperation {
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h
index ef80a31fe40..43846ab24d1 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.h
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h
@@ -19,8 +19,8 @@
* Lukas Toenne
*/
-#ifndef _COM_SunBeamsOperation_h
-#define _COM_SunBeamsOperation_h
+#ifndef __COM_SUNBEAMSOPERATION_H__
+#define __COM_SUNBEAMSOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h
index 26d50ca1753..9f0f539800d 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.h
+++ b/source/blender/compositor/operations/COM_TextureOperation.h
@@ -21,8 +21,8 @@
*/
-#ifndef _COM_TextureOperation_h
-#define _COM_TextureOperation_h
+#ifndef __COM_TEXTUREOPERATION_H__
+#define __COM_TEXTUREOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.h b/source/blender/compositor/operations/COM_TonemapOperation.h
index 6fcf72c9d14..2b07ded7305 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.h
+++ b/source/blender/compositor/operations/COM_TonemapOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_TonemapOperation_h
-#define _COM_TonemapOperation_h
+#ifndef __COM_TONEMAPOPERATION_H__
+#define __COM_TONEMAPOPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h
index 87bb0623ad5..add6ccd3459 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.h
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h
@@ -22,8 +22,8 @@
*/
-#ifndef _COM_TrackPositionOperation_h
-#define _COM_TrackPositionOperation_h
+#ifndef __COM_TRACKPOSITIONOPERATION_H__
+#define __COM_TRACKPOSITIONOPERATION_H__
#include <string.h>
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h
index f3708ef3c7c..1c54ec62284 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.h
+++ b/source/blender/compositor/operations/COM_TranslateOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_TranslateOperation_h_
-#define _COM_TranslateOperation_h_
+#ifndef __COM_TRANSLATEOPERATION_H__
+#define __COM_TRANSLATEOPERATION_H__
#include "COM_NodeOperation.h"
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.h b/source/blender/compositor/operations/COM_VectorBlurOperation.h
index 30ca2f644bb..a33761166c6 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.h
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_VectorBlurOperation_h
-#define _COM_VectorBlurOperation_h
+#ifndef __COM_VECTORBLUROPERATION_H__
+#define __COM_VECTORBLUROPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
#include "COM_QualityStepHelper.h"
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.h b/source/blender/compositor/operations/COM_VectorCurveOperation.h
index 518e4713c99..a5c1cb6d446 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_VectorCurveOperation_h
-#define _COM_VectorCurveOperation_h
+#ifndef __COM_VECTORCURVEOPERATION_H__
+#define __COM_VECTORCURVEOPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_CurveBaseOperation.h"
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h
index 0e4bff2c4e8..43e305fb291 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.h
+++ b/source/blender/compositor/operations/COM_ViewerOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ViewerOperation_h
-#define _COM_ViewerOperation_h
+#ifndef __COM_VIEWEROPERATION_H__
+#define __COM_VIEWEROPERATION_H__
#include "COM_NodeOperation.h"
#include "DNA_image_types.h"
#include "BLI_rect.h"
diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h
index 4a17b29ede8..4b8d1d8846b 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.h
+++ b/source/blender/compositor/operations/COM_WrapOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_WrapOperation_h_
-#define _COM_WrapOperation_h_
+#ifndef __COM_WRAPOPERATION_H__
+#define __COM_WRAPOPERATION_H__
#include "COM_ReadBufferOperation.h"
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h
index 73314c947f5..583d58e7b99 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.h
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_WriteBufferOperation_h_
-#define _COM_WriteBufferOperation_h_
+#ifndef __COM_WRITEBUFFEROPERATION_H__
+#define __COM_WRITEBUFFEROPERATION_H__
#include "COM_NodeOperation.h"
#include "COM_MemoryProxy.h"
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h
index c9d26adfc46..be6fb0fe576 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.h
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_ZCombineOperation_h
-#define _COM_ZCombineOperation_h
+#ifndef __COM_ZCOMBINEOPERATION_H__
+#define __COM_ZCOMBINEOPERATION_H__
#include "COM_MixOperation.h"
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 185a98f2a2b..c9cdea34401 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -106,28 +106,6 @@ set(SRC
util/deg_util_function.h
)
-if(WITH_CXX11)
- add_definitions(-DDEG_STD_UNORDERED_MAP)
-elseif(HAVE_STD_UNORDERED_MAP_HEADER)
- if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
- add_definitions(-DDEG_STD_UNORDERED_MAP)
- else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- add_definitions(-DDEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
- else()
- add_definitions(-DDEG_NO_UNORDERED_MAP)
- message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
- endif()
-else()
- if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
- add_definitions(-DDEG_TR1_UNORDERED_MAP)
- else()
- add_definitions(-DDEG_NO_UNORDERED_MAP)
- message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
- endif()
-endif()
-
if(WITH_BOOST)
list(APPEND INC_SYS
${BOOST_INCLUDE_DIR}
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 71376d94ca8..7d827f48f9c 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -239,9 +239,9 @@ void DEG_make_inactive(struct Depsgraph *depsgraph);
void DEG_debug_print_begin(struct Depsgraph *depsgraph);
void DEG_debug_print_eval(struct Depsgraph *depsgraph,
- const char* function_name,
- const char* object_name,
- const void* object_address);
+ const char *function_name,
+ const char *object_name,
+ const void *object_address);
void DEG_debug_print_eval_subdata(struct Depsgraph *depsgraph,
const char *function_name,
@@ -269,9 +269,9 @@ void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph,
const void *parent_address);
void DEG_debug_print_eval_time(struct Depsgraph *depsgraph,
- const char* function_name,
- const char* object_name,
- const void* object_address,
+ const char *function_name,
+ const char *object_name,
+ const void *object_address,
float time);
#ifdef __cplusplus
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index 4cbc7700947..8f5925a5ce3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -67,6 +67,12 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
}
if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
flag |= DEG_TAG_COPY_ON_WRITE;
+ /* This means ID is being added to the dependency graph first
+ * time, which is similar to "ob-visible-change"
+ */
+ if (GS(id->name) == ID_OB) {
+ flag |= OB_RECALC_OB | OB_RECALC_DATA;
+ }
}
if (flag != 0) {
DEG_graph_id_tag_update(bmain,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
index 218483d1dc5..cde7b9721b7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
@@ -37,24 +37,29 @@
namespace DEG {
-BuilderMap::BuilderMap() {
+BuilderMap::BuilderMap()
+{
set = BLI_gset_ptr_new("deg builder gset");
}
-BuilderMap::~BuilderMap() {
+BuilderMap::~BuilderMap()
+{
BLI_gset_free(set, NULL);
}
-bool BuilderMap::checkIsBuilt(ID *id) {
+bool BuilderMap::checkIsBuilt(ID *id)
+{
return BLI_gset_haskey(set, id);
}
-void BuilderMap::tagBuild(ID *id) {
+void BuilderMap::tagBuild(ID *id)
+{
BLI_gset_insert(set, id);
}
-bool BuilderMap::checkIsBuiltAndTag(ID *id) {
+bool BuilderMap::checkIsBuiltAndTag(ID *id)
+{
void **key_p;
if (!BLI_gset_ensure_p_ex(set, id, &key_p)) {
*key_p = id;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index ab7ddb507a0..efd57734b48 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -77,6 +77,8 @@ extern "C" {
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_idcode.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
@@ -93,6 +95,7 @@ extern "C" {
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
+#include "BKE_shader_fx.h"
#include "BKE_sound.h"
#include "BKE_tracking.h"
#include "BKE_world.h"
@@ -514,6 +517,18 @@ void DepsgraphNodeBuilder::build_object(int base_index,
data.builder = this;
modifiers_foreachIDLink(object, modifier_walk, &data);
}
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Shadr FX. */
+ if (object->shader_fx.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
+ }
/* Constraints. */
if (object->constraints.first != NULL) {
BuilderWalkUserData data;
@@ -538,10 +553,6 @@ void DepsgraphNodeBuilder::build_object(int base_index,
if (object->particlesystem.first != NULL) {
build_particles(object);
}
- /* Grease pencil. */
- if (object->gpd != NULL) {
- build_gpencil(object->gpd);
- }
/* Proxy object to copy from. */
if (object->proxy_from != NULL) {
build_object(-1, object->proxy_from, DEG_ID_LINKED_INDIRECTLY);
@@ -592,6 +603,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
case OB_SURF:
case OB_MBALL:
case OB_LATTICE:
+ case OB_GPENCIL:
build_object_data_geometry(object);
/* TODO(sergey): Only for until we support granular
* update of curves.
@@ -829,8 +841,19 @@ void DepsgraphNodeBuilder::build_driver_variables(ID * id, FCurve *fcurve)
LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
DRIVER_TARGETS_USED_LOOPER(dvar)
{
+ if (dtar->id == NULL) {
+ continue;
+ }
build_id(dtar->id);
build_driver_id_property(dtar->id, dtar->rna_path);
+ /* Corresponds to dtar_id_ensure_proxy_from(). */
+ if ((GS(dtar->id->name) == ID_OB) &&
+ (((Object *)dtar->id)->proxy_from != NULL))
+ {
+ Object *proxy_from = ((Object *)dtar->id)->proxy_from;
+ build_id(&proxy_from->id);
+ build_driver_id_property(&proxy_from->id, dtar->rna_path);
+ }
}
DRIVER_TARGETS_LOOPER_END
}
@@ -1202,6 +1225,20 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata)
op_node->set_as_entry();
break;
}
+
+ case ID_GD:
+ {
+ /* GPencil evaluation operations. */
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_gpencil_eval_geometry,
+ _1,
+ (bGPdata *)obdata_cow),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
+ break;
+ }
default:
BLI_assert(!"Should not happen");
break;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 6899a86b3e9..66293a91e85 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -158,7 +158,7 @@ struct DepsgraphNodeBuilder {
const char *name = "",
int name_tag = -1);
- void build_id(ID* id);
+ void build_id(ID *id);
void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene,
ViewLayer *view_layer,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index 00d7a5da455..b1486e82af5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -161,7 +161,8 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
build_armature(armature);
/* Rebuild pose if not up to date. */
if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild(object, armature);
+ /* By definition, no need to tag depsgraph as dirty from here, so we can pass NULL bmain. */
+ BKE_pose_rebuild(NULL, object, armature, true);
/* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
@@ -313,12 +314,13 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
}
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_proxy_copy,
+ function_bind(BKE_pose_eval_proxy_pose_init,
_1,
object_cow),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
+ int pchan_index = 0;
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_BONE,
@@ -333,10 +335,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
NULL,
DEG_OPCODE_BONE_READY);
/* Bone is fully evaluated. */
- op_node = add_operation_node(&object->id,
+ op_node = add_operation_node(
+ &object->id,
DEG_NODE_TYPE_BONE,
pchan->name,
- NULL,
+ function_bind(BKE_pose_eval_proxy_copy_bone,
+ _1,
+ object_cow,
+ pchan_index),
DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
@@ -348,10 +354,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
DEG_OPCODE_PARAMETERS_EVAL,
pchan->name);
}
+
+ pchan_index++;
}
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- NULL,
+ function_bind(BKE_pose_eval_proxy_pose_done,
+ _1,
+ object_cow),
DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index f1db05b7220..3d7b2d6d232 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -134,10 +134,6 @@ void DepsgraphNodeBuilder::build_view_layer(
if (scene->nodetree != NULL) {
build_compositor(scene);
}
- /* Grease pencil. */
- if (scene->gpd != NULL) {
- build_gpencil(scene->gpd);
- }
/* Cache file. */
LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
build_cachefile(cachefile);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index bba1ba67962..4f94066f3bb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -85,10 +85,12 @@ extern "C" {
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_rigidbody.h"
+#include "BKE_shader_fx.h"
#include "BKE_sound.h"
#include "BKE_tracking.h"
#include "BKE_world.h"
@@ -525,6 +527,18 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
data.builder = this;
modifiers_foreachIDLink(object, modifier_walk, &data);
}
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
+ }
/* Constraints. */
if (object->constraints.first != NULL) {
BuilderWalkUserData data;
@@ -570,17 +584,9 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
if (object->particlesystem.first != NULL) {
build_particles(object);
}
- /* Grease pencil. */
- if (object->gpd != NULL) {
- build_gpencil(object->gpd);
- }
/* Proxy object to copy from. */
if (object->proxy_from != NULL) {
build_object(NULL, object->proxy_from);
- ComponentKey ob_pose_key(&object->proxy_from->id, DEG_NODE_TYPE_EVAL_POSE);
- ComponentKey proxy_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
- add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose");
-
ComponentKey ob_transform_key(&object->proxy_from->id, DEG_NODE_TYPE_TRANSFORM);
ComponentKey proxy_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
@@ -630,6 +636,7 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
case OB_SURF:
case OB_MBALL:
case OB_LATTICE:
+ case OB_GPENCIL:
{
build_object_data_geometry(object);
break;
@@ -1351,6 +1358,14 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
continue;
}
build_id(dtar->id);
+ /* Initialize relations coming to proxy_from. */
+ Object *proxy_from = NULL;
+ if ((GS(dtar->id->name) == ID_OB) &&
+ (((Object *)dtar->id)->proxy_from != NULL))
+ {
+ proxy_from = ((Object *)dtar->id)->proxy_from;
+ build_id(&proxy_from->id);
+ }
/* Special handling for directly-named bones. */
if ((dtar->flag & DTAR_FLAG_STRUCT_REF) &&
(((Object *)dtar->id)->type == OB_ARMATURE) &&
@@ -1398,6 +1413,13 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
continue;
}
add_relation(variable_key, driver_key, "RNA Target -> Driver");
+ if (proxy_from != NULL) {
+ RNAPathKey proxy_from_variable_key(&proxy_from->id,
+ dtar->rna_path);
+ add_relation(proxy_from_variable_key,
+ variable_key,
+ "Proxy From -> Variable");
+ }
}
else {
if (dtar->id == id) {
@@ -1783,6 +1805,42 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
}
}
}
+ /* Grease Pencil Modifiers */
+ if (object->greasepencil_modifiers.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH(GpencilModifierData *, md, &object->greasepencil_modifiers) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo((GpencilModifierType)md->type);
+ if (mti->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
+ mti->updateDepsgraph(md, &ctx);
+ }
+ if (BKE_object_modifier_gpencil_use_time(object, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Shader FX */
+ if (object->shader_fx.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH(ShaderFxData *, fx, &object->shader_fx) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type);
+ if (fxi->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
+ fxi->updateDepsgraph(fx, &ctx);
+ }
+ if (BKE_object_shaderfx_use_time(object, fx)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
/* Materials. */
if (object->totcol) {
for (int a = 1; a <= object->totcol; a++) {
@@ -1880,13 +1938,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
}
/* Link object data evaluation node to exit operation. */
OperationKey obdata_geom_eval_key(obdata,
- DEG_NODE_TYPE_GEOMETRY,
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
OperationKey obdata_geom_done_key(obdata,
- DEG_NODE_TYPE_GEOMETRY,
- DEG_OPCODE_PLACEHOLDER,
- "Eval Done");
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_PLACEHOLDER,
+ "Eval Done");
add_relation(obdata_geom_eval_key,
obdata_geom_done_key,
"ObData Geom Eval Done");
@@ -1902,35 +1960,67 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
Curve *cu = (Curve *)obdata;
if (cu->bevobj != NULL) {
ComponentKey bevob_geom_key(&cu->bevobj->id,
- DEG_NODE_TYPE_GEOMETRY);
+ DEG_NODE_TYPE_GEOMETRY);
add_relation(bevob_geom_key,
- obdata_geom_eval_key,
- "Curve Bevel Geometry");
+ obdata_geom_eval_key,
+ "Curve Bevel Geometry");
ComponentKey bevob_key(&cu->bevobj->id,
- DEG_NODE_TYPE_TRANSFORM);
+ DEG_NODE_TYPE_TRANSFORM);
add_relation(bevob_key,
- obdata_geom_eval_key,
- "Curve Bevel Transform");
+ obdata_geom_eval_key,
+ "Curve Bevel Transform");
build_object(NULL, cu->bevobj);
}
if (cu->taperobj != NULL) {
ComponentKey taperob_key(&cu->taperobj->id,
- DEG_NODE_TYPE_GEOMETRY);
+ DEG_NODE_TYPE_GEOMETRY);
add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
build_object(NULL, cu->taperobj);
}
if (cu->textoncurve != NULL) {
ComponentKey textoncurve_key(&cu->textoncurve->id,
- DEG_NODE_TYPE_GEOMETRY);
+ DEG_NODE_TYPE_GEOMETRY);
add_relation(textoncurve_key,
- obdata_geom_eval_key,
- "Text on Curve");
+ obdata_geom_eval_key,
+ "Text on Curve");
build_object(NULL, cu->textoncurve);
}
break;
}
case ID_LT:
break;
+ case ID_GD: /* Grease Pencil */
+ {
+ bGPdata *gpd = (bGPdata *)obdata;
+
+ /* Geometry cache needs to be recalculated on frame change
+ * (e.g. to fix crashes after scrubbing the timeline when
+ * onion skinning is enabled, since the ghosts need to be
+ * re-added to the cache once scrubbing ends)
+ */
+ TimeSourceKey time_key;
+ ComponentKey geometry_key(obdata, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(time_key,
+ geometry_key,
+ "GP Frame Change");
+
+ /* Geometry cache also needs to be recalculated when Material
+ * settings change (e.g. when fill.opacity changes on/off,
+ * we need to rebuild the bGPDstroke->triangles caches)
+ */
+ for (int i = 0; i < gpd->totcol; i++) {
+ Material *ma = gpd->mat[i];
+ if ((ma != NULL) && (ma->gp_style != NULL)) {
+ OperationKey material_key(&ma->id,
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ add_relation(material_key,
+ geometry_key,
+ "Material -> GP Data");
+ }
+ }
+ break;
+ }
default:
BLI_assert(!"Should not happen");
break;
@@ -2213,6 +2303,11 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node
if (id_type == ID_ME && comp_node->type == DEG_NODE_TYPE_GEOMETRY) {
rel_flag &= ~DEPSREL_FLAG_NO_FLUSH;
}
+ /* materials need update grease pencil objects */
+ if (id_type == ID_MA) {
+ rel_flag &= ~DEPSREL_FLAG_NO_FLUSH;
+ }
+
/* Notes on exceptions:
* - Parameters component is where drivers are living. Changing any
* of the (custom) properties in the original datablock (even the
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index eaa17d27ffc..811986ea0e8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -469,11 +469,20 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
DEG_NODE_TYPE_BONE,
pchan->name,
DEG_OPCODE_BONE_DONE);
+ OperationKey from_bone_done_key(&proxy_from->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ DEG_OPCODE_BONE_DONE);
add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
+ /* Make sure bone in the proxy is not done before it's FROM is done. */
+ add_relation(from_bone_done_key,
+ bone_done_key,
+ "From Bone Done -> Pose Done");
+
if (pchan->prop != NULL) {
OperationKey bone_parameters(&object->id,
DEG_NODE_TYPE_PARAMETERS,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index f069c63f138..78d1a930eb7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -123,10 +123,6 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
if (scene->nodetree != NULL) {
build_compositor(scene);
}
- /* Grease pencil. */
- if (scene->gpd != NULL) {
- build_gpencil(scene->gpd);
- }
/* Masks. */
LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) {
build_mask(mask);
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index ca9f32d4d8c..a6c930196ef 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -128,10 +128,10 @@ Scene *DEG_get_evaluated_scene(const Depsgraph *graph)
reinterpret_cast<const DEG::Depsgraph *>(graph);
Scene *scene_cow = deg_graph->scene_cow;
/* TODO(sergey): Shall we expand datablock here? Or is it OK to assume
- * that calleer is OK with just a pointer in case scene is not up[dated
+ * that calleer is OK with just a pointer in case scene is not updated
* yet?
*/
- BLI_assert(DEG::deg_copy_on_write_is_expanded(&scene_cow->id));
+ BLI_assert(scene_cow != NULL && DEG::deg_copy_on_write_is_expanded(&scene_cow->id));
return scene_cow;
}
@@ -140,6 +140,9 @@ ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph)
const DEG::Depsgraph *deg_graph =
reinterpret_cast<const DEG::Depsgraph *>(graph);
Scene *scene_cow = DEG_get_evaluated_scene(graph);
+ if (scene_cow == NULL) {
+ return NULL; /* Happens with new, not-yet-built/evaluated graphes. */
+ }
/* Do name-based lookup. */
/* TODO(sergey): Can this be optimized? */
ViewLayer *view_layer_orig = deg_graph->view_layer;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 4229f8bf9a2..e4659a7a94d 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -100,6 +100,7 @@ void depsgraph_geometry_tag_to_component(const ID *id,
case OB_FONT:
case OB_LATTICE:
case OB_MBALL:
+ case OB_GPENCIL:
*component_type = DEG_NODE_TYPE_GEOMETRY;
break;
case OB_ARMATURE:
@@ -112,11 +113,17 @@ void depsgraph_geometry_tag_to_component(const ID *id,
case ID_ME:
*component_type = DEG_NODE_TYPE_GEOMETRY;
break;
- case ID_PA:
+ case ID_PA: /* Particles */
return;
case ID_LP:
*component_type = DEG_NODE_TYPE_PARAMETERS;
break;
+ case ID_GD:
+ *component_type = DEG_NODE_TYPE_GEOMETRY;
+ break;
+ case ID_PAL: /* Palettes */
+ *component_type = DEG_NODE_TYPE_PARAMETERS;
+ break;
default:
break;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 20aec0ba5ed..9ed50fafc3d 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -548,9 +548,13 @@ void update_special_pointers(const Depsgraph *depsgraph,
object_cow->runtime.mesh_orig = (Mesh *)object_cow->data;
}
if (object_cow->type == OB_ARMATURE) {
- BKE_pose_remap_bone_pointers((bArmature *)object_cow->data,
- object_cow->pose);
- update_pose_orig_pointers(object_orig->pose, object_cow->pose);
+ const bArmature *armature_orig = (bArmature *)object_orig->data;
+ bArmature *armature_cow = (bArmature *)object_cow->data;
+ BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
+ if (armature_orig->edbo == NULL) {
+ update_pose_orig_pointers(object_orig->pose,
+ object_cow->pose);
+ }
}
update_particle_system_orig_pointers(object_orig, object_cow);
break;
@@ -719,20 +723,19 @@ static void deg_update_copy_on_write_animation(const Depsgraph *depsgraph,
}
typedef struct ObjectRuntimeBackup {
- CurveCache *curve_cache;
Object_Runtime runtime;
short base_flag;
} ObjectRuntimeBackup;
/* Make a backup of object's evaluation runtime data, additionally
- * male object to be safe for free without invalidating backed up
+ * make object to be safe for free without invalidating backed up
* pointers.
*/
static void deg_backup_object_runtime(
Object *object,
ObjectRuntimeBackup *object_runtime_backup)
{
- /* Store evaluated mesh, and make sure we don't free it. */
+ /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
Mesh *mesh_eval = object->runtime.mesh_eval;
object_runtime_backup->runtime = object->runtime;
BKE_object_runtime_reset(object);
@@ -743,9 +746,6 @@ static void deg_backup_object_runtime(
if (mesh_eval != NULL && object->data == mesh_eval) {
object->data = object->runtime.mesh_orig;
}
- /* Store curve cache and make sure we don't free it. */
- object_runtime_backup->curve_cache = object->curve_cache;
- object->curve_cache = NULL;
/* Make a backup of base flags. */
object_runtime_backup->base_flag = object->base_flag;
}
@@ -757,7 +757,7 @@ static void deg_restore_object_runtime(
Mesh *mesh_orig = object->runtime.mesh_orig;
object->runtime = object_runtime_backup->runtime;
object->runtime.mesh_orig = mesh_orig;
- if (object->runtime.mesh_eval != NULL) {
+ if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
if (object->id.recalc & ID_RECALC_GEOMETRY) {
/* If geometry is tagged for update it means, that part of
* evaluated mesh are not valid anymore. In this case we can not
@@ -773,19 +773,14 @@ static void deg_restore_object_runtime(
/* Do same thing as object update: override actual object data
* pointer with evaluated datablock.
*/
- if (object->type == OB_MESH) {
- object->data = mesh_eval;
- /* Evaluated mesh simply copied edit_btmesh pointer from
- * original mesh during update, need to make sure no dead
- * pointers are left behind.
- */
- mesh_eval->edit_btmesh = mesh_orig->edit_btmesh;
- }
+ object->data = mesh_eval;
+ /* Evaluated mesh simply copied edit_btmesh pointer from
+ * original mesh during update, need to make sure no dead
+ * pointers are left behind.
+ */
+ mesh_eval->edit_btmesh = mesh_orig->edit_btmesh;
}
}
- if (object_runtime_backup->curve_cache != NULL) {
- object->curve_cache = object_runtime_backup->curve_cache;
- }
object->base_flag = object_runtime_backup->base_flag;
}
diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h
index e00aa5dbb5e..5484192207b 100644
--- a/source/blender/depsgraph/util/deg_util_foreach.h
+++ b/source/blender/depsgraph/util/deg_util_foreach.h
@@ -30,11 +30,4 @@
#pragma once
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# define foreach(x, y) for(x : y)
-#elif defined(HAVE_BOOST_FUNCTION_BINDINGS)
-# include <boost/foreach.hpp>
-# define foreach BOOST_FOREACH
-#else
-# error "Depsgraph requires either Boost or C++11 for range-based loops."
-#endif
+#define foreach(x, y) for(x : y)
diff --git a/source/blender/depsgraph/util/deg_util_function.h b/source/blender/depsgraph/util/deg_util_function.h
index e91986d54ba..8863d92eb74 100644
--- a/source/blender/depsgraph/util/deg_util_function.h
+++ b/source/blender/depsgraph/util/deg_util_function.h
@@ -30,22 +30,8 @@
#pragma once
-#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
-
#include <functional>
using std::function;
using namespace std::placeholders;
#define function_bind std::bind
-
-#elif defined(HAVE_BOOST_FUNCTION_BINDINGS)
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-
-using boost::function;
-#define function_bind boost::bind
-
-#else
-# error "Depsgraph requires either Boost or C++11 for function bindings."
-#endif
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 7d710d2711c..d8420d6a127 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -118,10 +118,19 @@ set(SRC
engines/workbench/workbench_effect_taa.c
engines/workbench/workbench_forward.c
engines/workbench/workbench_materials.c
+ engines/workbench/workbench_render.c
engines/workbench/workbench_studiolight.c
+ engines/workbench/workbench_volume.c
engines/workbench/solid_mode.c
engines/workbench/transparent_mode.c
engines/external/external_engine.c
+ engines/gpencil/gpencil_engine.h
+ engines/gpencil/gpencil_engine.c
+ engines/gpencil/gpencil_render.c
+ engines/gpencil/gpencil_cache_utils.c
+ engines/gpencil/gpencil_draw_utils.c
+ engines/gpencil/gpencil_draw_cache_impl.c
+ engines/gpencil/gpencil_shader_fx.c
DRW_engine.h
intern/DRW_render.h
@@ -226,6 +235,8 @@ data_to_c_simple(engines/workbench/shaders/workbench_shadow_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shadow_geom.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shadow_caps_geom.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shadow_debug_frag.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_volume_vert.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_volume_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
@@ -298,6 +309,34 @@ data_to_c_simple(modes/shaders/paint_wire_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_vert_frag.glsl SRC)
data_to_c_simple(modes/shaders/particle_strand_frag.glsl SRC)
data_to_c_simple(modes/shaders/particle_strand_vert.glsl SRC)
+data_to_c_simple(modes/shaders/volume_velocity_vert.glsl SRC)
+
+data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_geom.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_simple_mix_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_point_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_point_geom.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_point_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_background_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_paper_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_geom.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_frag.glsl SRC)
+
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
+
list(APPEND INC
)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index ab2001dcb6a..6d8e8a69e29 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -126,6 +126,9 @@ void DRW_draw_depth_loop(
struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d);
+/* grease pencil render */
+void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph);
+
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);
struct DRWInstanceDataList *DRW_instance_data_list_create(void);
@@ -136,10 +139,14 @@ void DRW_opengl_context_destroy(void);
void DRW_opengl_context_enable(void);
void DRW_opengl_context_disable(void);
+/* Never use this. Only for closing blender. */
+void DRW_opengl_context_enable_ex(bool restore);
+void DRW_opengl_context_disable_ex(bool restore);
+
void DRW_opengl_render_context_enable(void *re_gl_context);
void DRW_opengl_render_context_disable(void *re_gl_context);
-void DRW_gawain_render_context_enable(void *re_gwn_context);
-void DRW_gawain_render_context_disable(void *re_gwn_context);
+void DRW_gawain_render_context_enable(void *re_gpu_context);
+void DRW_gawain_render_context_disable(void *re_gpu_context);
void DRW_deferred_shader_remove(struct GPUMaterial *mat);
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 5a315cde2b5..57553d98d5d 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -42,9 +42,6 @@
#define BASIC_ENGINE "BLENDER_BASIC"
-/* we may want this later? */
-#define USE_DEPTH
-
/* *********** LISTS *********** */
/* GPUViewport.storage
@@ -54,11 +51,8 @@ typedef struct BASIC_StorageList {
} BASIC_StorageList;
typedef struct BASIC_PassList {
-#ifdef USE_DEPTH
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
-#endif
- struct DRWPass *color_pass;
} BASIC_PassList;
typedef struct BASIC_Data {
@@ -72,38 +66,24 @@ typedef struct BASIC_Data {
/* *********** STATIC *********** */
static struct {
-#ifdef USE_DEPTH
/* Depth Pre Pass */
struct GPUShader *depth_sh;
-#endif
- /* Shading Pass */
- struct GPUShader *color_sh;
} e_data = {NULL}; /* Engine data */
typedef struct BASIC_PrivateData {
-#ifdef USE_DEPTH
DRWShadingGroup *depth_shgrp;
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp_hair;
-#endif
- DRWShadingGroup *color_shgrp;
} BASIC_PrivateData; /* Transient data */
/* Functions */
static void basic_engine_init(void *UNUSED(vedata))
{
-#ifdef USE_DEPTH
/* Depth prepass */
if (!e_data.depth_sh) {
e_data.depth_sh = DRW_shader_create_3D_depth_only();
}
-#endif
-
- /* Shading pass */
- if (!e_data.color_sh) {
- e_data.color_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
- }
}
static void basic_cache_init(void *vedata)
@@ -116,8 +96,6 @@ static void basic_cache_init(void *vedata)
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
}
-#ifdef USE_DEPTH
- /* Depth Pass */
{
psl->depth_pass = DRW_pass_create(
"Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
@@ -128,13 +106,6 @@ static void basic_cache_init(void *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
}
-#endif
-
- /* Color Pass */
- {
- psl->color_pass = DRW_pass_create("Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
- stl->g_data->color_shgrp = DRW_shgroup_create(e_data.color_sh, psl->color_pass);
- }
}
static void basic_cache_populate(void *vedata, Object *ob)
@@ -160,21 +131,17 @@ static void basic_cache_populate(void *vedata, Object *ob)
ParticleSettings *part = psys->part;
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
- struct Gwn_Batch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
+ struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
DRW_shgroup_call_add(stl->g_data->depth_shgrp, hairs, NULL);
}
}
}
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
- bool do_cull = false; /* TODO (we probably wan't to take this from the viewport?) */
-#ifdef USE_DEPTH
+ const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
/* Depth Prepass */
DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
-#endif
- /* Shading */
- DRW_shgroup_call_add(stl->g_data->color_shgrp, geom, ob->obmat);
}
}
@@ -187,36 +154,10 @@ static void basic_cache_finish(void *vedata)
static void basic_draw_scene(void *vedata)
{
-
BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
- const bool is_select = DRW_state_is_select();
-
- bool use_color = true;
- bool use_depth = true;
- bool use_depth_cull = true;
- if (is_select) {
- /* Needed for depth-picking,
- * for other selection types there are no need for extra passes either. */
- use_color = false;
- use_depth_cull = false;
- }
-
-#ifdef USE_DEPTH
- /* Pass 1 : Depth pre-pass */
- if (use_depth) {
- DRW_draw_pass(psl->depth_pass);
- }
-
- if (use_depth_cull) {
- DRW_draw_pass(psl->depth_pass_cull);
- }
-#endif
-
- /* Pass 3 : Shading */
- if (use_color) {
- DRW_draw_pass(psl->color_pass);
- }
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
}
static void basic_engine_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
index 2ec6f841409..d111c28b256 100644
--- a/source/blender/draw/engines/eevee/eevee_bloom.c
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -196,7 +196,7 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
static DRWShadingGroup *eevee_create_bloom_pass(
const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
{
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
*pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 96e784b524c..636e532555f 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -30,7 +30,7 @@
#include "eevee_private.h"
#include "eevee_lightcache.h"
-static void eevee_view_layer_data_free(void *storage)
+void EEVEE_view_layer_data_free(void *storage)
{
EEVEE_ViewLayerData *sldata = (EEVEE_ViewLayerData *)storage;
@@ -77,7 +77,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer)
{
EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure_ex(
- view_layer, &draw_engine_eevee_type, &eevee_view_layer_data_free);
+ view_layer, &draw_engine_eevee_type, &EEVEE_view_layer_data_free);
if (*sldata == NULL) {
*sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData");
@@ -89,7 +89,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_laye
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void)
{
EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure(
- &draw_engine_eevee_type, &eevee_view_layer_data_free);
+ &draw_engine_eevee_type, &EEVEE_view_layer_data_free);
if (*sldata == NULL) {
*sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData");
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index b9f7624552c..cb54ad3a164 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -192,7 +192,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
* - Finally composite the 2 blurred buffers with the original render.
**/
DRWShadingGroup *grp;
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR);
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index d7a978066d5..28658d5126c 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -302,7 +302,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
downsample_write = DRW_STATE_WRITE_COLOR;
}
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
{
psl->color_downsample_ps = DRW_pass_create(
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index adbe165354a..8c66ba057b5 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -66,6 +66,7 @@ static void eevee_engine_init(void *ved)
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
+ stl->g_data->use_color_view_settings = USE_SCENE_LIGHT(v3d) || !LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d);
stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
@@ -316,37 +317,39 @@ static void eevee_draw_background(void *vedata)
/* Tonemapping and transfer result to default framebuffer. */
+ bool use_view_settings = stl->g_data->use_color_view_settings;
+
GPU_framebuffer_bind(dfbl->default_fb);
- DRW_transform_to_display(stl->effects->final_tx);
+ DRW_transform_to_display(stl->effects->final_tx, use_view_settings);
/* Debug : Ouput buffer to view. */
switch (G.debug_value) {
case 1:
- if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
+ if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer, use_view_settings);
break;
case 2:
- if (effects->ssr_pdf_output) DRW_transform_to_display(effects->ssr_pdf_output);
+ if (effects->ssr_pdf_output) DRW_transform_to_display(effects->ssr_pdf_output, use_view_settings);
break;
case 3:
- if (effects->ssr_normal_input) DRW_transform_to_display(effects->ssr_normal_input);
+ if (effects->ssr_normal_input) DRW_transform_to_display(effects->ssr_normal_input, use_view_settings);
break;
case 4:
- if (effects->ssr_specrough_input) DRW_transform_to_display(effects->ssr_specrough_input);
+ if (effects->ssr_specrough_input) DRW_transform_to_display(effects->ssr_specrough_input, use_view_settings);
break;
case 5:
- if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
+ if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer, use_view_settings);
break;
case 6:
- if (effects->gtao_horizons_debug) DRW_transform_to_display(effects->gtao_horizons_debug);
+ if (effects->gtao_horizons_debug) DRW_transform_to_display(effects->gtao_horizons_debug, use_view_settings);
break;
case 7:
- if (effects->gtao_horizons) DRW_transform_to_display(effects->gtao_horizons);
+ if (effects->gtao_horizons) DRW_transform_to_display(effects->gtao_horizons, use_view_settings);
break;
case 8:
- if (effects->sss_data) DRW_transform_to_display(effects->sss_data);
+ if (effects->sss_data) DRW_transform_to_display(effects->sss_data, use_view_settings);
break;
case 9:
- if (effects->velocity_tx) DRW_transform_to_display(effects->velocity_tx);
+ if (effects->velocity_tx) DRW_transform_to_display(effects->velocity_tx, use_view_settings);
break;
default:
break;
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index bf3ee34a03e..da55cbca2e0 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -45,7 +45,7 @@
#include "eevee_lightcache.h"
#include "eevee_private.h"
-#include "../../../intern/gawain/gawain/gwn_context.h"
+#include "GPU_context.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -83,8 +83,8 @@ extern void DRW_opengl_context_disable(void);
extern void DRW_opengl_render_context_enable(void *re_gl_context);
extern void DRW_opengl_render_context_disable(void *re_gl_context);
-extern void DRW_gawain_render_context_enable(void *re_gwn_context);
-extern void DRW_gawain_render_context_disable(void *re_gwn_context);
+extern void DRW_gawain_render_context_enable(void *re_gpu_context);
+extern void DRW_gawain_render_context_disable(void *re_gpu_context);
typedef struct EEVEE_LightBake {
Depsgraph *depsgraph;
@@ -93,6 +93,7 @@ typedef struct EEVEE_LightBake {
LightCache *lcache;
Scene *scene;
struct Main *bmain;
+ EEVEE_ViewLayerData *sldata;
LightProbe **probe; /* Current probe being rendered. */
GPUTexture *rt_color; /* Target cube color texture. */
@@ -144,7 +145,7 @@ typedef struct EEVEE_LightBake {
bool own_light_cache; /* If the lightcache was created for baking, it's first owned by the baker. */
int delay; /* ms. delay the start of the baking to not slowdown interactions (TODO remove) */
- void *gl_context, *gwn_context; /* If running in parallel (in a separate thread), use this context. */
+ void *gl_context, *gpu_context; /* If running in parallel (in a separate thread), use this context. */
} EEVEE_LightBake;
/* -------------------------------------------------------------------- */
@@ -369,10 +370,10 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
{
if (lbake->gl_context) {
DRW_opengl_render_context_enable(lbake->gl_context);
- if (lbake->gwn_context == NULL) {
- lbake->gwn_context = GWN_context_create();
+ if (lbake->gpu_context == NULL) {
+ lbake->gpu_context = GPU_context_create();
}
- DRW_gawain_render_context_enable(lbake->gwn_context);
+ DRW_gawain_render_context_enable(lbake->gpu_context);
}
else {
DRW_opengl_context_enable();
@@ -382,7 +383,7 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake)
{
if (lbake->gl_context) {
- DRW_gawain_render_context_disable(lbake->gwn_context);
+ DRW_gawain_render_context_disable(lbake->gpu_context);
DRW_opengl_render_context_disable(lbake->gl_context);
}
else {
@@ -586,7 +587,7 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
{
if (lbake->gl_context) {
DRW_opengl_render_context_enable(lbake->gl_context);
- DRW_gawain_render_context_enable(lbake->gwn_context);
+ DRW_gawain_render_context_enable(lbake->gpu_context);
}
else if (!lbake->resource_only) {
DRW_opengl_context_enable();
@@ -597,6 +598,12 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
lbake->lcache = NULL;
}
+ /* XXX Free the resources contained in the viewlayer data
+ * to be able to free the context before deleting the depsgraph. */
+ if (lbake->sldata) {
+ EEVEE_view_layer_data_free(lbake->sldata);
+ }
+
DRW_TEXTURE_FREE_SAFE(lbake->rt_depth);
DRW_TEXTURE_FREE_SAFE(lbake->rt_color);
DRW_TEXTURE_FREE_SAFE(lbake->grid_prev);
@@ -605,17 +612,17 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
GPU_FRAMEBUFFER_FREE_SAFE(lbake->rt_fb[i]);
}
- if (lbake->gwn_context) {
- DRW_gawain_render_context_disable(lbake->gwn_context);
- DRW_gawain_render_context_enable(lbake->gwn_context);
- GWN_context_discard(lbake->gwn_context);
+ if (lbake->gpu_context) {
+ DRW_gawain_render_context_disable(lbake->gpu_context);
+ DRW_gawain_render_context_enable(lbake->gpu_context);
+ GPU_context_discard(lbake->gpu_context);
}
if (lbake->gl_context && lbake->own_resources) {
/* Delete the baking context. */
DRW_opengl_render_context_disable(lbake->gl_context);
WM_opengl_context_dispose(lbake->gl_context);
- lbake->gwn_context = NULL;
+ lbake->gpu_context = NULL;
lbake->gl_context = NULL;
}
else if (lbake->gl_context) {
@@ -633,6 +640,8 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
+ lbake->sldata = sldata;
+
/* Disable all effects BUT high bitdepth shadows. */
scene_eval->eevee.flag &= SCE_EEVEE_SHADOW_HIGH_BITDEPTH;
scene_eval->eevee.taa_samples = 1;
@@ -746,6 +755,9 @@ static void compute_cell_id(
probe->grid_resolution_z)));
int visited_cells = 0;
+ *r_stride = 0;
+ *r_final_idx = 0;
+ r_local_cell[0] = r_local_cell[1] = r_local_cell[2] = 0;
for (int lvl = max_lvl; lvl >= 0; --lvl) {
*r_stride = 1 << lvl;
int prev_stride = *r_stride << 1;
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h
index b58a0544c59..3c6fc73a849 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.h
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.h
@@ -56,4 +56,4 @@ void EEVEE_lightcache_free(struct LightCache *lcache);
void EEVEE_lightcache_load(struct LightCache *lcache);
void EEVEE_lightcache_info_update(struct SceneEEVEE *eevee);
-#endif /* __EEVEE_LIGHTCACHE_H__ */ \ No newline at end of file
+#endif /* __EEVEE_LIGHTCACHE_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 1b341aced07..50f4e694d2a 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -74,8 +74,8 @@ static struct {
struct GPUTexture *depth_array_placeholder;
struct GPUTexture *cube_face_minmaxz;
- struct Gwn_VertFormat *format_probe_display_cube;
- struct Gwn_VertFormat *format_probe_display_planar;
+ struct GPUVertFormat *format_probe_display_cube;
+ struct GPUVertFormat *format_probe_display_planar;
} e_data = {NULL}; /* Engine data */
extern char datatoc_background_vert_glsl[];
@@ -376,7 +376,10 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
}
{
@@ -394,8 +397,9 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
#endif
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
}
@@ -413,8 +417,9 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
}
@@ -424,7 +429,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_fill_sh, psl->probe_grid_fill);
DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &light_cache->grid_tx.tex);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
}
}
@@ -447,7 +452,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
{
psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
Scene *scene = draw_ctx->scene;
@@ -471,6 +476,13 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
case GPU_MAT_SUCCESS:
grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove thoses (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_call_add(grp, geom, NULL);
break;
default:
@@ -489,7 +501,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
}
}
- if (DRW_state_draw_support()) {
+ if (DRW_state_draw_support() && !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
psl->probe_display = DRW_pass_create("LightProbe Display", state);
@@ -503,6 +515,9 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
DRW_shgroup_uniform_float_copy(grp, "sphere_size", scene_eval->eevee.gi_cubemap_draw_size * 0.5f);
+ /* TODO (fclem) get rid of thoses UBO. */
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
}
/* Grid Display */
@@ -519,6 +534,11 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_vec3(shgrp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
DRW_shgroup_uniform_float_copy(shgrp, "sphere_size", scene_eval->eevee.gi_irradiance_draw_size * 0.5f);
+ /* TODO (fclem) get rid of thoses UBO. */
+ DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 0f0d9d281c9..2c970fa5285 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -37,6 +37,8 @@
#define SHADOW_CASTER_ALLOC_CHUNK 16
+// #define DEBUG_CSM
+
static struct {
struct GPUShader *shadow_sh;
struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX];
@@ -423,7 +425,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Add a shadow caster to the shadowpasses */
void EEVEE_lights_cache_shcaster_add(
- EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob)
+ EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_StorageList *stl, struct GPUBatch *geom, Object *ob)
{
DRW_shgroup_call_object_add(
stl->g_data->shadow_shgrp,
@@ -432,7 +434,7 @@ void EEVEE_lights_cache_shcaster_add(
void EEVEE_lights_cache_shcaster_material_add(
EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl, struct GPUMaterial *gpumat,
- struct Gwn_Batch *geom, struct Object *ob, float *alpha_threshold)
+ struct GPUBatch *geom, struct Object *ob, float *alpha_threshold)
{
/* TODO / PERF : reuse the same shading group for objects with the same material */
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
@@ -871,13 +873,13 @@ static void eevee_shadow_cascade_setup(
/* Given 8 frustum corners */
float corners[8][3] = {
/* Near Cap */
- {-1.0f, -1.0f, splits_start_ndc[c]},
{ 1.0f, -1.0f, splits_start_ndc[c]},
+ {-1.0f, -1.0f, splits_start_ndc[c]},
{-1.0f, 1.0f, splits_start_ndc[c]},
{ 1.0f, 1.0f, splits_start_ndc[c]},
/* Far Cap */
- {-1.0f, -1.0f, splits_end_ndc[c]},
{ 1.0f, -1.0f, splits_end_ndc[c]},
+ {-1.0f, -1.0f, splits_end_ndc[c]},
{-1.0f, 1.0f, splits_end_ndc[c]},
{ 1.0f, 1.0f, splits_end_ndc[c]}
};
@@ -890,8 +892,17 @@ static void eevee_shadow_cascade_setup(
float center[3];
frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c]));
+#ifdef DEBUG_CSM
+ float dbg_col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ if (c < 3) {
+ dbg_col[c] = 1.0f;
+ }
+ DRW_debug_bbox((BoundBox *)&corners, dbg_col);
+ DRW_debug_sphere(center, sh_data->radius[c], dbg_col);
+#endif
+
/* Project into lightspace */
- mul_mat3_m4_v3(viewmat, center);
+ mul_m4_v3(viewmat, center);
/* Snap projection center to nearest texel to cancel shimmering. */
float shadow_origin[2], shadow_texco[2];
@@ -919,6 +930,10 @@ static void eevee_shadow_cascade_setup(
mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat);
mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]);
+
+#ifdef DEBUG_CSM
+ DRW_debug_m4_as_bbox(sh_data->viewprojmat[c], dbg_col, true);
+#endif
}
ubo_data->bias = 0.05f * la->bias;
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index 2e568d97c07..deb724c9ae6 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -60,7 +60,7 @@ void EEVEE_lookdev_cache_init(
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
if (sl && (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) {
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
GPUTexture *tex = NULL;
/* If one of the component is missing we start from scratch. */
@@ -112,18 +112,14 @@ void EEVEE_lookdev_cache_init(
if (!pinfo) {
/* Do not fadeout when doing probe rendering, only when drawing the background */
DRW_shgroup_uniform_float(*grp, "studioLightBackground", &v3d->shading.studiolight_background, 1);
- if (v3d->shading.studiolight_background > 0.0f) {
- BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE);
- tex = sl->equirectangular_irradiance_gputexture;
- }
+ BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE);
+ tex = sl->equirectangular_irradiance_gputexture;
}
else {
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE);
tex = sl->equirectangular_radiance_gputexture;
}
- if (tex != NULL) {
- DRW_shgroup_uniform_texture(*grp, "image", tex);
- }
+ DRW_shgroup_uniform_texture(*grp, "image", tex);
/* Do we need to recalc the lightprobes? */
if (pinfo &&
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 040b937f5b2..1eb63e0f0eb 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -137,7 +137,7 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
@@ -199,7 +199,7 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
@@ -362,7 +362,9 @@ static char *eevee_get_volume_defines(int options)
**/
static void add_standard_uniforms(
DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
- int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend)
+ int *ssr_id, float *refract_depth,
+ bool use_diffuse, bool use_glossy, bool use_refract,
+ bool use_ssrefraction, bool use_alpha_blend)
{
LightCache *lcache = vedata->stl->g_data->light_cache;
@@ -379,13 +381,13 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo);
- /* TODO if glossy or diffuse bsdf */
- if (true) {
+ if (use_diffuse || use_glossy || use_refract) {
DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
-
+ }
+ if ((use_diffuse || use_glossy) && !use_refract) {
if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons);
}
@@ -394,20 +396,17 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
}
}
-
- /* TODO if diffuse bsdf */
- if (true) {
+ if (use_diffuse) {
DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
}
-
- /* TODO if glossy bsdf */
- if (true) {
+ if (use_glossy || use_refract) {
DRW_shgroup_uniform_texture_ref(shgrp, "probeCubes", &lcache->cube_tx.tex);
+ }
+ if (use_glossy) {
DRW_shgroup_uniform_texture_ref(shgrp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
}
-
- if (use_ssrefraction) {
+ if (use_refract || use_ssrefraction) {
BLI_assert(refract_depth != NULL);
DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
@@ -565,6 +564,8 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
datatoc_volumetric_lib_glsl);
e_data.volume_shader_lib = BLI_string_joinN(
@@ -854,7 +855,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
}
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, use_blend);
return shgrp;
}
@@ -893,7 +894,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
* EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
if (!is_hair) {
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false);
}
}
@@ -909,7 +910,8 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
vedata->psl->default_pass[options],
e_data.default_lit[options]);
}
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false);
+
return shgrp;
}
else {
@@ -941,7 +943,7 @@ static struct DRWShadingGroup *EEVEE_lookdev_shading_group_get(
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass);
/* XXX / WATCH: This creates non persistent binds for the ubos and textures.
* But it's currently OK because the following shgroups does not add any bind. */
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false);
}
return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass);
@@ -959,7 +961,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
psl->background_pass = DRW_pass_create("Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
- struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -984,6 +986,13 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
case GPU_MAT_SUCCESS:
grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove thoses (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_call_add(grp, geom, NULL);
break;
case GPU_MAT_QUEUED:
@@ -1122,6 +1131,7 @@ static void material_opaque(
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_LampsInfo *linfo = sldata->lamps;
+ bool use_diffuse, use_glossy, use_refract;
float *color_p = &ma->r;
float *metal_p = &ma->metallic;
@@ -1129,10 +1139,9 @@ static void material_opaque(
float *rough_p = &ma->roughness;
const bool use_gpumat = (ma->use_nodes && ma->nodetree);
- const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
+ const bool use_ssrefract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) &&
- ((effects->enabled_effects & EFFECT_SSS) != 0);
+ bool use_sss = ((effects->enabled_effects & EFFECT_SSS) != 0);
const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -1144,7 +1153,7 @@ static void material_opaque(
/* This will have been created already, just perform a lookup. */
*gpumat = (use_gpumat) ? EEVEE_material_mesh_get(
- scene, ma, vedata, false, false, use_refract, use_sss, use_translucency, linfo->shadow_method) : NULL;
+ scene, ma, vedata, false, false, use_ssrefract, use_sss, use_translucency, linfo->shadow_method) : NULL;
*gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
scene, ma, (ma->blend_method == MA_BM_HASHED), false) : NULL;
return;
@@ -1157,7 +1166,7 @@ static void material_opaque(
/* Shading */
*gpumat = EEVEE_material_mesh_get(
- scene, ma, vedata, false, false, use_refract,
+ scene, ma, vedata, false, false, use_ssrefract,
use_sss, use_translucency, linfo->shadow_method);
GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
@@ -1173,7 +1182,7 @@ static void material_opaque(
* the surface shader. */
status_mat_surface = status_mat_depth;
}
- else if (use_refract) {
+ else if (use_ssrefract) {
*shgrp_depth = DRW_shgroup_material_create(
*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
*shgrp_depth_clip = DRW_shgroup_material_create(
@@ -1187,8 +1196,14 @@ static void material_opaque(
}
if (*shgrp_depth != NULL) {
- add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false);
- add_standard_uniforms(*shgrp_depth_clip, sldata, vedata, NULL, NULL, false, false);
+ use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE);
+ use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY);
+ use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT);
+
+ add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL,
+ use_diffuse, use_glossy, use_refract, false, false);
+ add_standard_uniforms(*shgrp_depth_clip, sldata, vedata, NULL, NULL,
+ use_diffuse, use_glossy, use_refract, false, false);
if (ma->blend_method == MA_BM_CLIP) {
DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1);
@@ -1206,13 +1221,19 @@ static void material_opaque(
{
static int no_ssr = -1;
static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr;
+ int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? &first_ssr : &no_ssr;
+ use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
+ use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
+ use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
+ use_sss = use_sss && GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
*shgrp = DRW_shgroup_material_create(
*gpumat,
- (use_refract) ? psl->refract_pass :
+ (use_ssrefract) ? psl->refract_pass :
(use_sss) ? psl->sss_pass : psl->material_pass);
- add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
+
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth,
+ use_diffuse, use_glossy, use_refract, use_ssrefract, false);
if (use_sss) {
struct GPUTexture *sss_tex_profile = NULL;
@@ -1243,7 +1264,6 @@ static void material_opaque(
}
case GPU_MAT_QUEUED:
{
- /* TODO Bypass probe compilation. */
color_p = compile_col;
metal_p = spec_p = rough_p = &half;
break;
@@ -1270,7 +1290,7 @@ static void material_opaque(
/* Fallback default depth prepass */
if (*shgrp_depth == NULL) {
- if (use_refract) {
+ if (use_ssrefract) {
*shgrp_depth = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : stl->g_data->refract_depth_shgrp;
*shgrp_depth_clip = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : stl->g_data->refract_depth_shgrp_clip;
}
@@ -1298,7 +1318,7 @@ static void material_transparent(
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_LampsInfo *linfo = sldata->lamps;
- const bool use_refract = (
+ const bool use_ssrefract = (
((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((stl->effects->enabled_effects & EFFECT_REFRACT) != 0)
);
@@ -1314,7 +1334,7 @@ static void material_transparent(
/* Shading */
*gpumat = EEVEE_material_mesh_get(
- scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract,
+ scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_ssrefract,
false, false, linfo->shadow_method);
switch (GPU_material_status(*gpumat)) {
@@ -1324,7 +1344,13 @@ static void material_transparent(
bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
*shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend);
+
+ bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
+
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth,
+ use_diffuse, use_glossy, use_refract, use_ssrefract, use_blend);
break;
}
case GPU_MAT_QUEUED:
@@ -1457,11 +1483,17 @@ static void material_particle_hair(
switch (GPU_material_status(gpumat)) {
case GPU_MAT_SUCCESS:
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
shgrp = DRW_shgroup_material_particle_hair_create(
ob, psys, md,
psl->material_pass,
gpumat);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
+
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL,
+ use_diffuse, use_glossy, use_refract, false, false);
break;
}
case GPU_MAT_QUEUED:
@@ -1555,11 +1587,17 @@ static void material_hair(
switch (GPU_material_status(gpumat)) {
case GPU_MAT_SUCCESS:
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
shgrp = DRW_shgroup_material_hair_create(
ob, hsys, scalp, draw_set,
psl->material_pass,
gpumat);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
+
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL,
+ use_diffuse, use_glossy, use_refract, false, false);
break;
}
case GPU_MAT_QUEUED:
@@ -1689,7 +1727,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
char *auto_layer_names;
int *auto_layer_is_srgb;
int auto_layer_count;
- struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len,
&auto_layer_names,
&auto_layer_is_srgb,
@@ -1820,7 +1858,7 @@ void EEVEE_materials_cache_finish(EEVEE_Data *vedata)
if (LOOK_DEV_OVERLAY_ENABLED(v3d)) {
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_LampsInfo *linfo = sldata->lamps;
- struct Gwn_Batch *sphere = DRW_cache_sphere_get();
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
static float mat1[4][4];
static float color[3] = {0.8f, 0.8f, 0.8f};
static float metallic_on = 1.0f;
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 6dabc8f91cb..08745850bd4 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -178,7 +178,7 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
EEVEE_EffectsInfo *effects = stl->effects;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
psl->motion_blur = DRW_pass_create("Motion Blur", DRW_STATE_WRITE_COLOR);
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index f39fbe33a71..8ede22cda5a 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -183,7 +183,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_EffectsInfo *effects = stl->effects;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
/** Occlusion algorithm overview
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index e2a875dca1f..bd1323dab3b 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -96,7 +96,7 @@ extern struct DrawEngineType draw_engine_eevee_type;
} ((void)0)
#define OVERLAY_ENABLED(v3d) ((v3d) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0)
-#define LOOK_DEV_MODE_ENABLED(v3d) ((v3d) && (v3d->drawtype == OB_MATERIAL))
+#define LOOK_DEV_MODE_ENABLED(v3d) ((v3d) && (v3d->shading.type == OB_MATERIAL))
#define LOOK_DEV_OVERLAY_ENABLED(v3d) (LOOK_DEV_MODE_ENABLED(v3d) && OVERLAY_ENABLED(v3d) && (v3d->overlay.flag & V3D_OVERLAY_LOOK_DEV))
#define USE_SCENE_LIGHT(v3d) ((!v3d) || (!LOOK_DEV_MODE_ENABLED(v3d)) || ((LOOK_DEV_MODE_ENABLED(v3d) && (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS))))
#define LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d) (LOOK_DEV_MODE_ENABLED(v3d) && !(v3d->shading.flag & V3D_SHADING_SCENE_WORLD))
@@ -515,6 +515,7 @@ typedef struct EEVEE_EffectsInfo {
int volume_current_sample;
/* SSR */
bool reflection_trace_full;
+ bool ssr_was_persp;
int ssr_neighbor_ofs;
int ssr_halfres_ofs[2];
struct GPUTexture *ssr_normal_input; /* Textures from pool */
@@ -773,9 +774,13 @@ typedef struct EEVEE_PrivateData {
/* Mist Settings */
float mist_start, mist_inv_dist, mist_falloff;
+
+ /* Color Management */
+ bool use_color_view_settings;
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
+void EEVEE_view_layer_data_free(void *sldata);
EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void);
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer);
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void);
@@ -815,10 +820,10 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_shcaster_add(
- EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob);
+ EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, struct GPUBatch *geom, Object *ob);
void EEVEE_lights_cache_shcaster_material_add(
EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl,
- struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob,
+ struct GPUMaterial *gpumat, struct GPUBatch *geom, struct Object *ob,
float *alpha_threshold);
void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata);
@@ -908,6 +913,7 @@ void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
void EEVEE_mist_free(void);
/* eevee_temporal_sampling.c */
+void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata);
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_matrices_calc(
EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]);
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index ef949c32eed..46229c2dc9b 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -132,6 +132,14 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
});
}
+ const bool is_persp = DRW_viewport_is_persp_get();
+ if (effects->ssr_was_persp != is_persp) {
+ effects->ssr_was_persp = is_persp;
+ DRW_viewport_request_redraw();
+ EEVEE_temporal_sampling_reset(vedata);
+ stl->g_data->valid_double_buffer = false;
+ }
+
effects->reflection_trace_full = (scene_eval->eevee.flag & SCE_EEVEE_SSR_HALF_RESOLUTION) == 0;
common_data->ssr_thickness = scene_eval->eevee.ssr_thickness;
common_data->ssr_border_fac = scene_eval->eevee.ssr_border_fade;
@@ -189,7 +197,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
EEVEE_EffectsInfo *effects = stl->effects;
LightCache *lcache = stl->g_data->light_cache;
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
if ((effects->enabled_effects & EFFECT_SSR) != 0) {
int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0;
@@ -219,6 +227,8 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
if (!effects->reflection_trace_full) {
@@ -237,6 +247,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_texture_ref(grp, "hitBuffer", &effects->ssr_hit_output);
DRW_shgroup_uniform_texture_ref(grp, "pdfBuffer", &effects->ssr_pdf_output);
DRW_shgroup_uniform_texture_ref(grp, "prevColorBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 6ee3b9cc286..9667f2ac9d7 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -204,7 +204,7 @@ void EEVEE_subsurface_add_pass(
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 7cd76669fe4..6cb2d1d3b53 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -174,6 +174,11 @@ void EEVEE_temporal_sampling_matrices_calc(
invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
}
+void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
+{
+ vedata->stl->effects->taa_render_sample = 1;
+}
+
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -294,11 +299,11 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &txl->color);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
// DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_shgroup_uniform_texture_ref(grp, "velocityBuffer", &effects->velocity_tx);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
else {
DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index d0cea65d05e..f8bb8c6f1cf 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -397,6 +397,12 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (grp) {
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ /* TODO (fclem): remove thoses (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
}
}
@@ -475,6 +481,13 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
+ /* TODO(fclem) remove thoses "unecessary" UBOs */
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", ob->imat);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 8b232bf14a4..286f00783d9 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -548,6 +548,14 @@ float F_eta(float eta, float cos_theta)
return result;
}
+/* Fresnel color blend base on fresnel factor */
+vec3 F_color_blend(float eta, float fresnel, vec3 f0_color)
+{
+ float f0 = F_eta(eta, 1.0);
+ float fac = saturate((fresnel - f0) / max(1e-8, 1.0 - f0));
+ return mix(f0_color, vec3(1.0), fac);
+}
+
/* Fresnel */
vec3 F_schlick(vec3 f0, float cos_theta)
{
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index ec5f6f4472f..7281eb4cf2d 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -318,6 +318,8 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
#define SSS_LUT_SIZE 64.0
#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE))
#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE))
+
+#ifdef USE_TRANSLUCENCY
layout(std140) uniform sssProfile {
vec4 kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
@@ -330,6 +332,7 @@ vec3 sss_profile(float s) {
s /= radii_max_radius.w;
return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
}
+#endif
vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
{
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 22194c22f39..c31fa166634 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -54,6 +54,13 @@ uniform int hairThicknessRes = 1;
#define CLOSURE_SUBSURFACE
#endif /* SURFACE_PRINCIPLED */
+#if !defined(SURFACE_CLEARCOAT) && !defined(CLOSURE_NAME)
+ #define SURFACE_CLEARCOAT
+ #define CLOSURE_NAME eevee_closure_clearcoat
+ #define CLOSURE_GLOSSY
+ #define CLOSURE_CLEARCOAT
+#endif /* SURFACE_CLEARCOAT */
+
#if !defined(SURFACE_DIFFUSE) && !defined(CLOSURE_NAME)
#define SURFACE_DIFFUSE
#define CLOSURE_NAME eevee_closure_diffuse
@@ -67,6 +74,14 @@ uniform int hairThicknessRes = 1;
#define CLOSURE_SUBSURFACE
#endif /* SURFACE_SUBSURFACE */
+#if !defined(SURFACE_SKIN) && !defined(CLOSURE_NAME)
+ #define SURFACE_SKIN
+ #define CLOSURE_NAME eevee_closure_skin
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_SUBSURFACE
+ #define CLOSURE_GLOSSY
+#endif /* SURFACE_SKIN */
+
#if !defined(SURFACE_GLOSSY) && !defined(CLOSURE_NAME)
#define SURFACE_GLOSSY
#define CLOSURE_NAME eevee_closure_glossy
@@ -215,7 +230,7 @@ void CLOSURE_NAME(
#endif
#ifdef CLOSURE_CLEARCOAT
- out_spec_clear += l_color_vis * light_specular(ld, ltc_mat_clear, C_N, V, l_vector) * C_intensity * ld.l_spec;
+ out_spec_clear += l_color_vis * light_specular(ld, ltc_mat_clear, C_N, V, l_vector) * ld.l_spec;
#endif
}
@@ -226,8 +241,8 @@ void CLOSURE_NAME(
#ifdef CLOSURE_CLEARCOAT
vec3 brdf_lut_lamps_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).rgb;
- out_spec_clear *= F_area(f0, brdf_lut_lamps_clear.xy) * brdf_lut_lamps_clear.z;
- out_spec += out_spec_clear;
+ out_spec_clear *= F_area(vec3(0.04), brdf_lut_lamps_clear.xy) * brdf_lut_lamps_clear.z;
+ out_spec += out_spec_clear * C_intensity;
#endif
/* ---------------------------------------------------------------- */
@@ -417,7 +432,7 @@ void CLOSURE_NAME(
NV = dot(C_N, V);
vec2 C_uv = lut_coords(NV, C_roughness);
vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg;
- vec3 C_fresnel = F_ibl(vec3(0.04), brdf_lut) * specular_occlusion(NV, final_ao, C_roughness);
+ vec3 C_fresnel = F_ibl(vec3(0.04), C_brdf_lut) * specular_occlusion(NV, final_ao, C_roughness);
out_spec += C_spec_accum.rgb * C_fresnel * C_intensity;
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
index f2e9e7001e8..e110937c5aa 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
@@ -2,10 +2,12 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelMatrix;
+#ifdef CLIP_PLANES
/* keep in sync with DRWManager.view_data */
layout(std140) uniform clip_block {
vec4 ClipPlanes[1];
};
+#endif
#ifndef HAIR_SHADER
in vec3 pos;
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 2917805d233..b2c30ba723c 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -128,7 +128,7 @@ static void external_cache_populate(void *vedata, Object *ob)
if (!DRW_object_is_renderable(ob))
return;
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
/* Depth Prepass */
DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
@@ -165,14 +165,14 @@ static void external_draw_scene_do(void *vedata)
}
/* Rendered draw. */
- gpuPushProjectionMatrix();
+ GPU_matrix_push_projection();
ED_region_pixelspace(ar);
/* Render result draw. */
type = rv3d->render_engine->type;
type->view_draw(rv3d->render_engine, draw_ctx->evil_C);
- gpuPopProjectionMatrix();
+ GPU_matrix_pop_projection();
/* Set render info. */
EXTERNAL_Data *data = vedata;
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
new file mode 100644
index 00000000000..e8bb27b2724
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_cache_utils.c
+ * \ingroup draw
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_global.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_view3d_types.h"
+
+#include "gpencil_engine.h"
+
+#include "draw_cache_impl.h"
+
+ /* add a gpencil object to cache to defer drawing */
+tGPencilObjectCache *gpencil_object_cache_add(
+ tGPencilObjectCache *cache_array, Object *ob, bool is_temp,
+ int *gp_cache_size, int *gp_cache_used)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ tGPencilObjectCache *cache_elem = NULL;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ tGPencilObjectCache *p = NULL;
+
+ /* By default a cache is created with one block with a predefined number of free slots,
+ if the size is not enough, the cache is reallocated adding a new block of free slots.
+ This is done in order to keep cache small */
+ if (*gp_cache_used + 1 > *gp_cache_size) {
+ if ((*gp_cache_size == 0) || (cache_array == NULL)) {
+ p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, "tGPencilObjectCache");
+ *gp_cache_size = GP_CACHE_BLOCK_SIZE;
+ }
+ else {
+ *gp_cache_size += GP_CACHE_BLOCK_SIZE;
+ p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
+ }
+ cache_array = p;
+ }
+
+ /* zero out all pointers */
+ cache_elem = &cache_array[*gp_cache_used];
+ memset(cache_elem, 0, sizeof(*cache_elem));
+
+ /* save object */
+ cache_elem->ob = ob;
+ cache_elem->temp_ob = is_temp;
+ cache_elem->idx = *gp_cache_used;
+
+ cache_elem->init_grp = 0;
+ cache_elem->end_grp = -1;
+
+ /* calculate zdepth from point of view */
+ float zdepth = 0.0;
+ if (rv3d) {
+ if (rv3d->is_persp) {
+ zdepth = ED_view3d_calc_zfac(rv3d, ob->loc, NULL);
+ }
+ else {
+ zdepth = -dot_v3v3(rv3d->viewinv[2], ob->loc);
+ }
+ }
+ else {
+ /* In render mode, rv3d is not available, so use the distance to camera.
+ * The real distance is not important, but the relative distance to the camera plane
+ * in order to sort by z_depth of the objects
+ */
+ float vn[3] = { 0.0f, 0.0f, -1.0f }; /* always face down */
+ float plane_cam[4];
+ struct Object *camera = draw_ctx->scene->camera;
+ if (camera) {
+ mul_m4_v3(camera->obmat, vn);
+ normalize_v3(vn);
+ plane_from_point_normal_v3(plane_cam, camera->loc, vn);
+ zdepth = dist_squared_to_plane_v3(ob->loc, plane_cam);
+ }
+ }
+ cache_elem->zdepth = zdepth;
+ /* increase slots used in cache */
+ (*gp_cache_used)++;
+
+ return cache_array;
+}
+
+/* get current cache data */
+static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
+{
+ bGPdata *gpd = ob->data;
+ if (gpd->runtime.batch_cache_data == NULL) {
+ gpd->runtime.batch_cache_data = BLI_ghash_str_new("GP batch cache data");
+ return NULL;
+ }
+
+ return (GpencilBatchCache *) BLI_ghash_lookup(gpd->runtime.batch_cache_data, ob->id.name);
+}
+
+/* verify if cache is valid */
+static bool gpencil_batch_cache_valid(Object *ob, bGPdata *gpd, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_get_element(ob);
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
+
+ if (cfra != cache->cache_frame) {
+ return false;
+ }
+
+ if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
+ return false;
+ }
+
+ if (cache->is_editmode) {
+ return false;
+ }
+
+ if (cache->is_dirty) {
+ return false;
+ }
+
+ return true;
+}
+
+/* resize the cache to the number of slots */
+static void gpencil_batch_cache_resize(GpencilBatchCache *cache, int slots)
+{
+ cache->cache_size = slots;
+ cache->batch_stroke = MEM_recallocN(cache->batch_stroke, sizeof(struct Gwn_Batch *) * slots);
+ cache->batch_fill = MEM_recallocN(cache->batch_fill, sizeof(struct Gwn_Batch *) * slots);
+ cache->batch_edit = MEM_recallocN(cache->batch_edit, sizeof(struct Gwn_Batch *) * slots);
+ cache->batch_edlin = MEM_recallocN(cache->batch_edlin, sizeof(struct Gwn_Batch *) * slots);
+}
+
+/* check size and increase if no free slots */
+void gpencil_batch_cache_check_free_slots(Object *ob)
+{
+ GpencilBatchCache *cache = gpencil_batch_get_element(ob);
+
+ /* the memory is reallocated by chunks, not for one slot only to improve speed */
+ if (cache->cache_idx >= cache->cache_size) {
+ cache->cache_size += GPENCIL_MIN_BATCH_SLOTS_CHUNK;
+ gpencil_batch_cache_resize(cache, cache->cache_size);
+ }
+}
+
+/* cache init */
+static void gpencil_batch_cache_init(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_get_element(ob);
+ bGPdata *gpd = ob->data;
+
+ if (G.debug_value >= 664) {
+ printf("gpencil_batch_cache_init: %s\n", ob->id.name);
+ }
+
+ if (!cache) {
+ cache = MEM_callocN(sizeof(*cache), __func__);
+ BLI_ghash_insert(gpd->runtime.batch_cache_data, ob->id.name, cache);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->cache_size = GPENCIL_MIN_BATCH_SLOTS_CHUNK;
+ cache->batch_stroke = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Stroke");
+ cache->batch_fill = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Fill");
+ cache->batch_edit = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Edit");
+ cache->batch_edlin = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Edlin");
+
+ cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
+ gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+
+ cache->cache_idx = 0;
+ cache->is_dirty = true;
+ cache->cache_frame = cfra;
+}
+
+/* clear cache */
+static void gpencil_batch_cache_clear(GpencilBatchCache *cache, bGPdata *gpd)
+{
+ if (!cache) {
+ return;
+ }
+
+ if (cache->cache_size == 0) {
+ return;
+ }
+
+ if (G.debug_value >= 664) {
+ printf("gpencil_batch_cache_clear: %s\n", gpd->id.name);
+ }
+
+ if (cache->cache_size > 0) {
+ for (int i = 0; i < cache->cache_size; i++) {
+ GPU_BATCH_DISCARD_SAFE(cache->batch_stroke[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->batch_fill[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->batch_edit[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->batch_edlin[i]);
+ }
+ MEM_SAFE_FREE(cache->batch_stroke);
+ MEM_SAFE_FREE(cache->batch_fill);
+ MEM_SAFE_FREE(cache->batch_edit);
+ MEM_SAFE_FREE(cache->batch_edlin);
+ }
+
+ MEM_SAFE_FREE(cache);
+}
+
+/* get cache */
+GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
+{
+ bGPdata *gpd = ob->data;
+
+ if (!gpencil_batch_cache_valid(ob, gpd, cfra)) {
+ if (G.debug_value >= 664) {
+ printf("gpencil_batch_cache: %s\n", gpd->id.name);
+ }
+
+ GpencilBatchCache *cache = gpencil_batch_get_element(ob);
+ if (cache) {
+ gpencil_batch_cache_clear(cache, gpd);
+ BLI_ghash_remove(gpd->runtime.batch_cache_data, ob->id.name, NULL, NULL);
+ }
+ gpencil_batch_cache_init(ob, cfra);
+ }
+
+ return gpencil_batch_get_element(ob);
+}
+
+/* set cache as dirty */
+void DRW_gpencil_batch_cache_dirty(bGPdata *gpd)
+{
+ if (gpd->runtime.batch_cache_data == NULL) {
+ return;
+ }
+
+ GHashIterator *ihash = BLI_ghashIterator_new(gpd->runtime.batch_cache_data);
+ while (!BLI_ghashIterator_done(ihash)) {
+ GpencilBatchCache *cache = (GpencilBatchCache *)BLI_ghashIterator_getValue(ihash);
+ if (cache) {
+ cache->is_dirty = true;
+ }
+ BLI_ghashIterator_step(ihash);
+ }
+ BLI_ghashIterator_free(ihash);
+}
+
+/* free batch cache */
+void DRW_gpencil_batch_cache_free(bGPdata *gpd)
+{
+ if (gpd->runtime.batch_cache_data == NULL) {
+ return;
+ }
+
+ GHashIterator *ihash = BLI_ghashIterator_new(gpd->runtime.batch_cache_data);
+ while (!BLI_ghashIterator_done(ihash)) {
+ GpencilBatchCache *cache = (GpencilBatchCache *)BLI_ghashIterator_getValue(ihash);
+ if (cache) {
+ gpencil_batch_cache_clear(cache, gpd);
+ }
+ BLI_ghashIterator_step(ihash);
+ }
+ BLI_ghashIterator_free(ihash);
+
+ /* free hash */
+ if (gpd->runtime.batch_cache_data) {
+ BLI_ghash_free(gpd->runtime.batch_cache_data, NULL, NULL);
+ gpd->runtime.batch_cache_data = NULL;
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
new file mode 100644
index 00000000000..83a52e077ca
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -0,0 +1,751 @@
+/*
+ * ***** 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) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw/engines/gpencil/gpencil_draw_cache_impl.c
+ * \ingroup draw
+ */
+
+#include "BLI_polyfill_2d.h"
+#include "BLI_math_color.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_action.h"
+
+#include "DRW_render.h"
+
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+
+#include "gpencil_engine.h"
+
+/* Helper to add stroke point to vbo */
+static void gpencil_set_stroke_point(
+ GPUVertBuf *vbo, float matrix[4][4], const bGPDspoint *pt, int idx,
+ uint pos_id, uint color_id,
+ uint thickness_id, uint uvdata_id, short thickness,
+ const float ink[4])
+{
+ float viewfpt[3];
+
+ float alpha = ink[3] * pt->strength;
+ CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+ float col[4];
+ ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
+
+ GPU_vertbuf_attr_set(vbo, color_id, idx, col);
+
+ /* transfer both values using the same shader variable */
+ float uvdata[2] = { pt->uv_fac, pt->uv_rot };
+ GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
+
+ /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */
+ mul_v3_m4v3(viewfpt, matrix, &pt->x);
+ float thick = max_ff(pt->pressure * thickness, 1.0f);
+ GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick);
+
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
+}
+
+/* Helper to add a new fill point and texture coordinates to vertex buffer */
+static void gpencil_set_fill_point(
+ GPUVertBuf *vbo, int idx, bGPDspoint *pt, const float fcolor[4], float uv[2],
+ uint pos_id, uint color_id, uint text_id)
+{
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
+ GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
+ GPU_vertbuf_attr_set(vbo, text_id, idx, uv);
+}
+
+/* create batch geometry data for points stroke shader */
+GPUBatch *DRW_gpencil_get_point_geom(bGPDstroke *gps, short thickness, const float ink[4])
+{
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, size_id, uvdata_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ size_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+
+ /* draw stroke curve */
+ const bGPDspoint *pt = gps->points;
+ int idx = 0;
+ float alpha;
+ float col[4];
+
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
+ /* set point */
+ alpha = ink[3] * pt->strength;
+ CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+ ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
+
+ float thick = max_ff(pt->pressure * thickness, 1.0f);
+
+ GPU_vertbuf_attr_set(vbo, color_id, idx, col);
+ GPU_vertbuf_attr_set(vbo, size_id, idx, &thick);
+
+ /* transfer both values using the same shader variable */
+ float uvdata[2] = { pt->uv_fac, pt->uv_rot };
+ GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
+
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
+ idx++;
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* create batch geometry data for stroke shader */
+GPUBatch *DRW_gpencil_get_stroke_geom(bGPDframe *gpf, bGPDstroke *gps, short thickness, const float ink[4])
+{
+ bGPDspoint *points = gps->points;
+ int totpoints = gps->totpoints;
+ /* if cyclic needs more vertex */
+ int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0;
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, thickness_id, uvdata_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, totpoints + cyclic_add + 2);
+
+ /* draw stroke curve */
+ const bGPDspoint *pt = points;
+ int idx = 0;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* first point for adjacency (not drawn) */
+ if (i == 0) {
+ if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, &points[totpoints - 1], idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ idx++;
+ }
+ else {
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, &points[1], idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ idx++;
+ }
+ }
+ /* set point */
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, pt, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ idx++;
+ }
+
+ if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
+ /* draw line to first point to complete the cycle */
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, &points[0], idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ idx++;
+ /* now add adjacency point (not drawn) */
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, &points[1], idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ idx++;
+ }
+ /* last adjacency point (not drawn) */
+ else {
+ gpencil_set_stroke_point(
+ vbo, gpf->runtime.viewmatrix, &points[totpoints - 2], idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* create batch geometry data for current buffer stroke shader */
+GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, float matrix[4][4], short thickness)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ ARegion *ar = draw_ctx->ar;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ ToolSettings *ts = scene->toolsettings;
+ Object *ob = draw_ctx->obact;
+
+ tGPspoint *points = gpd->runtime.sbuffer;
+ int totpoints = gpd->runtime.sbuffer_size;
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, thickness_id, uvdata_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, totpoints + 2);
+
+ /* draw stroke curve */
+ const tGPspoint *tpt = points;
+ bGPDspoint pt, pt2;
+ int idx = 0;
+
+ /* get origin to reproject point */
+ float origin[3];
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+
+ for (int i = 0; i < totpoints; i++, tpt++) {
+ ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
+ ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
+
+ /* first point for adjacency (not drawn) */
+ if (i == 0) {
+ if (totpoints > 1) {
+ ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2);
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ }
+ else {
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ }
+ idx++;
+ }
+ /* set point */
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
+ }
+
+ /* last adjacency point (not drawn) */
+ if (totpoints > 2) {
+ ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2);
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ }
+ else {
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* create batch geometry data for current buffer point shader */
+GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, float matrix[4][4], short thickness)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ ARegion *ar = draw_ctx->ar;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ ToolSettings *ts = scene->toolsettings;
+ Object *ob = draw_ctx->obact;
+
+ tGPspoint *points = gpd->runtime.sbuffer;
+ int totpoints = gpd->runtime.sbuffer_size;
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, thickness_id, uvdata_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, totpoints);
+
+ /* draw stroke curve */
+ const tGPspoint *tpt = points;
+ bGPDspoint pt;
+ int idx = 0;
+
+ /* get origin to reproject point */
+ float origin[3];
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+
+ for (int i = 0; i < totpoints; i++, tpt++) {
+ ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
+ ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
+
+ /* set point */
+ gpencil_set_stroke_point(
+ vbo, matrix, &pt, idx,
+ pos_id, color_id, thickness_id, uvdata_id,
+ thickness, gpd->runtime.scolor);
+ idx++;
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* create batch geometry data for current buffer fill shader */
+GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
+{
+ if (gpd == NULL) {
+ return NULL;
+ }
+
+ const tGPspoint *points = gpd->runtime.sbuffer;
+ int totpoints = gpd->runtime.sbuffer_size;
+ if (totpoints < 3) {
+ return NULL;
+ }
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ ARegion *ar = draw_ctx->ar;
+ ToolSettings *ts = scene->toolsettings;
+ Object *ob = draw_ctx->obact;
+
+ /* get origin to reproject point */
+ float origin[3];
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+
+ int tot_triangles = totpoints - 2;
+ /* allocate memory for temporary areas */
+ uint (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, __func__);
+ float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__);
+
+ /* Convert points to array and triangulate
+ * Here a cache is not used because while drawing the information changes all the time, so the cache
+ * would be recalculated constantly, so it is better to do direct calculation for each function call
+ */
+ for (int i = 0; i < totpoints; i++) {
+ const tGPspoint *pt = &points[i];
+ points2d[i][0] = pt->x;
+ points2d[i][1] = pt->y;
+ }
+ BLI_polyfill_calc(points2d, (uint)totpoints, 0, tmp_triangles);
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+
+ /* draw triangulation data */
+ if (tot_triangles > 0) {
+ GPU_vertbuf_data_alloc(vbo, tot_triangles * 3);
+
+ const tGPspoint *tpt;
+ bGPDspoint pt;
+
+ int idx = 0;
+ for (int i = 0; i < tot_triangles; i++) {
+ for (int j = 0; j < 3; j++) {
+ tpt = &points[tmp_triangles[i][j]];
+ ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt.x);
+ GPU_vertbuf_attr_set(vbo, color_id, idx, gpd->runtime.sfill);
+ idx++;
+ }
+ }
+ }
+
+ /* clear memory */
+ if (tmp_triangles) {
+ MEM_freeN(tmp_triangles);
+ }
+ if (points2d) {
+ MEM_freeN(points2d);
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* create batch geometry data for stroke shader */
+GPUBatch *DRW_gpencil_get_fill_geom(Object *ob, bGPDstroke *gps, const float color[4])
+{
+ BLI_assert(gps->totpoints >= 3);
+
+ /* Calculate triangles cache for filling area (must be done only after changes) */
+ if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
+ DRW_gpencil_triangulate_stroke_fill(gps);
+ ED_gpencil_calc_stroke_uv(ob, gps);
+ }
+
+ BLI_assert(gps->tot_triangles >= 1);
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, text_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ text_id = GPU_vertformat_attr_add(&format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, gps->tot_triangles * 3);
+
+ /* Draw all triangles for filling the polygon (cache must be calculated before) */
+ bGPDtriangle *stroke_triangle = gps->triangles;
+ int idx = 0;
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
+ for (int j = 0; j < 3; j++) {
+ gpencil_set_fill_point(
+ vbo, idx, &gps->points[stroke_triangle->verts[j]], color, stroke_triangle->uv[j],
+ pos_id, color_id, text_id);
+ idx++;
+ }
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* Draw selected verts for strokes being edited */
+GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob->data;
+ bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+
+ int vgindex = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, vgindex)) {
+ vgindex = -1;
+ }
+
+ /* Get size of verts:
+ * - The selected state needs to be larger than the unselected state so that
+ * they stand out more.
+ * - We use the theme setting for size of the unselected verts
+ */
+ float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float vsize;
+ if ((int)bsize > 8) {
+ vsize = 10.0f;
+ bsize = 8.0f;
+ }
+ else {
+ vsize = bsize + 2;
+ }
+
+ /* for now, we assume that the base color of the points is not too close to the real color */
+ float selectColor[4];
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+ selectColor[3] = alpha;
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, size_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+
+ /* Draw start and end point differently if enabled stroke direction hint */
+ bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
+
+ /* Draw all the stroke points (selected or not) */
+ bGPDspoint *pt = gps->points;
+ MDeformVert *dvert = gps->dvert;
+
+ int idx = 0;
+ float fcolor[4];
+ float fsize = 0;
+ for (int i = 0; i < gps->totpoints; i++, pt++, dvert++) {
+ /* weight paint */
+ if (is_weight_paint) {
+ float weight = BKE_gpencil_vgroup_use_index(dvert, vgindex);
+ CLAMP(weight, 0.0f, 1.0f);
+ float hue = 2.0f * (1.0f - weight) / 3.0f;
+ hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
+ selectColor[3] = 1.0f;
+ copy_v4_v4(fcolor, selectColor);
+ fsize = vsize;
+ }
+ else {
+ if (show_direction_hint && i == 0) {
+ /* start point in green bigger */
+ ARRAY_SET_ITEMS(fcolor, 0.0f, 1.0f, 0.0f, 1.0f);
+ fsize = vsize + 4;
+ }
+ else if (show_direction_hint && (i == gps->totpoints - 1)) {
+ /* end point in red smaller */
+ ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f);
+ fsize = vsize + 1;
+ }
+ else if (pt->flag & GP_SPOINT_SELECT) {
+ copy_v4_v4(fcolor, selectColor);
+ fsize = vsize;
+ }
+ else {
+ copy_v4_v4(fcolor, gps->runtime.tmp_stroke_rgba);
+ fsize = bsize;
+ }
+ }
+
+ GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
+ GPU_vertbuf_attr_set(vbo, size_id, idx, &fsize);
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
+ idx++;
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+/* Draw lines for strokes being edited */
+GPUBatch *DRW_gpencil_get_edlin_geom(bGPDstroke *gps, float alpha, short UNUSED(dflag))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob->data;
+ bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+
+ int vgindex = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, vgindex)) {
+ vgindex = -1;
+ }
+
+ float selectColor[4];
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+ selectColor[3] = alpha;
+ float linecolor[4];
+ copy_v4_v4(linecolor, gpd->line_color);
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+
+ /* Draw all the stroke lines (selected or not) */
+ bGPDspoint *pt = gps->points;
+
+ /* GPXX: for some converted files, this struct could be null
+ * maybe we can remove this and move to versioning code after
+ * merge */
+ if (gps->dvert == NULL) {
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
+ }
+
+ MDeformVert *dvert = gps->dvert;
+
+ int idx = 0;
+ float fcolor[4];
+ for (int i = 0; i < gps->totpoints; i++, pt++, dvert++) {
+ /* weight paint */
+ if (is_weight_paint) {
+ float weight = BKE_gpencil_vgroup_use_index(dvert, vgindex);
+ CLAMP(weight, 0.0f, 1.0f);
+ float hue = 2.0f * (1.0f - weight) / 3.0f;
+ hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
+ selectColor[3] = 1.0f;
+ copy_v4_v4(fcolor, selectColor);
+ }
+ else {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ copy_v4_v4(fcolor, selectColor);
+ }
+ else {
+ copy_v4_v4(fcolor, linecolor);
+ }
+ }
+
+ GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
+ idx++;
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+static void set_grid_point(
+ GPUVertBuf *vbo, int idx, float col_grid[4],
+ uint pos_id, uint color_id,
+ float v1, float v2, int axis)
+{
+ GPU_vertbuf_attr_set(vbo, color_id, idx, col_grid);
+
+ float pos[3];
+ /* Set the grid in the selected axis (default is always Y axis) */
+ if (axis & V3D_GP_GRID_AXIS_X) {
+ pos[0] = 0.0f;
+ pos[1] = v1;
+ pos[2] = v2;
+ }
+ else if (axis & V3D_GP_GRID_AXIS_Z) {
+ pos[0] = v1;
+ pos[1] = v2;
+ pos[2] = 0.0f;
+ }
+ else {
+ pos[0] = v1;
+ pos[1] = 0.0f;
+ pos[2] = v2;
+ }
+
+
+
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, pos);
+}
+
+/* Draw grid lines */
+GPUBatch *DRW_gpencil_get_grid(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+ View3D *v3d = draw_ctx->v3d;
+
+ float col_grid[4];
+
+ /* verify we have something to draw and valid values */
+ if (v3d->overlay.gpencil_grid_lines < 1) {
+ v3d->overlay.gpencil_grid_lines = GP_DEFAULT_GRID_LINES;
+ }
+
+ if (v3d->overlay.gpencil_grid_scale == 0.0f) {
+ v3d->overlay.gpencil_grid_scale = 1.0f;
+ }
+
+ if (v3d->overlay.gpencil_grid_opacity < 0.1f) {
+ v3d->overlay.gpencil_grid_opacity = 0.1f;
+ }
+
+ UI_GetThemeColor3fv(TH_GRID, col_grid);
+ col_grid[3] = v3d->overlay.gpencil_grid_opacity;
+
+ /* if use locked axis, copy value */
+ int axis = v3d->overlay.gpencil_grid_axis;
+ if ((v3d->overlay.gpencil_grid_axis & V3D_GP_GRID_AXIS_LOCK) == 0) {
+
+ axis = v3d->overlay.gpencil_grid_axis;
+ }
+ else {
+ switch (ts->gp_sculpt.lock_axis) {
+ case GP_LOCKAXIS_X:
+ {
+ axis = V3D_GP_GRID_AXIS_X;
+ break;
+ }
+ case GP_LOCKAXIS_NONE:
+ case GP_LOCKAXIS_Y:
+ {
+ axis = V3D_GP_GRID_AXIS_Y;
+ break;
+ }
+ case GP_LOCKAXIS_Z:
+ {
+ axis = V3D_GP_GRID_AXIS_Z;
+ break;
+ }
+ }
+ }
+
+ const char *grid_unit = NULL;
+ const int gridlines = v3d->overlay.gpencil_grid_lines;
+ const float grid_scale = v3d->overlay.gpencil_grid_scale * ED_scene_grid_scale(scene, &grid_unit);
+ const float grid = grid_scale;
+ const float space = (grid_scale / gridlines);
+
+ const uint vertex_len = 2 * (gridlines * 4 + 2);
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vertex_len);
+
+ int idx = 0;
+
+ for (int a = 1; a <= gridlines; a++) {
+ const float line = a * space;
+
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, -line, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, -line, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, +line, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, +line, axis);
+ idx++;
+
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line, -grid, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line, +grid, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line, -grid, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line, +grid, axis);
+ idx++;
+ }
+ /* center lines */
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid, 0.0f, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid, 0.0f, axis);
+ idx++;
+
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, -grid, axis);
+ idx++;
+ set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, +grid, axis);
+ idx++;
+
+ return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
new file mode 100644
index 00000000000..401934b35a7
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -0,0 +1,1384 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_draw_utils.c
+ * \ingroup draw
+ */
+
+#include "BLI_polyfill_2d.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BKE_brush.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_image.h"
+#include "BKE_material.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+ /* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+/* For EvaluationContext... */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "gpencil_engine.h"
+
+/* fill type to communicate to shader */
+#define SOLID 0
+#define GRADIENT 1
+#define RADIAL 2
+#define CHESS 3
+#define TEXTURE 4
+#define PATTERN 5
+
+/* Helper for doing all the checks on whether a stroke can be drawn */
+static bool gpencil_can_draw_stroke(
+ struct MaterialGPencilStyle *gp_style, const bGPDstroke *gps,
+ const bool onion, const bool is_mat_preview)
+{
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL))
+ return false;
+
+ /* if mat preview render always visible */
+ if (is_mat_preview) {
+ return true;
+ }
+
+ /* check if the color is visible */
+ if ((gp_style == NULL) ||
+ (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN)))
+ {
+ return false;
+ }
+
+ /* stroke can be drawn */
+ return true;
+}
+
+/* calc bounding box in 2d using flat projection data */
+static void gpencil_calc_2d_bounding_box(
+ const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], bool expand)
+{
+ minv[0] = points2d[0][0];
+ minv[1] = points2d[0][1];
+ maxv[0] = points2d[0][0];
+ maxv[1] = points2d[0][1];
+
+ for (int i = 1; i < totpoints; i++) {
+ /* min */
+ if (points2d[i][0] < minv[0]) {
+ minv[0] = points2d[i][0];
+ }
+ if (points2d[i][1] < minv[1]) {
+ minv[1] = points2d[i][1];
+ }
+ /* max */
+ if (points2d[i][0] > maxv[0]) {
+ maxv[0] = points2d[i][0];
+ }
+ if (points2d[i][1] > maxv[1]) {
+ maxv[1] = points2d[i][1];
+ }
+ }
+ /* If not expanded, use a perfect square */
+ if (expand == false) {
+ if (maxv[0] > maxv[1]) {
+ maxv[1] = maxv[0];
+ }
+ else {
+ maxv[0] = maxv[1];
+ }
+ }
+}
+
+/* calc texture coordinates using flat projected points */
+static void gpencil_calc_stroke_fill_uv(
+ const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], float(*r_uv)[2])
+{
+ float d[2];
+ d[0] = maxv[0] - minv[0];
+ d[1] = maxv[1] - minv[1];
+ for (int i = 0; i < totpoints; i++) {
+ r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
+ r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
+ }
+}
+
+/* Get points of stroke always flat to view not affected by camera view or view position */
+static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
+{
+ const bGPDspoint *pt0 = &points[0];
+ const bGPDspoint *pt1 = &points[1];
+ const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
+ float locx[3];
+ float locy[3];
+ float loc3[3];
+ float normal[3];
+
+ /* local X axis (p0 -> p1) */
+ sub_v3_v3v3(locx, &pt1->x, &pt0->x);
+
+ /* point vector at 3/4 */
+ sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
+
+ /* vector orthogonal to polygon plane */
+ cross_v3_v3v3(normal, locx, loc3);
+
+ /* local Y axis (cross to normal/x axis) */
+ cross_v3_v3v3(locy, normal, locx);
+
+ /* Normalize vectors */
+ normalize_v3(locx);
+ normalize_v3(locy);
+
+ /* Get all points in local space */
+ for (int i = 0; i < totpoints; i++) {
+ const bGPDspoint *pt = &points[i];
+ float loc[3];
+
+ /* Get local space using first point as origin */
+ sub_v3_v3v3(loc, &pt->x, &pt0->x);
+
+ points2d[i][0] = dot_v3v3(loc, locx);
+ points2d[i][1] = dot_v3v3(loc, locy);
+ }
+
+ /* Concave (-1), Convex (1), or Autodetect (0)? */
+ *r_direction = (int)locy[2];
+}
+
+/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
+void DRW_gpencil_triangulate_stroke_fill(bGPDstroke *gps)
+{
+ BLI_assert(gps->totpoints >= 3);
+
+ /* allocate memory for temporary areas */
+ gps->tot_triangles = gps->totpoints - 2;
+ uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
+ float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
+
+ int direction = 0;
+
+ /* convert to 2d and triangulate */
+ gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
+ BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
+
+ /* calc texture coordinates automatically */
+ float minv[2];
+ float maxv[2];
+ /* first needs bounding box data */
+ gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv, false);
+ /* calc uv data */
+ gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
+
+ /* Number of triangles */
+ gps->tot_triangles = gps->totpoints - 2;
+ /* save triangulation data in stroke cache */
+ if (gps->tot_triangles > 0) {
+ if (gps->triangles == NULL) {
+ gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation");
+ }
+ else {
+ gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
+ }
+
+ for (int i = 0; i < gps->tot_triangles; i++) {
+ bGPDtriangle *stroke_triangle = &gps->triangles[i];
+ memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
+ /* copy texture coordinates */
+ copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
+ copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
+ copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
+ }
+ }
+ else {
+ /* No triangles needed - Free anything allocated previously */
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+
+ gps->triangles = NULL;
+ }
+
+ /* disable recalculation flag */
+ if (gps->flag & GP_STROKE_RECALC_CACHES) {
+ gps->flag &= ~GP_STROKE_RECALC_CACHES;
+ }
+
+ /* clear memory */
+ MEM_SAFE_FREE(tmp_triangles);
+ MEM_SAFE_FREE(points2d);
+ MEM_SAFE_FREE(uv);
+}
+
+/* recalc the internal geometry caches for fill and uvs */
+static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
+{
+ if (gps->flag & GP_STROKE_RECALC_CACHES) {
+ /* Calculate triangles cache for filling area (must be done only after changes) */
+ if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
+ if ((gps->totpoints > 2) &&
+ ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)))
+ {
+ DRW_gpencil_triangulate_stroke_fill(gps);
+ }
+ }
+
+ /* calc uv data along the stroke */
+ ED_gpencil_calc_stroke_uv(ob, gps);
+
+ /* clear flag */
+ gps->flag &= ~GP_STROKE_RECALC_CACHES;
+ }
+}
+
+/* create shading group for filling */
+static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(
+ GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass,
+ GPUShader *shader, bGPdata *gpd, MaterialGPencilStyle *gp_style, int id)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
+ /* e_data.gpencil_fill_sh */
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1);
+
+ /* set style type */
+ switch (gp_style->fill_style) {
+ case GP_STYLE_FILL_STYLE_SOLID:
+ stl->shgroups[id].fill_style = SOLID;
+ break;
+ case GP_STYLE_FILL_STYLE_GRADIENT:
+ if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) {
+ stl->shgroups[id].fill_style = GRADIENT;
+ }
+ else {
+ stl->shgroups[id].fill_style = RADIAL;
+ }
+ break;
+ case GP_STYLE_FILL_STYLE_CHESSBOARD:
+ stl->shgroups[id].fill_style = CHESS;
+ break;
+ case GP_STYLE_FILL_STYLE_TEXTURE:
+ if (gp_style->flag & GP_STYLE_FILL_PATTERN) {
+ stl->shgroups[id].fill_style = PATTERN;
+ }
+ else {
+ stl->shgroups[id].fill_style = TEXTURE;
+ }
+ break;
+ default:
+ stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID;
+ break;
+ }
+ DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1);
+
+ DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1);
+
+ DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1);
+ DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1);
+ DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1);
+ DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1);
+ DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1);
+
+ DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1);
+ DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1);
+ DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1);
+ DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1);
+
+ stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0;
+ DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1);
+
+ stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0;
+ DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1);
+
+ DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
+ /* image texture */
+ if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) ||
+ (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE))
+ {
+ ImBuf *ibuf;
+ Image *image = gp_style->ima;
+ ImageUser iuser = { NULL };
+ void *lock;
+
+ iuser.ok = true;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ else {
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true, 0.0);
+ DRW_shgroup_uniform_texture(grp, "myTexture", texture);
+
+ stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
+ DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ else {
+ /* if no texture defined, need a blank texture to avoid errors in draw manager */
+ DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
+ stl->shgroups[id].texture_clamp = 0;
+ DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
+ }
+
+ return grp;
+}
+
+/* create shading group for strokes */
+DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
+ GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
+ bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* e_data.gpencil_stroke_sh */
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
+
+ DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(grp, "pixelsize", &U.pixelsize, 1);
+
+ /* avoid wrong values */
+ if ((gpd) && (gpd->pixfactor == 0)) {
+ gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ }
+
+ /* object scale and depth */
+ if ((ob) && (id > -1)) {
+ stl->shgroups[id].obj_scale = (ob->size[0] + ob->size[1] + ob->size[2]) / 3.0f;
+ DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
+ stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
+ DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
+
+ stl->shgroups[id].stroke_style = gp_style->stroke_style;
+ stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
+ if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
+ stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
+ if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
+ stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
+ }
+ }
+ DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
+ DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
+ }
+ else {
+ stl->storage->obj_scale = 1.0f;
+ stl->storage->keep_size = 0;
+ stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
+ DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
+ DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
+ if (gpd) {
+ DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
+ }
+ else {
+ DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
+ }
+ }
+
+ if ((gpd) && (id > -1)) {
+ DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
+ }
+ else {
+ /* for drawing always on front */
+ DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
+ }
+
+ /* image texture for pattern */
+ if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
+ ImBuf *ibuf;
+ Image *image = gp_style->sima;
+ ImageUser iuser = { NULL };
+ void *lock;
+
+ iuser.ok = true;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ else {
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
+ DRW_shgroup_uniform_texture(grp, "myTexture", texture);
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ else {
+ /* if no texture defined, need a blank texture to avoid errors in draw manager */
+ DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
+ }
+
+ return grp;
+}
+
+/* create shading group for volumetrics */
+static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
+ GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
+ bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* e_data.gpencil_stroke_sh */
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
+ DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(grp, "pixelsize", &U.pixelsize, 1);
+
+ /* avoid wrong values */
+ if ((gpd) && (gpd->pixfactor == 0)) {
+ gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ }
+
+ /* object scale and depth */
+ if ((ob) && (id > -1)) {
+ stl->shgroups[id].obj_scale = (ob->size[0] + ob->size[1] + ob->size[2]) / 3.0f;
+ DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
+ stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
+ DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
+
+ stl->shgroups[id].mode = gp_style->mode;
+ stl->shgroups[id].stroke_style = gp_style->stroke_style;
+ stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
+ if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
+ stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
+ if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
+ stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
+ }
+ }
+ DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
+ DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1);
+ DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
+ }
+ else {
+ stl->storage->obj_scale = 1.0f;
+ stl->storage->keep_size = 0;
+ stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ stl->storage->mode = gp_style->mode;
+ DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
+ DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
+ DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
+ DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1);
+ if (gpd) {
+ DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
+ }
+ else {
+ DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
+ }
+ }
+
+ if (gpd) {
+ DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&gpd->xray_mode, 1);
+ }
+ else {
+ /* for drawing always on front */
+ DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
+ }
+
+ /* image texture */
+ if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
+ ImBuf *ibuf;
+ Image *image = gp_style->sima;
+ ImageUser iuser = { NULL };
+ void *lock;
+
+ iuser.ok = true;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ else {
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
+ DRW_shgroup_uniform_texture(grp, "myTexture", texture);
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ else {
+ /* if no texture defined, need a blank texture to avoid errors in draw manager */
+ DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
+ }
+
+ return grp;
+}
+
+/* add fill shading group to pass */
+static void gpencil_add_fill_shgroup(
+ GpencilBatchCache *cache, DRWShadingGroup *fillgrp,
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
+ const float tintcolor[4], const bool onion, const bool custonion)
+{
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ if (gps->totpoints >= 3) {
+ float tfill[4];
+ /* set color using material, tint color and opacity */
+ interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
+ tfill[3] = gps->runtime.tmp_fill_rgba[3] * gpl->opacity;
+ if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
+ const float *color;
+ if (!onion) {
+ color = tfill;
+ }
+ else {
+ if (custonion) {
+ color = tintcolor;
+ }
+ else {
+ ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]);
+ color = tfill;
+ }
+ }
+ if (cache->is_dirty) {
+ gpencil_batch_cache_check_free_slots(ob);
+ cache->batch_fill[cache->cache_idx] = DRW_gpencil_get_fill_geom(ob, gps, color);
+ }
+ DRW_shgroup_call_add(fillgrp, cache->batch_fill[cache->cache_idx], gpf->runtime.viewmatrix);
+ }
+ }
+}
+
+/* add stroke shading group to pass */
+static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup *strokegrp,
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
+ const float opacity, const float tintcolor[4], const bool onion, const bool custonion)
+{
+ float tcolor[4];
+ float ink[4];
+ short sthickness;
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* set color using base color, tint color and opacity */
+ if (!onion) {
+ /* if special stroke, use fill color as stroke color */
+ if (gps->flag & GP_STROKE_NOFILL) {
+ interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
+ tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
+ }
+ else {
+ interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]);
+ tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity;
+ }
+ copy_v4_v4(ink, tcolor);
+ }
+ else {
+ if (custonion) {
+ copy_v4_v4(ink, tintcolor);
+ }
+ else {
+ ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity);
+ copy_v4_v4(ink, tcolor);
+ }
+ }
+
+ sthickness = gps->thickness + gpl->line_change;
+ CLAMP_MIN(sthickness, 1);
+ if (cache->is_dirty) {
+ gpencil_batch_cache_check_free_slots(ob);
+ if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
+ cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gpf, gps, sthickness, ink);
+ }
+ else {
+ cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_point_geom(gps, sthickness, ink);
+ }
+ }
+ DRW_shgroup_call_add(strokegrp, cache->batch_stroke[cache->cache_idx], gpf->runtime.viewmatrix);
+}
+
+/* add edit points shading group to pass */
+static void gpencil_add_editpoints_shgroup(
+ GPENCIL_StorageList *stl, GpencilBatchCache *cache, ToolSettings *UNUSED(ts), Object *ob,
+ bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* alpha factor for edit points/line to make them more subtle */
+ float edit_alpha = v3d->vertex_opacity;
+
+ if (GPENCIL_ANY_EDIT_MODE(gpd)) {
+ Object *obact = DRW_context_state_get()->obact;
+ if ((!obact) || (obact->type != OB_GPENCIL)) {
+ return;
+ }
+ const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+
+ /* line of the original stroke */
+ if (cache->is_dirty) {
+ gpencil_batch_cache_check_free_slots(ob);
+ cache->batch_edlin[cache->cache_idx] = DRW_gpencil_get_edlin_geom(gps, edit_alpha, gpd->flag);
+ }
+ if (cache->batch_edlin[cache->cache_idx]) {
+ if ((obact) && (obact == ob) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES))
+ {
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_edit_line,
+ cache->batch_edlin[cache->cache_idx],
+ gpf->runtime.viewmatrix);
+ }
+ }
+ /* edit points */
+ if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
+ if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
+ if (cache->is_dirty) {
+ gpencil_batch_cache_check_free_slots(ob);
+ cache->batch_edit[cache->cache_idx] = DRW_gpencil_get_edit_geom(gps, edit_alpha, gpd->flag);
+ }
+ if (cache->batch_edit[cache->cache_idx]) {
+ if ((obact) && (obact == ob)) {
+ /* edit pass */
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_edit_point,
+ cache->batch_edit[cache->cache_idx],
+ gpf->runtime.viewmatrix);
+ }
+ }
+ }
+ }
+ }
+}
+
+/* function to draw strokes for onion only */
+static void gpencil_draw_onion_strokes(
+ GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, Object *ob,
+ bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf,
+ const float opacity, const float tintcolor[4], const bool custonion)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
+
+ float viewmatrix[4][4];
+
+ /* get parent matrix and save as static data */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
+ copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ int id = stl->storage->shgroup_id;
+ /* check if stroke can be drawn */
+ if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
+ continue;
+ }
+ /* limit the number of shading groups */
+ if (id >= GPENCIL_MAX_SHGROUPS) {
+ continue;
+ }
+
+ stl->shgroups[id].shgrps_fill = NULL;
+ if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
+ stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, true);
+ }
+ else {
+ stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, true);
+ }
+
+ /* stroke */
+ gpencil_add_stroke_shgroup(
+ cache, stl->shgroups[id].shgrps_stroke, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
+
+ stl->storage->shgroup_id++;
+ cache->cache_idx++;
+ }
+}
+
+
+/* main function to draw strokes */
+static void gpencil_draw_strokes(
+ GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob,
+ bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf,
+ const float opacity, const float tintcolor[4], const bool custonion)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ bGPDstroke *gps, *src_gps;
+ DRWShadingGroup *fillgrp;
+ DRWShadingGroup *strokegrp;
+ float viewmatrix[4][4];
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool playing = stl->storage->is_playing;
+ const bool is_render = (bool)stl->storage->is_render;
+ const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
+ const bool overlay_multiedit = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) : true;
+
+ /* Get evaluation context */
+ /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files
+ * (i.e. the thumbnail offscreen rendering fails)
+ */
+ Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
+
+ /* get parent matrix and save as static data */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
+ copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix);
+
+ /* apply geometry modifiers */
+ if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
+ if (!stl->storage->simplify_modif) {
+ if (BKE_gpencil_has_geometry_modifiers(ob)) {
+ BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render);
+ }
+ }
+ }
+
+ if (src_gpf) {
+ src_gps = src_gpf->strokes.first;
+ }
+ else {
+ src_gps = NULL;
+ }
+
+ for (gps = derived_gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* check if stroke can be drawn */
+ if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
+ continue;
+ }
+ /* limit the number of shading groups */
+ if (stl->storage->shgroup_id >= GPENCIL_MAX_SHGROUPS) {
+ continue;
+ }
+
+ /* be sure recalc all chache in source stroke to avoid recalculation when frame change
+ * and improve fps */
+ if (src_gps) {
+ DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps);
+ }
+
+ /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */
+ if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
+ if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID))
+ {
+ continue;
+ }
+ }
+
+ if ((gpl->actframe->framenum == derived_gpf->framenum) ||
+ (!is_multiedit) || (overlay_multiedit))
+ {
+ int id = stl->storage->shgroup_id;
+ if (gps->totpoints > 0) {
+ if ((gps->totpoints > 2) && (!stl->storage->simplify_fill) &&
+ ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) &&
+ ((gps->flag & GP_STROKE_NOFILL) == 0))
+ {
+ stl->shgroups[id].shgrps_fill = DRW_gpencil_shgroup_fill_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_fill_sh, gpd, gp_style, id);
+ }
+ else {
+ stl->shgroups[id].shgrps_fill = NULL;
+ }
+ if ((gp_style->mode == GP_STYLE_MODE_LINE) && (gps->totpoints > 1)) {
+ stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, false);
+ }
+ else {
+ stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, false);
+ }
+ }
+ else {
+ stl->shgroups[id].shgrps_fill = NULL;
+ stl->shgroups[id].shgrps_stroke = NULL;
+ }
+ stl->storage->shgroup_id++;
+
+ fillgrp = stl->shgroups[id].shgrps_fill;
+ strokegrp = stl->shgroups[id].shgrps_stroke;
+
+ /* copy color to temp fields to apply temporal changes in the stroke */
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ /* apply modifiers (only modify geometry, but not create ) */
+ if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
+ if (!stl->storage->simplify_modif) {
+ BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render);
+ }
+ }
+
+ /* fill */
+ if ((fillgrp) && (!stl->storage->simplify_fill)) {
+ gpencil_add_fill_shgroup(
+ cache, fillgrp, ob, gpl, derived_gpf, gps, tintcolor, false, custonion);
+ }
+ /* stroke */
+ if (strokegrp) {
+ gpencil_add_stroke_shgroup(
+ cache, strokegrp, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
+ }
+ }
+
+ /* edit points (only in edit mode and not play animation not render) */
+ if ((src_gps) && (!playing) && (!is_render)) {
+ if (!stl->g_data->shgrps_edit_line) {
+ stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass);
+ }
+ if (!stl->g_data->shgrps_edit_point) {
+ stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->edit_pass);
+ const float *viewport_size = DRW_viewport_size_get();
+ DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
+ }
+
+ gpencil_add_editpoints_shgroup(stl, cache, ts, ob, gpd, gpl, derived_gpf, src_gps);
+ }
+
+ if (src_gps) {
+ src_gps = src_gps->next;
+ }
+
+ cache->cache_idx++;
+ }
+}
+
+ /* draw stroke in drawing buffer */
+void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ bGPdata *gpd = ob->data;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ float obscale = (ob->size[0] + ob->size[1] + ob->size[2]) / 3.0f;
+
+ /* use the brush material */
+ Material *ma = BKE_gpencil_get_material_from_brush(brush);
+ if (ma != NULL) {
+ gp_style = ma->gp_style;
+ }
+ /* this is not common, but avoid any special situations when brush could be without material */
+ if (gp_style == NULL) {
+ gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ }
+
+ /* drawing strokes */
+ /* Check if may need to draw the active stroke cache, only if this layer is the active layer
+ * that is being edited. (Stroke buffer is currently stored in gp-data)
+ */
+ if (ED_gpencil_session_active() && (gpd->runtime.sbuffer_size > 0)) {
+ if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ short lthick = brush->size * obscale;
+ /* if only one point, don't need to draw buffer because the user has no time to see it */
+ if (gpd->runtime.sbuffer_size > 1) {
+ if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
+ stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
+ }
+ else {
+ stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
+ }
+
+ /* clean previous version of the batch */
+ if (stl->storage->buffer_stroke) {
+ GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke);
+ MEM_SAFE_FREE(e_data->batch_buffer_stroke);
+ stl->storage->buffer_stroke = false;
+ }
+
+ /* use unit matrix because the buffer is in screen space and does not need conversion */
+ if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
+ e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
+ gpd, stl->storage->unit_matrix, lthick);
+ }
+ else {
+ e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
+ gpd, stl->storage->unit_matrix, lthick);
+ }
+
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_drawing_stroke,
+ e_data->batch_buffer_stroke,
+ stl->storage->unit_matrix);
+
+ if ((gpd->runtime.sbuffer_size >= 3) && (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
+ ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0))
+ {
+ /* if not solid, fill is simulated with solid color */
+ if (gpd->runtime.bfill_style > 0) {
+ gpd->runtime.sfill[3] = 0.5f;
+ }
+ stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
+ e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
+
+ /* clean previous version of the batch */
+ if (stl->storage->buffer_fill) {
+ GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill);
+ MEM_SAFE_FREE(e_data->batch_buffer_fill);
+ stl->storage->buffer_fill = false;
+ }
+
+ e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_drawing_fill,
+ e_data->batch_buffer_fill,
+ stl->storage->unit_matrix);
+ stl->storage->buffer_fill = true;
+ }
+ stl->storage->buffer_stroke = true;
+ }
+ }
+ }
+}
+
+/* get alpha factor for onion strokes */
+static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd)
+{
+#define MIN_ALPHA_VALUE 0.01f
+
+ /* if fade is disabled, opacity is equal in all frames */
+ if ((gpd->onion_flag & GP_ONION_FADE) == 0) {
+ color[3] = gpd->onion_factor;
+ }
+ else {
+ /* add override opacity factor */
+ color[3] += gpd->onion_factor - 0.5f;
+ }
+
+ CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f);
+}
+
+/* draw onion-skinning for a layer */
+static void gpencil_draw_onionskins(
+ GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata,
+ Object *ob, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
+{
+
+ const float default_color[3] = { UNPACK3(U.gpencil_new_layer_col) };
+ const float alpha = 1.0f;
+ float color[4];
+ int idx;
+ float fac = 1.0f;
+ int step = 0;
+ int mode = 0;
+ bool colflag = false;
+ bGPDframe *gpf_loop = NULL;
+ int last = gpf->framenum;
+
+ colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL;
+
+
+ /* -------------------------------
+ * 1) Draw Previous Frames First
+ * ------------------------------- */
+ step = gpd->gstep;
+ mode = gpd->onion_mode;
+
+ if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) {
+ copy_v3_v3(color, gpd->gcolor_prev);
+ }
+ else {
+ copy_v3_v3(color, default_color);
+ }
+
+ idx = 0;
+ for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
+ /* only selected frames */
+ if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
+ continue;
+ }
+ /* absolute range */
+ if (mode == GP_ONION_MODE_ABSOLUTE) {
+ if ((gpf->framenum - gf->framenum) > step) {
+ break;
+ }
+ }
+ /* relative range */
+ if (mode == GP_ONION_MODE_RELATIVE) {
+ idx++;
+ if (idx > step) {
+ break;
+ }
+
+ }
+ /* alpha decreases with distance from curframe index */
+ if (mode != GP_ONION_MODE_SELECTED) {
+ if (mode == GP_ONION_MODE_ABSOLUTE) {
+ fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1));
+ }
+ else {
+ fac = 1.0f - ((float)idx / (float)(step + 1));
+ }
+ color[3] = alpha * fac * 0.66f;
+ }
+ else {
+ idx++;
+ fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
+ color[3] = fac;
+ }
+
+ /* if loop option, save the frame to use later */
+ if ((mode != GP_ONION_MODE_ABSOLUTE) && (gpd->onion_flag & GP_ONION_LOOP)) {
+ gpf_loop = gf;
+ }
+
+ gpencil_get_onion_alpha(color, gpd);
+ gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
+ }
+ /* -------------------------------
+ * 2) Now draw next frames
+ * ------------------------------- */
+ step = gpd->gstep_next;
+ mode = gpd->onion_mode;
+
+ if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) {
+ copy_v3_v3(color, gpd->gcolor_next);
+ }
+ else {
+ copy_v3_v3(color, default_color);
+ }
+
+ idx = 0;
+ for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
+ /* only selected frames */
+ if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
+ continue;
+ }
+ /* absolute range */
+ if (mode == GP_ONION_MODE_ABSOLUTE) {
+ if ((gf->framenum - gpf->framenum) > step) {
+ break;
+ }
+ }
+ /* relative range */
+ if (mode == GP_ONION_MODE_RELATIVE) {
+ idx++;
+ if (idx > step) {
+ break;
+ }
+
+ }
+ /* alpha decreases with distance from curframe index */
+ if (mode != GP_ONION_MODE_SELECTED) {
+ if (mode == GP_ONION_MODE_ABSOLUTE) {
+ fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1));
+ }
+ else {
+ fac = 1.0f - ((float)idx / (float)(step + 1));
+ }
+ color[3] = alpha * fac * 0.66f;
+ }
+ else {
+ idx++;
+ fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
+ color[3] = fac;
+ }
+
+ gpencil_get_onion_alpha(color, gpd);
+ gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
+ if (last < gf->framenum) {
+ last = gf->framenum;
+ }
+ }
+
+ /* Draw first frame in blue for loop mode */
+ if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) {
+ if ((last == gpf->framenum) || (gpf->next == NULL)) {
+ gpencil_get_onion_alpha(color, gpd);
+ gpencil_draw_onion_strokes(
+ cache, e_data, vedata, ob, gpd, gpl,
+ gpf_loop, color[3], color, colflag);
+ }
+ }
+}
+
+/* populate a datablock for multiedit (no onions, no modifiers) */
+void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd)
+{
+ bGPDframe *gpf = NULL;
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
+ ToolSettings *ts = scene->toolsettings;
+ cache->cache_idx = 0;
+
+ /* check if playing animation */
+ bool playing = stl->storage->is_playing;
+
+ /* draw strokes */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* don't draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* list of frames to draw */
+ if (!playing) {
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
+ gpencil_draw_strokes(
+ cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
+ gpl->opacity, gpl->tintcolor, false);
+ }
+ }
+ }
+ else {
+ gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
+ if (gpf) {
+ gpencil_draw_strokes(
+ cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
+ gpl->opacity, gpl->tintcolor, false);
+ }
+ }
+
+ }
+
+ cache->is_dirty = false;
+}
+
+/* helper for populate a complete grease pencil datablock */
+void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
+ ToolSettings *ts = scene->toolsettings;
+ bGPDframe *derived_gpf = NULL;
+ const bool main_onion = v3d != NULL ? ((v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) == 0) : true;
+ const bool no_onion = (bool)(gpd->flag & GP_DATA_STROKE_WEIGHTMODE) || main_onion;
+ const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
+
+ /* check if playing animation */
+ bool playing = stl->storage->is_playing;
+
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
+ cache->cache_idx = 0;
+
+ /* init general modifiers data */
+ if (!stl->storage->simplify_modif) {
+ if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
+ BKE_gpencil_lattice_init(ob);
+ }
+ }
+ /* draw normal strokes */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* don't draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
+ if (gpf == NULL)
+ continue;
+
+ /* create GHash if need */
+ if (gpl->runtime.derived_data == NULL) {
+ gpl->runtime.derived_data = (GHash *)BLI_ghash_str_new(gpl->info);
+ }
+
+ if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) {
+ derived_gpf = BLI_ghash_lookup(gpl->runtime.derived_data, ob->id.name);
+ }
+ else {
+ derived_gpf = NULL;
+ }
+
+ if (derived_gpf == NULL) {
+ cache->is_dirty = true;
+ }
+ if (cache->is_dirty) {
+ if (derived_gpf != NULL) {
+ /* first clear temp data */
+ if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) {
+ BLI_ghash_remove(gpl->runtime.derived_data, ob->id.name, NULL, NULL);
+ }
+
+ BKE_gpencil_free_frame_runtime_data(derived_gpf);
+ }
+ /* create new data */
+ derived_gpf = BKE_gpencil_frame_duplicate(gpf);
+ if (!BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) {
+ BLI_ghash_insert(gpl->runtime.derived_data, ob->id.name, derived_gpf);
+ }
+ else {
+ BLI_ghash_reinsert(gpl->runtime.derived_data, ob->id.name, derived_gpf, NULL, NULL);
+ }
+ }
+
+ /* draw onion skins */
+ if ((gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
+ (!no_onion) && (overlay) &&
+ (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
+ ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
+ {
+ if ((!stl->storage->is_render) ||
+ ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
+ {
+ gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf);
+ }
+ }
+
+ /* draw normal strokes */
+ gpencil_draw_strokes(
+ cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf,
+ gpl->opacity, gpl->tintcolor, false);
+
+ }
+
+ /* clear any lattice data */
+ if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
+ BKE_gpencil_lattice_clear(ob);
+ }
+
+ cache->is_dirty = false;
+}
+
+/* Helper for gpencil_instance_modifiers()
+ * See also MOD_gpencilinstance.c -> bakeModifier()
+ */
+static void gp_instance_modifier_make_instances(GPENCIL_StorageList *stl, Object *ob, InstanceGpencilModifierData *mmd)
+{
+ /* reset random */
+ mmd->rnd[0] = 1;
+ int e = 0;
+
+ /* Generate instances */
+ for (int x = 0; x < mmd->count[0]; x++) {
+ for (int y = 0; y < mmd->count[1]; y++) {
+ for (int z = 0; z < mmd->count[2]; z++) {
+ if ((x == 0) && (y == 0) && (z == 0)) {
+ continue;
+ }
+
+ Object *newob = NULL;
+ const int elem_idx[3] = {x, y, z};
+ float mat[4][4];
+ int sh;
+
+ /* original strokes are at index = 0,0,0 */
+ if ((x == 0) && (y == 0) && (z == 0)) {
+ continue;
+ }
+
+ /* compute transform for instance */
+ BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat);
+
+ /* add object to cache */
+ newob = MEM_dupallocN(ob);
+
+ /* Create a unique name or the object hash used in draw will fail.
+ * the name must be unique in the hash, not in the scene because
+ * the object never is linked to scene and is removed after drawing.
+ *
+ * It uses special characters to be sure the name cannot be equal
+ * to any existing name because UI limits the use of special characters.
+ *
+ * Name = OB\t_{pointer}_{index}
+ */
+ sprintf(newob->id.name, "OB\t_%p_%d", &ob, e++);
+
+ mul_m4_m4m4(newob->obmat, ob->obmat, mat);
+
+ /* apply scale */
+ ARRAY_SET_ITEMS(newob->size, mat[0][0], mat[1][1], mat[2][2]);
+
+ /* apply shift */
+ sh = x;
+ if (mmd->lock_axis == GP_LOCKAXIS_Y) {
+ sh = y;
+ }
+ if (mmd->lock_axis == GP_LOCKAXIS_Z) {
+ sh = z;
+ }
+ madd_v3_v3fl(newob->obmat[3], mmd->shift, sh);
+
+ /* add temp object to cache */
+ stl->g_data->gp_object_cache = gpencil_object_cache_add(
+ stl->g_data->gp_object_cache, newob, true,
+ &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
+ }
+ }
+ }
+}
+
+/* create instances using instance modifiers */
+void gpencil_instance_modifiers(GPENCIL_StorageList *stl, Object *ob)
+{
+ if ((ob) && (ob->data)) {
+ bGPdata *gpd = ob->data;
+ if (GPENCIL_ANY_EDIT_MODE(gpd)) {
+ return;
+ }
+ }
+
+ for (GpencilModifierData *md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if (((md->mode & eGpencilModifierMode_Realtime) && (stl->storage->is_render == false)) ||
+ ((md->mode & eGpencilModifierMode_Render) && (stl->storage->is_render == true)))
+ {
+ if (md->type == eGpencilModifierType_Instance) {
+ InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
+
+ /* Only add instances if the "Make Objects" flag is set
+ * FIXME: This is a workaround for z-ordering weirdness when all instances are in the same object
+ */
+ if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) {
+ gp_instance_modifier_make_instances(stl, ob, mmd);
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
new file mode 100644
index 00000000000..2a4f2f999bc
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_engine.c
+ * \ingroup draw
+ */
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BKE_camera.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_gpencil.h"
+#include "BKE_shader_fx.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_view3d_types.h"
+
+#include "draw_mode_engines.h"
+
+#include "UI_resources.h"
+
+#include "GPU_texture.h"
+
+#include "gpencil_engine.h"
+
+#include "ED_screen.h"
+#include "ED_gpencil.h"
+
+extern char datatoc_gpencil_fill_vert_glsl[];
+extern char datatoc_gpencil_fill_frag_glsl[];
+extern char datatoc_gpencil_stroke_vert_glsl[];
+extern char datatoc_gpencil_stroke_geom_glsl[];
+extern char datatoc_gpencil_stroke_frag_glsl[];
+extern char datatoc_gpencil_zdepth_mix_frag_glsl[];
+extern char datatoc_gpencil_simple_mix_frag_glsl[];
+extern char datatoc_gpencil_point_vert_glsl[];
+extern char datatoc_gpencil_point_geom_glsl[];
+extern char datatoc_gpencil_point_frag_glsl[];
+extern char datatoc_gpencil_background_frag_glsl[];
+extern char datatoc_gpencil_paper_frag_glsl[];
+extern char datatoc_gpencil_edit_point_vert_glsl[];
+extern char datatoc_gpencil_edit_point_geom_glsl[];
+extern char datatoc_gpencil_edit_point_frag_glsl[];
+
+/* *********** STATIC *********** */
+static GPENCIL_e_data e_data = {NULL}; /* Engine data */
+
+/* *********** FUNCTIONS *********** */
+
+/* create a multisample buffer if not present */
+void DRW_gpencil_multisample_ensure(GPENCIL_Data *vedata, int rect_w, int rect_h)
+{
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
+
+ short samples = stl->storage->multisamples;
+
+ if (samples > 0) {
+ if (!fbl->multisample_fb) {
+ fbl->multisample_fb = GPU_framebuffer_create();
+ if (fbl->multisample_fb) {
+ if (txl->multisample_color == NULL) {
+ txl->multisample_color = GPU_texture_create_2D_multisample(
+ rect_w, rect_h, GPU_RGBA16F, NULL, samples, NULL);
+ }
+ if (txl->multisample_depth == NULL) {
+ txl->multisample_depth = GPU_texture_create_2D_multisample(
+ rect_w, rect_h, GPU_DEPTH24_STENCIL8, NULL, samples, NULL);
+ }
+ GPU_framebuffer_ensure_config(
+ &fbl->multisample_fb, {
+ GPU_ATTACHMENT_TEXTURE(txl->multisample_depth),
+ GPU_ATTACHMENT_TEXTURE(txl->multisample_color)
+ });
+ }
+ }
+ }
+}
+
+static void GPENCIL_create_framebuffers(void *vedata)
+{
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
+ /* Go full 32bits for rendering */
+ GPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F;
+
+ if (DRW_state_is_fbo()) {
+ const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] };
+
+ /* create multiframe framebuffer for AA */
+ if (stl->storage->multisamples > 0) {
+ DRW_gpencil_multisample_ensure(vedata, size[0], size[1]);
+ }
+
+ /* temp textures */
+ e_data.temp_depth_tx_a = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH24_STENCIL8,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_a = DRW_texture_pool_query_2D(size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_a, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_a),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_a)
+ });
+
+ e_data.temp_depth_tx_b = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH24_STENCIL8,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_b = DRW_texture_pool_query_2D(
+ size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_b, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_b),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b)
+ });
+
+ /* used for rim FX effect */
+ e_data.temp_depth_tx_rim = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH24_STENCIL8,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_rim = DRW_texture_pool_query_2D(
+ size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_rim, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_rim),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_rim),
+ });
+
+ /* background framebuffer to speed up drawing process (always 16 bits) */
+ e_data.background_depth_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH24_STENCIL8,
+ &draw_engine_gpencil_type);
+ e_data.background_color_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_RGBA32F,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->background_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.background_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.background_color_tx)
+ });
+ }
+}
+
+static void GPENCIL_create_shaders(void)
+{
+ /* normal fill shader */
+ if (!e_data.gpencil_fill_sh) {
+ e_data.gpencil_fill_sh = DRW_shader_create(
+ datatoc_gpencil_fill_vert_glsl, NULL,
+ datatoc_gpencil_fill_frag_glsl, NULL);
+ }
+
+ /* normal stroke shader using geometry to display lines (line mode) */
+ if (!e_data.gpencil_stroke_sh) {
+ e_data.gpencil_stroke_sh = DRW_shader_create(
+ datatoc_gpencil_stroke_vert_glsl,
+ datatoc_gpencil_stroke_geom_glsl,
+ datatoc_gpencil_stroke_frag_glsl,
+ NULL);
+ }
+
+ /* dot/rectangle mode for normal strokes using geometry */
+ if (!e_data.gpencil_point_sh) {
+ e_data.gpencil_point_sh = DRW_shader_create(
+ datatoc_gpencil_point_vert_glsl,
+ datatoc_gpencil_point_geom_glsl,
+ datatoc_gpencil_point_frag_glsl,
+ NULL);
+ }
+ /* used for edit points or strokes with one point only */
+ if (!e_data.gpencil_edit_point_sh) {
+ e_data.gpencil_edit_point_sh = DRW_shader_create(
+ datatoc_gpencil_edit_point_vert_glsl,
+ datatoc_gpencil_edit_point_geom_glsl,
+ datatoc_gpencil_edit_point_frag_glsl, NULL);
+ }
+
+ /* used for edit lines for edit modes */
+ if (!e_data.gpencil_line_sh) {
+ e_data.gpencil_line_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR);
+ }
+
+ /* used to filling during drawing */
+ if (!e_data.gpencil_drawing_fill_sh) {
+ e_data.gpencil_drawing_fill_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+
+ /* full screen for mix zdepth*/
+ if (!e_data.gpencil_fullscreen_sh) {
+ e_data.gpencil_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_zdepth_mix_frag_glsl, NULL);
+ }
+ if (!e_data.gpencil_simple_fullscreen_sh) {
+ e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_simple_mix_frag_glsl, NULL);
+ }
+
+ /* shaders for use when drawing */
+ if (!e_data.gpencil_background_sh) {
+ e_data.gpencil_background_sh = DRW_shader_create_fullscreen(datatoc_gpencil_background_frag_glsl, NULL);
+ }
+ if (!e_data.gpencil_paper_sh) {
+ e_data.gpencil_paper_sh = DRW_shader_create_fullscreen(datatoc_gpencil_paper_frag_glsl, NULL);
+ }
+}
+
+void GPENCIL_engine_init(void *vedata)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ /* init storage */
+ if (!stl->storage) {
+ stl->storage = MEM_callocN(sizeof(GPENCIL_Storage), "GPENCIL_Storage");
+
+ /* unit matrix */
+ unit_m4(stl->storage->unit_matrix);
+ }
+
+ stl->storage->multisamples = U.gpencil_multisamples;
+
+ /* create framebuffers */
+ GPENCIL_create_framebuffers(vedata);
+
+ /* create shaders */
+ GPENCIL_create_shaders();
+ GPENCIL_create_fx_shaders(&e_data);
+
+ /* blank texture used if no texture defined for fill shader */
+ if (!e_data.gpencil_blank_texture) {
+ float rect[16][16][4] = {{{0.0f}}};
+ e_data.gpencil_blank_texture = DRW_texture_create_2D(16, 16, GPU_RGBA8, DRW_TEX_FILTER, (float *)rect);
+ }
+}
+
+static void GPENCIL_engine_free(void)
+{
+ /* only free custom shaders, builtin shaders are freed in blender close */
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_fill_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_stroke_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_point_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
+
+ DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
+
+ GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_stroke);
+ MEM_SAFE_FREE(e_data.batch_buffer_stroke);
+
+ GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill);
+ MEM_SAFE_FREE(e_data.batch_buffer_fill);
+
+ /* effects */
+ GPENCIL_delete_fx_shaders(&e_data);
+}
+
+void GPENCIL_cache_init(void *vedata)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+
+ /* Special handling for when active object is GP object (e.g. for draw mode) */
+ Object *obact = draw_ctx->obact;
+ bGPdata *obact_gpd = NULL;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ if (obact && (obact->type == OB_GPENCIL) && (obact->data)) {
+ obact_gpd = (bGPdata *)obact->data;
+ gp_style = BKE_material_gpencil_settings_get(obact, obact->actcol);
+ }
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ stl->storage->xray = GP_XRAY_FRONT; /* used for drawing */
+ stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; /* used for drawing */
+ }
+ stl->storage->tonemapping = 0;
+
+ stl->g_data->shgrps_edit_line = NULL;
+ stl->g_data->shgrps_edit_point = NULL;
+
+ if (!stl->shgroups) {
+ /* Alloc maximum size because count strokes is very slow and can be very complex due onion skinning.
+ I tried to allocate only one block and using realloc, increasing the size when read a new strokes
+ in cache_finish, but the realloc produce weird things on screen, so we keep as is while we found
+ a better solution
+ */
+ stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup");
+ }
+
+ /* init gp objects cache */
+ stl->g_data->gp_cache_used = 0;
+ stl->g_data->gp_cache_size = 0;
+ stl->g_data->gp_object_cache = NULL;
+
+ {
+ /* Stroke pass */
+ psl->stroke_pass = DRW_pass_create(
+ "GPencil Stroke Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND);
+ stl->storage->shgroup_id = 0;
+
+ /* edit pass */
+ psl->edit_pass = DRW_pass_create(
+ "GPencil Edit Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
+
+ /* detect if playing animation */
+ stl->storage->is_playing = false;
+ if (draw_ctx->evil_C) {
+ stl->storage->is_playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL;
+ }
+ /* save render state */
+ stl->storage->is_render = DRW_state_is_image_render();
+ stl->storage->is_mat_preview = (bool)stl->storage->is_render && STREQ(scene->id.name + 2, "preview");
+
+ if (obact_gpd) {
+ /* for some reason, when press play there is a delay in the animation flag check
+ * and this produces errors. To be sure, we set cache as dirty because the frame
+ * is changing.
+ */
+ if (stl->storage->is_playing == true) {
+ obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+ /* if render, set as dirty to update all data */
+ else if (stl->storage->is_render == true) {
+ obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+ }
+
+ /* save simplify flags (can change while drawing, so it's better to save) */
+ stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing);
+ stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
+ stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing);
+
+ /* save pixsize */
+ stl->storage->pixsize = DRW_viewport_pixelsize_get();
+ if ((!DRW_state_is_opengl_render()) && (stl->storage->is_render)) {
+ stl->storage->pixsize = &stl->storage->render_pixsize;
+ }
+
+ /* detect if painting session */
+ if ((obact_gpd) &&
+ (obact_gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
+ (stl->storage->is_playing == false))
+ {
+ if (((obact_gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) &&
+ (obact_gpd->runtime.sbuffer_size > 1))
+ {
+ stl->g_data->session_flag = GP_DRW_PAINT_PAINTING;
+ }
+ else {
+ stl->g_data->session_flag = GP_DRW_PAINT_IDLE;
+ }
+ }
+ else {
+ /* if not drawing mode */
+ stl->g_data->session_flag = GP_DRW_PAINT_HOLD;
+ }
+
+ if (gp_style) {
+ stl->storage->stroke_style = gp_style->stroke_style;
+ stl->storage->color_type = GPENCIL_COLOR_SOLID;
+ if (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) {
+ stl->storage->color_type = GPENCIL_COLOR_TEXTURE;
+ if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
+ stl->storage->color_type = GPENCIL_COLOR_PATTERN;
+ }
+ }
+ }
+ else {
+ stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID;
+ stl->storage->color_type = GPENCIL_COLOR_SOLID;
+ }
+
+ /* drawing buffer pass for drawing the stroke that is beeing drawing by the user. The data
+ * is stored in sbuffer
+ */
+ psl->drawing_pass = DRW_pass_create(
+ "GPencil Drawing Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+
+ /* full screen pass to combine the result with default framebuffer */
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ psl->mix_pass = DRW_pass_create(
+ "GPencil Mix Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass);
+ DRW_shgroup_call_add(mix_shgrp, quad, NULL);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &e_data.input_color_tx);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &e_data.input_depth_tx);
+ DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
+
+ /* mix pass no blend used to copy between passes. A separated pass is required
+ * because if mix_pass is used, the acumulation of blend degrade the colors.
+ *
+ * This pass is used too to take the snapshot used for background_pass. This image
+ * will be used as the background while the user is drawing.
+ */
+ psl->mix_pass_noblend = DRW_pass_create(
+ "GPencil Mix Pass no blend",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass_noblend);
+ DRW_shgroup_call_add(mix_shgrp_noblend, quad, NULL);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeColor", &e_data.input_color_tx);
+ DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeDepth", &e_data.input_depth_tx);
+ DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1);
+
+ /* Painting session pass (used only to speedup while the user is drawing )
+ * This pass is used to show the snapshot of the current grease pencil strokes captured
+ * when the user starts to draw (see comments above).
+ * In this way, the previous strokes don't need to be redraw and the drawing process
+ * is far to agile.
+ */
+ psl->background_pass = DRW_pass_create(
+ "GPencil Background Painting Session Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh, psl->background_pass);
+ DRW_shgroup_call_add(background_shgrp, quad, NULL);
+ DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &e_data.background_color_tx);
+ DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &e_data.background_depth_tx);
+
+ /* pass for drawing paper (only if viewport)
+ * In render, the v3d is null so the paper is disabled
+ * The paper is way to isolate the drawing in complex scene and to have a cleaner
+ * drawing area.
+ */
+ if (v3d) {
+ psl->paper_pass = DRW_pass_create(
+ "GPencil Paper Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
+ DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass);
+ DRW_shgroup_call_add(paper_shgrp, quad, NULL);
+ DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1);
+ DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1);
+ }
+
+ /* grid pass */
+ if (v3d) {
+ psl->grid_pass = DRW_pass_create(
+ "GPencil Grid Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass);
+ }
+
+ /* create effects passes */
+ if (!stl->storage->simplify_fx) {
+ GPENCIL_create_fx_passes(psl);
+ }
+ }
+}
+
+void GPENCIL_cache_populate(void *vedata, Object *ob)
+{
+ /* object must be visible */
+ if (!DRW_check_object_visible_within_active_context(ob)) {
+ return;
+ }
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+ View3D *v3d = draw_ctx->v3d;
+
+ /* object datablock (this is not draw now) */
+ if (ob->type == OB_GPENCIL && ob->data) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
+
+ /* if render set as dirty */
+ if (stl->storage->is_render == true) {
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+
+ /* allocate memory for saving gp objects for drawing later */
+ stl->g_data->gp_object_cache = gpencil_object_cache_add(
+ stl->g_data->gp_object_cache, ob, false,
+ &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used);
+
+ /* generate instances as separate cache objects for instance modifiers
+ * with the "Make as Objects" option enabled
+ */
+ if (!stl->storage->simplify_modif) {
+ gpencil_instance_modifiers(stl, ob);
+ }
+ }
+ /* draw current painting strokes */
+ DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob);
+
+ /* grid */
+ if ((v3d) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_GRID) &&
+ (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact))
+ {
+ stl->g_data->batch_grid = DRW_gpencil_get_grid();
+ DRW_shgroup_call_add(stl->g_data->shgrps_grid,
+ stl->g_data->batch_grid,
+ ob->obmat);
+ }
+ }
+}
+
+void GPENCIL_cache_finish(void *vedata)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ bool is_multiedit = false;
+
+ /* if painting session, don't need to do more */
+ if (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING) {
+ return;
+ }
+
+ /* Draw all pending objects */
+ if (stl->g_data->gp_cache_used > 0) {
+ for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
+ Object *ob = stl->g_data->gp_object_cache[i].ob;
+ bGPdata *gpd = ob->data;
+
+ /* save init shading group */
+ stl->g_data->gp_object_cache[i].init_grp = stl->storage->shgroup_id;
+
+ /* fill shading groups */
+ is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ if (!is_multiedit) {
+ DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, gpd);
+ }
+ else {
+ DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, gpd);
+ }
+
+ /* save end shading group */
+ stl->g_data->gp_object_cache[i].end_grp = stl->storage->shgroup_id - 1;
+ /* if render set to dirty to refresh viewport */
+ if (stl->storage->is_render == true) {
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+ /* FX passses */
+ tGPencilObjectCache *cache = &stl->g_data->gp_object_cache[i];
+ if ((!stl->storage->simplify_fx) && (!is_multiedit)) {
+ DRW_gpencil_fx_prepare(&e_data, vedata, cache);
+ }
+ }
+ }
+}
+
+/* helper function to sort inverse gpencil objects using qsort */
+static int gpencil_object_cache_compare_zdepth(const void *a1, const void *a2)
+{
+ const tGPencilObjectCache *ps1 = a1, *ps2 = a2;
+
+ if (ps1->zdepth < ps2->zdepth) return 1;
+ else if (ps1->zdepth > ps2->zdepth) return -1;
+
+ return 0;
+}
+
+/* prepare a texture with full viewport screenshot for fast drawing */
+static void gpencil_prepare_fast_drawing(
+ GPENCIL_StorageList *stl, DefaultFramebufferList *dfbl,
+ GPENCIL_FramebufferList *fbl, DRWPass *pass,
+ const float clearcol[4])
+{
+ if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) {
+ GPU_framebuffer_bind(fbl->background_fb);
+ /* clean only in first loop cycle */
+ if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) {
+ GPU_framebuffer_clear_color_depth(fbl->background_fb, clearcol, 1.0f);
+ stl->g_data->session_flag = GP_DRW_PAINT_FILLING;
+ }
+ /* repeat pass to fill temp texture */
+ DRW_draw_pass(pass);
+ /* set default framebuffer again */
+ GPU_framebuffer_bind(dfbl->default_fb);
+ }
+}
+
+static void gpencil_free_obj_list(GPENCIL_StorageList *stl)
+{
+ /* Clear temp objects created for display instances only. These objects are created
+ * while the draw manager draw the scene, but only to hold the strokes data.
+ * see: gp_instance_modifier_make_instances()
+ *
+ * the normal objects are not freed because they are not tagged as temp objects
+ */
+ for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
+ Object *ob = stl->g_data->gp_object_cache[i].ob;
+ if (stl->g_data->gp_object_cache[i].temp_ob) {
+ MEM_SAFE_FREE(ob);
+ }
+ }
+
+ /* free the cache itself */
+ MEM_SAFE_FREE(stl->g_data->gp_object_cache);
+}
+
+/* draw scene */
+void GPENCIL_draw_scene(void *ved)
+{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
+
+ int init_grp, end_grp;
+ tGPencilObjectCache *cache;
+ const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Object *obact = draw_ctx->obact;
+ const bool playing = stl->storage->is_playing;
+ const bool is_render = stl->storage->is_render;
+
+ /* paper pass to display a confortable area to draw over complex scenes with geometry */
+ if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_PAPER) &&
+ (stl->g_data->gp_cache_used > 0))
+ {
+ DRW_draw_pass(psl->paper_pass);
+ }
+ }
+
+ /* if we have a painting session, we use fast viewport drawing method */
+ if ((!is_render) && (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING)) {
+ GPU_framebuffer_bind(dfbl->default_fb);
+
+ MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
+
+ DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->drawing_pass);
+
+ MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl);
+
+ /* free memory */
+ gpencil_free_obj_list(stl);
+
+ /* grid pass */
+ if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_GRID))
+ {
+ DRW_draw_pass(psl->grid_pass);
+ }
+ }
+
+ return;
+ }
+
+ if (DRW_state_is_fbo()) {
+ /* attach temp textures */
+ GPU_framebuffer_texture_attach(fbl->temp_fb_a, e_data.temp_depth_tx_a, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->temp_fb_a, e_data.temp_color_tx_a, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->temp_fb_b, e_data.temp_depth_tx_b, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->temp_fb_b, e_data.temp_color_tx_b, 0, 0);
+
+ GPU_framebuffer_texture_attach(fbl->background_fb, e_data.background_depth_tx, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->background_fb, e_data.background_color_tx, 0, 0);
+
+ /* Draw all pending objects */
+ if (stl->g_data->gp_cache_used > 0) {
+
+ /* sort by zdepth */
+ qsort(stl->g_data->gp_object_cache, stl->g_data->gp_cache_used,
+ sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth);
+
+ for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
+ cache = &stl->g_data->gp_object_cache[i];
+ Object *ob = cache->ob;
+ bGPdata *gpd = ob->data;
+ init_grp = cache->init_grp;
+ end_grp = cache->end_grp;
+ /* Render stroke in separated framebuffer */
+ GPU_framebuffer_bind(fbl->temp_fb_a);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
+
+ /* Stroke Pass: DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH
+ * draw only a subset that usually start with a fill and end with stroke because the
+ * shading groups are created by pairs */
+ if (end_grp >= init_grp) {
+ MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
+
+ DRW_draw_pass_subset(
+ psl->stroke_pass,
+ stl->shgroups[init_grp].shgrps_fill != NULL ?
+ stl->shgroups[init_grp].shgrps_fill : stl->shgroups[init_grp].shgrps_stroke,
+ stl->shgroups[end_grp].shgrps_stroke);
+
+ MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fbl->temp_fb_a, txl);
+ }
+
+ /* Current buffer drawing */
+ if ((!is_render) && (gpd->runtime.sbuffer_size > 0)) {
+ DRW_draw_pass(psl->drawing_pass);
+ }
+ /* fx passes */
+ if ((!stl->storage->simplify_fx) &&
+ (BKE_shaderfx_has_gpencil(ob)))
+ {
+ stl->storage->tonemapping = 0;
+ DRW_gpencil_fx_draw(&e_data, vedata, cache);
+ }
+
+ e_data.input_depth_tx = e_data.temp_depth_tx_a;
+ e_data.input_color_tx = e_data.temp_color_tx_a;
+
+ /* Combine with scene buffer */
+ if ((!is_render) || (fbl->main == NULL)) {
+ GPU_framebuffer_bind(dfbl->default_fb);
+ }
+ else {
+ GPU_framebuffer_bind(fbl->main);
+ }
+ /* tonemapping */
+ stl->storage->tonemapping = stl->storage->is_render ? 1 : 0;
+
+ DRW_draw_pass(psl->mix_pass);
+
+ /* prepare for fast drawing */
+ if (!is_render) {
+ gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol);
+ }
+ }
+ /* edit points */
+ if ((!is_render) && (!playing)) {
+ DRW_draw_pass(psl->edit_pass);
+ }
+ }
+ /* grid pass */
+ if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_GRID))
+ {
+ DRW_draw_pass(psl->grid_pass);
+ }
+ }
+ }
+ /* free memory */
+ gpencil_free_obj_list(stl);
+
+ /* detach temp textures */
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_texture_detach(fbl->temp_fb_a, e_data.temp_depth_tx_a);
+ GPU_framebuffer_texture_detach(fbl->temp_fb_a, e_data.temp_color_tx_a);
+ GPU_framebuffer_texture_detach(fbl->temp_fb_b, e_data.temp_depth_tx_b);
+ GPU_framebuffer_texture_detach(fbl->temp_fb_b, e_data.temp_color_tx_b);
+
+ GPU_framebuffer_texture_detach(fbl->background_fb, e_data.background_depth_tx);
+ GPU_framebuffer_texture_detach(fbl->background_fb, e_data.background_color_tx);
+
+ /* attach again default framebuffer after detach textures */
+ if (!is_render) {
+ GPU_framebuffer_bind(dfbl->default_fb);
+ }
+
+ /* the temp texture is ready. Now we can use fast screen drawing */
+ if (stl->g_data->session_flag & GP_DRW_PAINT_FILLING) {
+ stl->g_data->session_flag = GP_DRW_PAINT_READY;
+ }
+ }
+}
+
+static const DrawEngineDataSize GPENCIL_data_size = DRW_VIEWPORT_DATA_SIZE(GPENCIL_Data);
+
+DrawEngineType draw_engine_gpencil_type = {
+ NULL, NULL,
+ N_("GpencilMode"),
+ &GPENCIL_data_size,
+ &GPENCIL_engine_init,
+ &GPENCIL_engine_free,
+ &GPENCIL_cache_init,
+ &GPENCIL_cache_populate,
+ &GPENCIL_cache_finish,
+ NULL,
+ &GPENCIL_draw_scene,
+ NULL,
+ NULL,
+ &GPENCIL_render_to_image,
+};
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
new file mode 100644
index 00000000000..21ac6045792
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_engine.h
+ * \ingroup draw
+ */
+
+#ifndef __GPENCIL_ENGINE_H__
+#define __GPENCIL_ENGINE_H__
+
+#include "GPU_batch.h"
+
+struct tGPspoint;
+struct bGPDstroke;
+struct ModifierData;
+struct GPENCIL_Data;
+struct GPENCIL_StorageList;
+struct Object;
+struct MaterialGPencilStyle;
+struct RenderEngine;
+struct RenderLayer;
+
+ /* TODO: these could be system parameter in userprefs screen */
+#define GPENCIL_MAX_GP_OBJ 256
+
+#define GPENCIL_CACHE_BLOCK_SIZE 8
+#define GPENCIL_MAX_SHGROUPS 65536
+#define GPENCIL_MIN_BATCH_SLOTS_CHUNK 16
+
+#define GPENCIL_COLOR_SOLID 0
+#define GPENCIL_COLOR_TEXTURE 1
+#define GPENCIL_COLOR_PATTERN 2
+
+#define GP_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
+#define GP_SIMPLIFY_ONPLAY(playing) (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
+#define GP_SIMPLIFY_FILL(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
+#define GP_SIMPLIFY_MODIF(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
+#define GP_SIMPLIFY_FX(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
+
+#define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
+
+ /* *********** OBJECTS CACHE *********** */
+
+ /* used to save gpencil objects */
+typedef struct tGPencilObjectCache {
+ struct Object *ob;
+ int init_grp, end_grp;
+ int idx; /*original index, can change after sort */
+
+ /* effects */
+ DRWShadingGroup *fx_wave_sh;
+ DRWShadingGroup *fx_blur_sh;
+ DRWShadingGroup *fx_colorize_sh;
+ DRWShadingGroup *fx_pixel_sh;
+ DRWShadingGroup *fx_rim_sh;
+ DRWShadingGroup *fx_swirl_sh;
+ DRWShadingGroup *fx_flip_sh;
+ DRWShadingGroup *fx_light_sh;
+
+ float zdepth; /* z-depth value to sort gp object */
+ bool temp_ob; /* flag to tag temporary objects that must be removed after drawing loop */
+} tGPencilObjectCache;
+
+ /* *********** LISTS *********** */
+typedef struct GPENCIL_shgroup {
+ int s_clamp;
+ int stroke_style;
+ int color_type;
+ int mode;
+ int texture_mix;
+ int texture_flip;
+ int texture_clamp;
+ int fill_style;
+ int keep_size;
+ float obj_scale;
+ struct DRWShadingGroup *shgrps_fill;
+ struct DRWShadingGroup *shgrps_stroke;
+} GPENCIL_shgroup;
+
+typedef struct GPENCIL_Storage {
+ int shgroup_id; /* total elements */
+ float unit_matrix[4][4];
+ int stroke_style;
+ int color_type;
+ int mode;
+ int xray;
+ int keep_size;
+ float obj_scale;
+ float pixfactor;
+ bool is_playing;
+ bool is_render;
+ bool is_mat_preview;
+ bool buffer_stroke;
+ bool buffer_fill;
+ const float *pixsize;
+ float render_pixsize;
+ int tonemapping;
+ short multisamples;
+
+ /* simplify settings*/
+ bool simplify_fill;
+ bool simplify_modif;
+ bool simplify_fx;
+
+ /* Render Matrices and data */
+ float persmat[4][4], persinv[4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float winmat[4][4], wininv[4][4];
+ float view_vecs[2][4]; /* vec4[2] */
+
+ Object *camera; /* camera pointer for render mode */
+} GPENCIL_Storage;
+
+typedef struct GPENCIL_StorageList {
+ struct GPENCIL_Storage *storage;
+ struct g_data *g_data;
+ struct GPENCIL_shgroup *shgroups;
+} GPENCIL_StorageList;
+
+typedef struct GPENCIL_PassList {
+ struct DRWPass *stroke_pass;
+ struct DRWPass *edit_pass;
+ struct DRWPass *drawing_pass;
+ struct DRWPass *mix_pass;
+ struct DRWPass *mix_pass_noblend;
+ struct DRWPass *background_pass;
+ struct DRWPass *paper_pass;
+ struct DRWPass *grid_pass;
+
+ /* effects */
+ struct DRWPass *fx_shader_pass;
+ struct DRWPass *fx_shader_pass_blend;
+
+} GPENCIL_PassList;
+
+typedef struct GPENCIL_FramebufferList {
+ struct GPUFrameBuffer *main;
+ struct GPUFrameBuffer *temp_fb_a;
+ struct GPUFrameBuffer *temp_fb_b;
+ struct GPUFrameBuffer *temp_fb_rim;
+ struct GPUFrameBuffer *background_fb;
+
+ struct GPUFrameBuffer *multisample_fb;
+} GPENCIL_FramebufferList;
+
+typedef struct GPENCIL_TextureList {
+ struct GPUTexture *texture;
+
+ /* multisample textures */
+ struct GPUTexture *multisample_color;
+ struct GPUTexture *multisample_depth;
+
+} GPENCIL_TextureList;
+
+typedef struct GPENCIL_Data {
+ void *engine_type; /* Required */
+ struct GPENCIL_FramebufferList *fbl;
+ struct GPENCIL_TextureList *txl;
+ struct GPENCIL_PassList *psl;
+ struct GPENCIL_StorageList *stl;
+
+ /* render textures */
+ struct GPUTexture *render_depth_tx;
+ struct GPUTexture *render_color_tx;
+
+} GPENCIL_Data;
+
+/* *********** STATIC *********** */
+typedef struct g_data {
+ struct DRWShadingGroup *shgrps_edit_point;
+ struct DRWShadingGroup *shgrps_edit_line;
+ struct DRWShadingGroup *shgrps_drawing_stroke;
+ struct DRWShadingGroup *shgrps_drawing_fill;
+ struct DRWShadingGroup *shgrps_grid;
+
+ /* grid geometry */
+ GPUBatch *batch_grid;
+
+ int gp_cache_used; /* total objects in cache */
+ int gp_cache_size; /* size of the cache */
+ struct tGPencilObjectCache *gp_object_cache;
+
+ int session_flag;
+
+} g_data; /* Transient data */
+
+/* flags for fast drawing support */
+typedef enum eGPsession_Flag {
+ GP_DRW_PAINT_HOLD = (1 << 0),
+ GP_DRW_PAINT_IDLE = (1 << 1),
+ GP_DRW_PAINT_FILLING = (1 << 2),
+ GP_DRW_PAINT_READY = (1 << 3),
+ GP_DRW_PAINT_PAINTING = (1 << 4),
+} eGPsession_Flag;
+
+typedef struct GPENCIL_e_data {
+ /* general drawing shaders */
+ struct GPUShader *gpencil_fill_sh;
+ struct GPUShader *gpencil_stroke_sh;
+ struct GPUShader *gpencil_point_sh;
+ struct GPUShader *gpencil_edit_point_sh;
+ struct GPUShader *gpencil_line_sh;
+ struct GPUShader *gpencil_drawing_fill_sh;
+ struct GPUShader *gpencil_fullscreen_sh;
+ struct GPUShader *gpencil_simple_fullscreen_sh;
+ struct GPUShader *gpencil_background_sh;
+ struct GPUShader *gpencil_paper_sh;
+
+ /* effects */
+ struct GPUShader *gpencil_fx_blur_sh;
+ struct GPUShader *gpencil_fx_colorize_sh;
+ struct GPUShader *gpencil_fx_flip_sh;
+ struct GPUShader *gpencil_fx_light_sh;
+ struct GPUShader *gpencil_fx_pixel_sh;
+ struct GPUShader *gpencil_fx_rim_prepare_sh;
+ struct GPUShader *gpencil_fx_rim_resolve_sh;
+ struct GPUShader *gpencil_fx_swirl_sh;
+ struct GPUShader *gpencil_fx_wave_sh;
+
+ /* textures */
+ struct GPUTexture *background_depth_tx;
+ struct GPUTexture *background_color_tx;
+
+ struct GPUTexture *gpencil_blank_texture;
+
+ /* runtime pointers texture */
+ struct GPUTexture *input_depth_tx;
+ struct GPUTexture *input_color_tx;
+
+ /* working textures */
+ struct GPUTexture *temp_color_tx_a;
+ struct GPUTexture *temp_depth_tx_a;
+
+ struct GPUTexture *temp_color_tx_b;
+ struct GPUTexture *temp_depth_tx_b;
+
+ struct GPUTexture *temp_color_tx_rim;
+ struct GPUTexture *temp_depth_tx_rim;
+
+ /* for buffer only one batch is nedeed because the drawing is only of one stroke */
+ GPUBatch *batch_buffer_stroke;
+ GPUBatch *batch_buffer_fill;
+
+} GPENCIL_e_data; /* Engine data */
+
+/* GPUBatch Cache */
+typedef struct GpencilBatchCache {
+ /* For normal strokes, a variable number of batch can be needed depending of number of strokes.
+ It could use the stroke number as total size, but when activate the onion skining, the number
+ can change, so the size is changed dinamically.
+ */
+ GPUBatch **batch_stroke;
+ GPUBatch **batch_fill;
+ GPUBatch **batch_edit;
+ GPUBatch **batch_edlin;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+ bool is_editmode;
+ int cache_frame;
+
+ /* keep information about the size of the cache */
+ int cache_size; /* total batch slots available */
+ int cache_idx; /* current slot index */
+} GpencilBatchCache;
+
+/* general drawing functions */
+struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
+ struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, struct DRWPass *pass, struct GPUShader *shader,
+ struct Object *ob, struct bGPdata *gpd, struct MaterialGPencilStyle *gp_style, int id, bool onion);
+void DRW_gpencil_populate_datablock(struct GPENCIL_e_data *e_data, void *vedata, struct Scene *scene, struct Object *ob, struct bGPdata *gpd);
+void DRW_gpencil_populate_buffer_strokes(struct GPENCIL_e_data *e_data, void *vedata, struct ToolSettings *ts, struct Object *ob);
+void DRW_gpencil_populate_multiedit(struct GPENCIL_e_data *e_data, void *vedata, struct Scene *scene, struct Object *ob, struct bGPdata *gpd);
+void DRW_gpencil_triangulate_stroke_fill(struct bGPDstroke *gps);
+
+void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h);
+
+/* create geometry functions */
+struct GPUBatch *DRW_gpencil_get_point_geom(struct bGPDstroke *gps, short thickness, const float ink[4]);
+struct GPUBatch *DRW_gpencil_get_stroke_geom(struct bGPDframe *gpf, struct bGPDstroke *gps, short thickness, const float ink[4]);
+struct GPUBatch *DRW_gpencil_get_fill_geom(struct Object *ob, struct bGPDstroke *gps, const float color[4]);
+struct GPUBatch *DRW_gpencil_get_edit_geom(struct bGPDstroke *gps, float alpha, short dflag);
+struct GPUBatch *DRW_gpencil_get_edlin_geom(struct bGPDstroke *gps, float alpha, short dflag);
+struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, float matrix[4][4], short thickness);
+struct GPUBatch *DRW_gpencil_get_buffer_fill_geom(struct bGPdata *gpd);
+struct GPUBatch *DRW_gpencil_get_buffer_point_geom(struct bGPdata *gpd, float matrix[4][4], short thickness);
+struct GPUBatch *DRW_gpencil_get_grid(void);
+
+/* object cache functions */
+struct tGPencilObjectCache *gpencil_object_cache_add(
+ struct tGPencilObjectCache *cache_array, struct Object *ob,
+ bool is_temp, int *gp_cache_size, int *gp_cache_used);
+
+/* geometry batch cache functions */
+void gpencil_batch_cache_check_free_slots(struct Object *ob);
+struct GpencilBatchCache *gpencil_batch_cache_get(struct Object *ob, int cfra);
+
+/* modifier functions */
+void gpencil_instance_modifiers(struct GPENCIL_StorageList *stl, struct Object *ob);
+
+/* effects */
+void GPENCIL_create_fx_shaders(struct GPENCIL_e_data *e_data);
+void GPENCIL_delete_fx_shaders(struct GPENCIL_e_data *e_data);
+void GPENCIL_create_fx_passes(struct GPENCIL_PassList *psl);
+
+void DRW_gpencil_fx_prepare(
+ struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata,
+ struct tGPencilObjectCache *cache);
+void DRW_gpencil_fx_draw(
+ struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata,
+ struct tGPencilObjectCache *cache);
+
+/* main functions */
+void GPENCIL_engine_init(void *vedata);
+void GPENCIL_cache_init(void *vedata);
+void GPENCIL_cache_populate(void *vedata, struct Object *ob);
+void GPENCIL_cache_finish(void *vedata);
+void GPENCIL_draw_scene(void *vedata);
+
+/* render */
+void GPENCIL_render_init(struct GPENCIL_Data *ved, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void GPENCIL_render_to_image(void *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect);
+
+/* Use of multisample framebuffers. */
+#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) { \
+ if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \
+ DRW_stats_query_start("GP Multisample Blit"); \
+ GPU_framebuffer_bind(fbl->multisample_fb); \
+ GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \
+ DRW_stats_query_end(); \
+ } \
+}
+
+#define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) { \
+ if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \
+ DRW_stats_query_start("GP Multisample Resolve"); \
+ GPU_framebuffer_bind(fb); \
+ DRW_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \
+ DRW_stats_query_end(); \
+ } \
+}
+
+#endif /* __GPENCIL_ENGINE_H__ */
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
new file mode 100644
index 00000000000..0b90de88ec1
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_render.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_render.c
+ * \ingroup draw
+ */
+#include "BLI_rect.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BKE_camera.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "draw_mode_engines.h"
+
+#include "RE_pipeline.h"
+
+#include "gpencil_engine.h"
+
+/* Get pixel size for render
+* This function uses the same calculation used for viewport, because if use
+* camera pixelsize, the result is not correct.
+*/
+static float get_render_pixelsize(float persmat[4][4], int winx, int winy)
+{
+ float v1[3], v2[3];
+ float len_px, len_sc;
+
+ v1[0] = persmat[0][0];
+ v1[1] = persmat[1][0];
+ v1[2] = persmat[2][0];
+
+ v2[0] = persmat[0][1];
+ v2[1] = persmat[1][1];
+ v2[2] = persmat[2][1];
+
+ len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
+ len_sc = (float)MAX2(winx, winy);
+
+ return len_px / len_sc;
+}
+
+/* init render data */
+void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_StorageList *stl = vedata->stl;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] };
+
+ /* In render mode the default framebuffer is not generated
+ * because there is no viewport. So we need to manually create one
+ * NOTE : use 32 bit format for precision in render mode.
+ */
+ /* create multiframe framebuffer for AA */
+ if (U.gpencil_multisamples > 0) {
+ int rect_w = (int)viewport_size[0];
+ int rect_h = (int)viewport_size[1];
+ DRW_gpencil_multisample_ensure(vedata, rect_w, rect_h);
+ }
+
+ vedata->render_depth_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH24_STENCIL8,
+ &draw_engine_gpencil_type);
+ vedata->render_color_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_RGBA32F,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->main, {
+ GPU_ATTACHMENT_TEXTURE(vedata->render_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(vedata->render_color_tx)
+ });
+
+ /* Alloc transient data. */
+ if (!stl->g_data) {
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
+ }
+
+ /* Set the pers & view matrix. */
+ struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+ float frame = BKE_scene_frame_get(scene);
+ RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat);
+ RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv);
+
+ invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv);
+ mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat);
+ invert_m4_m4(stl->storage->persinv, stl->storage->persmat);
+ invert_m4_m4(stl->storage->wininv, stl->storage->winmat);
+
+ DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV);
+
+ /* calculate pixel size for render */
+ stl->storage->render_pixsize = get_render_pixelsize(stl->storage->persmat, viewport_size[0], viewport_size[1]);
+ /* INIT CACHE */
+ GPENCIL_cache_init(vedata);
+}
+
+/* render all objects and select only grease pencil */
+static void GPENCIL_render_cache(
+ void *vedata, struct Object *ob,
+ struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
+{
+ if ((ob == NULL) || (DRW_check_object_visible_within_active_context(ob) == false)) {
+ return;
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ GPENCIL_cache_populate(vedata, ob);
+ }
+}
+
+/* TODO: Reuse Eevee code in shared module instead to duplicate here */
+static void GPENCIL_render_update_viewvecs(float invproj[4][4], float winmat[4][4], float(*r_viewvecs)[4])
+{
+ /* view vectors for the corners of the view frustum.
+ * Can be used to recreate the world space position easily */
+ float view_vecs[4][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 },
+ { -1.0f, -1.0f, 1.0f, 1.0f }
+ };
+
+ /* convert the view vectors to view space */
+ const bool is_persp = (winmat[3][3] == 0.0f);
+ for (int i = 0; i < 4; i++) {
+ mul_project_m4_v3(invproj, view_vecs[i]);
+ /* normalized trick see:
+ * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ if (is_persp) {
+ /* Divide XY by Z. */
+ mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
+ }
+ }
+
+ /**
+ * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
+ * view_vecs[1] is the vector going from the near-bottom-left corner to
+ * the far-top-right corner.
+ * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
+ * when Z = 1, and top-left corner if Z = 1.
+ * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
+ * distance from the near plane to the far clip plane.
+ **/
+ copy_v4_v4(r_viewvecs[0], view_vecs[0]);
+
+ /* we need to store the differences */
+ r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
+ r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
+ r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
+}
+
+/* Update view_vecs */
+static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata)
+{
+ GPENCIL_StorageList *stl = vedata->stl;
+
+ float invproj[4][4], winmat[4][4];
+ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
+
+ /* this is separated to keep function equal to Eevee for future reuse of same code */
+ GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs);
+}
+
+/* read z-depth render result */
+static void GPENCIL_render_result_z(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ GPENCIL_StorageList *stl = vedata->stl;
+
+ if ((view_layer->passflag & SCE_PASS_Z) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
+
+ GPU_framebuffer_read_depth(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), rp->rect);
+
+ bool is_persp = DRW_viewport_is_persp_get();
+
+ GPENCIL_render_update_vecs(vedata);
+
+ /* Convert ogl depth [0..1] to view Z [near..far] */
+ for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) {
+ if (rp->rect[i] == 1.0f) {
+ rp->rect[i] = 1e10f; /* Background */
+ }
+ else {
+ if (is_persp) {
+ rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
+ rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]);
+ }
+ else {
+ rp->rect[i] = -stl->storage->view_vecs[0][2] + rp->rect[i] * -stl->storage->view_vecs[1][2];
+ }
+ }
+ }
+ }
+}
+
+/* read combined render result */
+static void GPENCIL_render_result_combined(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect)
+{
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+
+ GPU_framebuffer_bind(fbl->main);
+ GPU_framebuffer_read_color(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 4, 0, rp->rect);
+}
+
+/* helper to blend pixels */
+static void blend_pixel(float src[4], float dst[4])
+{
+ float alpha = src[3];
+
+ /* use blend: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA */
+ dst[0] = (src[0] * alpha) + (dst[0] * (1.0f - alpha));
+ dst[1] = (src[1] * alpha) + (dst[1] * (1.0f - alpha));
+ dst[2] = (src[2] * alpha) + (dst[2] * (1.0f - alpha));
+}
+
+/* render grease pencil to image */
+void GPENCIL_render_to_image(void *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect)
+{
+ const char *viewname = RE_GetActiveRenderView(engine->re);
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ int imgsize = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
+
+ /* save previous render data */
+ RenderPass *rpass_color_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
+ RenderPass *rpass_depth_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
+ float *src_rect_color_data = NULL;
+ float *src_rect_depth_data = NULL;
+ if ((rpass_color_src) && (rpass_depth_src) && (rpass_color_src->rect) && (rpass_depth_src->rect)) {
+ src_rect_color_data = MEM_dupallocN(rpass_color_src->rect);
+ src_rect_depth_data = MEM_dupallocN(rpass_depth_src->rect);
+ }
+ else {
+ /* TODO: put this message in a better place */
+ printf("Warning: To render grease pencil, enable Combined and Z passes.\n");
+ }
+
+ GPENCIL_engine_init(vedata);
+ GPENCIL_render_init(vedata, engine, draw_ctx->depsgraph);
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Object *camera = DEG_get_evaluated_object(draw_ctx->depsgraph, RE_GetCamera(engine->re));
+ stl->storage->camera = camera; /* save current camera */
+
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ if (fbl->main) {
+ GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx, 0, 0);
+ GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx, 0, 0);
+ /* clean first time the buffer */
+ float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ GPU_framebuffer_bind(fbl->main);
+ GPU_framebuffer_clear_color_depth(fbl->main, clearcol, 1.0f);
+ }
+
+ /* loop all objects and draw */
+ DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache);
+
+ GPENCIL_cache_finish(vedata);
+ GPENCIL_draw_scene(vedata);
+
+ /* combined data */
+ GPENCIL_render_result_combined(render_layer, viewname, vedata, rect);
+ /* z-depth data */
+ GPENCIL_render_result_z(render_layer, viewname, vedata, rect);
+
+ /* detach textures */
+ if (fbl->main) {
+ GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx);
+ GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx);
+ }
+
+ /* merge previous render image with new GP image */
+ if (src_rect_color_data) {
+ RenderPass *rpass_color_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
+ RenderPass *rpass_depth_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
+ float *gp_rect_color_data = rpass_color_gp->rect;
+ float *gp_rect_depth_data = rpass_depth_gp->rect;
+ float *gp_pixel_rgba;
+ float *gp_pixel_depth;
+ float *src_pixel_rgba;
+ float *src_pixel_depth;
+ float tmp[4];
+
+ for (int i = 0; i < imgsize; i++) {
+ gp_pixel_rgba = &gp_rect_color_data[i * 4];
+ gp_pixel_depth = &gp_rect_depth_data[i];
+
+ src_pixel_rgba = &src_rect_color_data[i * 4];
+ src_pixel_depth = &src_rect_depth_data[i];
+
+ /* check grease pencil render transparency */
+ if (gp_pixel_rgba[3] > 0.0f) {
+ copy_v4_v4(tmp, gp_pixel_rgba);
+ if (src_pixel_rgba[3] > 0.0f) {
+ /* copy source color on back */
+ copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
+ /* check z-depth */
+ if (gp_pixel_depth[0] > src_pixel_depth[0]) {
+ /* copy source z-depth */
+ gp_pixel_depth[0] = src_pixel_depth[0];
+ /* blend gp render */
+ blend_pixel(tmp, gp_pixel_rgba);
+ /* blend object on top */
+ blend_pixel(src_pixel_rgba, gp_pixel_rgba);
+ }
+ else {
+ /* blend gp render */
+ blend_pixel(tmp, gp_pixel_rgba);
+ }
+ }
+ }
+ else {
+ copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
+ gp_pixel_depth[0] = src_pixel_depth[0];
+ }
+ }
+
+ /* free memory */
+ MEM_SAFE_FREE(src_rect_color_data);
+ MEM_SAFE_FREE(src_rect_depth_data);
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
new file mode 100644
index 00000000000..827f2e9344b
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright 2017, 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): Antonio Vazquez
+ *
+ */
+
+/** \file blender/draw/engines/gpencil/gpencil_shader_fx.c
+ * \ingroup draw
+ */
+#include "DNA_gpencil_types.h"
+#include "DNA_shader_fx_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_camera_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_shader_fx.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BKE_camera.h"
+
+#include "ED_view3d.h"
+#include "ED_gpencil.h"
+
+#include "gpencil_engine.h"
+
+extern char datatoc_gpencil_fx_blur_frag_glsl[];
+extern char datatoc_gpencil_fx_colorize_frag_glsl[];
+extern char datatoc_gpencil_fx_flip_frag_glsl[];
+extern char datatoc_gpencil_fx_light_frag_glsl[];
+extern char datatoc_gpencil_fx_pixel_frag_glsl[];
+extern char datatoc_gpencil_fx_rim_prepare_frag_glsl[];
+extern char datatoc_gpencil_fx_rim_resolve_frag_glsl[];
+extern char datatoc_gpencil_fx_swirl_frag_glsl[];
+extern char datatoc_gpencil_fx_wave_frag_glsl[];
+
+/* verify if this fx is active */
+static bool effect_is_active(Object *ob, ShaderFxData *fx, bool is_render)
+{
+ if (fx == NULL) {
+ return false;
+ }
+
+ bGPdata *gpd = ob->data;
+ if (gpd == NULL) {
+ return false;
+ }
+
+ bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
+ if (((fx->mode & eShaderFxMode_Editmode) == 0) && (is_edit)) {
+ return false;
+ }
+
+ if (((fx->mode & eShaderFxMode_Realtime) && (is_render == false)) ||
+ ((fx->mode & eShaderFxMode_Render) && (is_render == true)))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+/* get normal of draw using one stroke of visible layer
+* /param gpd GP datablock
+* /param r_point Point on plane
+* /param r_normal Normal vector
+*/
+static bool get_normal_vector(bGPdata *gpd, float r_point[3], float r_normal[3])
+{
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* get frame */
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL)
+ continue;
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->totpoints >= 3) {
+ bGPDspoint *pt = &gps->points[0];
+ BKE_gpencil_stroke_normal(gps, r_normal);
+ /* in some weird situations, the normal cannot be calculated, so try next stroke */
+ if ((r_normal[0] != 0.0f) || (r_normal[1] != 0.0f) || (r_normal[2] != 0.0f)) {
+ copy_v3_v3(r_point, &pt->x);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/* helper to get near and far depth of field values */
+static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2])
+{
+ if (camera == NULL) {
+ return;
+ }
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ Camera *cam = (Camera *)camera->data;
+
+ float fstop = cam->gpu_dof.fstop;
+ float focus_dist = BKE_camera_object_dof_distance(camera);
+ float focal_len = cam->lens;
+
+ /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
+ * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
+ * because the shader reads coordinates in world space, which is in blender units.
+ * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
+ float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f;
+ float scale_camera = 0.001f / scale;
+ /* we want radius here for the aperture number */
+ float aperture_scaled = 0.5f * scale_camera * focal_len / fstop;
+ float focal_len_scaled = scale_camera * focal_len;
+
+ float hyperfocal = (focal_len_scaled * focal_len_scaled) / (aperture_scaled * coc);
+ nearfar[0] = (hyperfocal * focus_dist) / (hyperfocal + focal_len);
+ nearfar[1] = (hyperfocal * focus_dist) / (hyperfocal - focal_len);
+}
+
+/* **************** Shader Effects ***************************** */
+
+/* Gaussian Blur FX
+ * The effect is done using two shading groups because is faster to apply horizontal
+ * and vertical in different operations.
+ */
+static void DRW_gpencil_fx_blur(
+ ShaderFxData *fx, int ob_idx, GPENCIL_e_data *e_data,
+ GPENCIL_Data *vedata, tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+
+ BlurShaderFxData *fxd = (BlurShaderFxData *)fx;
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ DRWShadingGroup *fx_shgrp;
+
+ Object *ob = cache->ob;
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ fxd->blur[0] = fxd->radius[0];
+ fxd->blur[1] = fxd->radius[1];
+
+ /* init weight */
+ if (fxd->flag & FX_BLUR_DOF_MODE) {
+ /* viewport and opengl render */
+ Object *camera = NULL;
+ if (rv3d) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ camera = v3d->camera;
+ }
+ }
+ else {
+ camera = stl->storage->camera;
+ }
+
+ if (camera) {
+ float nearfar[2];
+ GPENCIL_dof_nearfar(camera, fxd->coc, nearfar);
+ float zdepth = stl->g_data->gp_object_cache[ob_idx].zdepth;
+ /* the object is on focus area */
+ if ((zdepth >= nearfar[0]) && (zdepth <= nearfar[1])) {
+ fxd->blur[0] = 0;
+ fxd->blur[1] = 0;
+ }
+ else {
+ float f;
+ if (zdepth < nearfar[0]) {
+ f = nearfar[0] - zdepth;
+ }
+ else {
+ f = zdepth - nearfar[1];
+ }
+ fxd->blur[0] = f;
+ fxd->blur[1] = f;
+ CLAMP2(&fxd->blur[0], 0, fxd->radius[0]);
+ }
+ }
+ else {
+ /* if not camera view, the blur is disabled */
+ fxd->blur[0] = 0;
+ fxd->blur[1] = 0;
+ }
+ }
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_blur_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
+
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Colorize FX */
+static void DRW_gpencil_fx_colorize(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
+{
+ if (fx == NULL) {
+ return;
+ }
+ ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1);
+ DRW_shgroup_uniform_vec4(fx_shgrp, "high_color", &fxd->high_color[0], 1);
+ DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "factor", &fxd->factor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Flip FX */
+static void DRW_gpencil_fx_flip(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
+{
+ if (fx == NULL) {
+ return;
+ }
+ FlipShaderFxData *fxd = (FlipShaderFxData *)fx;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+
+ fxd->flipmode = 100;
+ /* the number works as bit flag */
+ if (fxd->flag & FX_FLIP_HORIZONTAL) {
+ fxd->flipmode += 10;
+ }
+ if (fxd->flag & FX_FLIP_VERTICAL) {
+ fxd->flipmode += 1;
+ }
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1);
+
+ DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Light FX */
+static void DRW_gpencil_fx_light(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
+ tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+ Object *ob = cache->ob;
+ LightShaderFxData *fxd = (LightShaderFxData *)fx;
+
+ if (fxd->object == NULL) {
+ return;
+ }
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+
+ DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
+
+ /* location of the light using obj location as origin */
+ copy_v3_v3(fxd->loc, &fxd->object->loc[0]);
+
+ /* Calc distance to strokes plane
+ * The w component of location is used to transfer the distance to drawing plane
+ */
+ float r_point[3], r_normal[3];
+ float r_plane[4];
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (!get_normal_vector(gpd, r_point, r_normal)) {
+ return;
+ }
+ mul_mat3_m4_v3(ob->obmat, r_normal); /* only rotation component */
+ plane_from_point_normal_v3(r_plane, r_point, r_normal);
+ float dt = dist_to_plane_v3(fxd->object->loc, r_plane);
+ fxd->loc[3] = dt; /* use last element to save it */
+
+ DRW_shgroup_uniform_vec4(fx_shgrp, "loc", &fxd->loc[0], 1);
+
+ DRW_shgroup_uniform_float(fx_shgrp, "energy", &fxd->energy, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "ambient", &fxd->ambient, 1);
+
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Pixelate FX */
+static void DRW_gpencil_fx_pixel(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
+ tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+ Object *ob = cache->ob;
+ PixelShaderFxData *fxd = (PixelShaderFxData *)fx;
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3);
+ DRW_shgroup_uniform_vec4(fx_shgrp, "color", &fxd->rgba[0], 1);
+
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Rim FX */
+static void DRW_gpencil_fx_rim(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
+ tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+ Object *ob = cache->ob;
+ RimShaderFxData *fxd = (RimShaderFxData *)fx;
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ /* prepare pass */
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_rim_prepare_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
+
+ DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2);
+ DRW_shgroup_uniform_vec3(fx_shgrp, "rim_color", &fxd->rim_rgb[0], 1);
+ DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1);
+
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+
+ /* blur pass */
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_blur_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_rim);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_rim);
+ DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
+
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh_b = fx_shgrp;
+
+ /* resolve pass */
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_rim_resolve_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_rim);
+ DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1);
+ DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
+
+ fxd->runtime.fx_sh_c = fx_shgrp;
+}
+
+/* Swirl FX */
+static void DRW_gpencil_fx_swirl(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
+ tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+ Object *ob = cache->ob;
+ SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
+ if (fxd->object == NULL) {
+ return;
+ }
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+
+ DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
+
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &fxd->object->loc[0], 1);
+
+ DRW_shgroup_uniform_int(fx_shgrp, "radius", &fxd->radius, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "angle", &fxd->angle, 1);
+ DRW_shgroup_uniform_int(fx_shgrp, "transparent", &fxd->transparent, 1);
+
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* Wave Distorsion FX */
+static void DRW_gpencil_fx_wave(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
+{
+ if (fx == NULL) {
+ return;
+ }
+
+ WaveShaderFxData *fxd = (WaveShaderFxData *)fx;
+
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+
+ DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1);
+ DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1);
+ DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+}
+
+/* ************************************************************** */
+
+/* create all FX shaders */
+void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data)
+{
+ /* fx shaders (all in screen space) */
+ if (!e_data->gpencil_fx_blur_sh) {
+ e_data->gpencil_fx_blur_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_blur_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_colorize_sh) {
+ e_data->gpencil_fx_colorize_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_colorize_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_flip_sh) {
+ e_data->gpencil_fx_flip_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_flip_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_light_sh) {
+ e_data->gpencil_fx_light_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_light_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_pixel_sh) {
+ e_data->gpencil_fx_pixel_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_pixel_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_rim_prepare_sh) {
+ e_data->gpencil_fx_rim_prepare_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_rim_prepare_frag_glsl, NULL);
+
+ e_data->gpencil_fx_rim_resolve_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_rim_resolve_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_swirl_sh) {
+ e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_swirl_frag_glsl, NULL);
+ }
+ if (!e_data->gpencil_fx_wave_sh) {
+ e_data->gpencil_fx_wave_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_wave_frag_glsl, NULL);
+ }
+}
+
+/* free FX shaders */
+void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data)
+{
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_blur_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_colorize_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_flip_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_light_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_pixel_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_prepare_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh);
+}
+
+/* create all passes used by FX */
+void GPENCIL_create_fx_passes(GPENCIL_PassList *psl)
+{
+ psl->fx_shader_pass = DRW_pass_create(
+ "GPencil Shader FX Pass",
+ DRW_STATE_WRITE_COLOR |
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ psl->fx_shader_pass_blend = DRW_pass_create(
+ "GPencil Shader FX Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND |
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+}
+
+
+/* prepare fx shading groups */
+void DRW_gpencil_fx_prepare(
+ struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata,
+ struct tGPencilObjectCache *cache)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Object *ob = cache->ob;
+ int ob_idx = cache->idx;
+
+ if (ob->shader_fx.first == NULL) {
+ return;
+ }
+ /* loop FX */
+ for (ShaderFxData *fx = ob->shader_fx.first; fx; fx = fx->next) {
+ if (effect_is_active(ob, fx, stl->storage->is_render)) {
+ switch (fx->type) {
+ case eShaderFxType_Blur:
+ DRW_gpencil_fx_blur(fx, ob_idx, e_data, vedata, cache);
+ break;
+ case eShaderFxType_Colorize:
+ DRW_gpencil_fx_colorize(fx, e_data, vedata);
+ break;
+ case eShaderFxType_Flip:
+ DRW_gpencil_fx_flip(fx, e_data, vedata);
+ break;
+ case eShaderFxType_Light:
+ DRW_gpencil_fx_light(fx, e_data, vedata, cache);
+ break;
+ case eShaderFxType_Pixel:
+ DRW_gpencil_fx_pixel(fx, e_data, vedata, cache);
+ break;
+ case eShaderFxType_Rim:
+ DRW_gpencil_fx_rim(fx, e_data, vedata, cache);
+ break;
+ case eShaderFxType_Swirl:
+ DRW_gpencil_fx_swirl(fx, e_data, vedata, cache);
+ break;
+ case eShaderFxType_Wave:
+ DRW_gpencil_fx_wave(fx, e_data, vedata);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+}
+
+/* helper to draw one FX pass and do ping-pong copy */
+static void gpencil_draw_fx_pass(
+ GPENCIL_e_data *e_data,
+ GPENCIL_PassList *psl,
+ GPENCIL_FramebufferList *fbl,
+ DRWShadingGroup *shgrp, bool blend)
+{
+ if (shgrp == NULL) {
+ return;
+ }
+
+ static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ GPU_framebuffer_bind(fbl->temp_fb_b);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+
+ /* draw effect pass in temp texture (B) using as source the previous image
+ * existing in the other temp texture (A) */
+ if (!blend) {
+ DRW_draw_pass_subset(psl->fx_shader_pass, shgrp, shgrp);
+ }
+ else {
+ DRW_draw_pass_subset(psl->fx_shader_pass_blend, shgrp, shgrp);
+ }
+
+ /* copy pass from b to a for ping-pong frame buffers */
+ e_data->input_depth_tx = e_data->temp_depth_tx_b;
+ e_data->input_color_tx = e_data->temp_color_tx_b;
+
+ GPU_framebuffer_bind(fbl->temp_fb_a);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
+ DRW_draw_pass(psl->mix_pass_noblend);
+}
+
+/* helper to manage gaussian blur passes */
+static void draw_gpencil_blur_passes(
+ struct GPENCIL_e_data *e_data,
+ struct GPENCIL_Data *vedata,
+ struct BlurShaderFxData *fxd)
+{
+ if (fxd->runtime.fx_sh == NULL) {
+ return;
+ }
+
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ DRWShadingGroup *shgrp = fxd->runtime.fx_sh;
+ int samples = fxd->samples;
+
+ float bx = fxd->blur[0];
+ float by = fxd->blur[1];
+
+ /* the blur is done in two steps (Hor/Ver) because is faster and
+ * gets better result
+ *
+ * samples could be 0 and disable de blur effects because sometimes
+ * is easier animate the number of samples only, instead to animate the
+ * hide/unhide and the number of samples to make some effects.
+ */
+ for (int b = 0; b < samples; b++) {
+ /* horizontal */
+ if (bx > 0) {
+ fxd->blur[0] = bx;
+ fxd->blur[1] = 0;
+ gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true);
+ }
+ /* vertical */
+ if (by > 0) {
+ fxd->blur[0] = 0;
+ fxd->blur[1] = by;
+ gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true);
+ }
+ }
+}
+
+static void draw_gpencil_rim_blur(
+ struct GPENCIL_e_data *UNUSED(e_data),
+ struct GPENCIL_Data *vedata,
+ struct RimShaderFxData *fxd)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ GPU_framebuffer_bind(fbl->temp_fb_b);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+ DRW_draw_pass_subset(psl->fx_shader_pass_blend,
+ fxd->runtime.fx_sh_b, fxd->runtime.fx_sh_b);
+
+ /* copy pass from b for ping-pong frame buffers */
+ GPU_framebuffer_bind(fbl->temp_fb_rim);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_rim, clearcol, 1.0f);
+ DRW_draw_pass(psl->mix_pass_noblend);
+}
+
+/* helper to draw RIM passes */
+static void draw_gpencil_rim_passes(
+ struct GPENCIL_e_data *e_data,
+ struct GPENCIL_Data *vedata,
+ struct RimShaderFxData *fxd)
+{
+ if (fxd->runtime.fx_sh_b == NULL) {
+ return;
+ }
+
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+
+ static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ int bx = fxd->blur[0];
+ int by = fxd->blur[1];
+
+ /* prepare mask */
+ GPU_framebuffer_bind(fbl->temp_fb_rim);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_rim, clearcol, 1.0f);
+ DRW_draw_pass_subset(
+ psl->fx_shader_pass_blend,
+ fxd->runtime.fx_sh, fxd->runtime.fx_sh);
+
+ /* blur rim */
+ e_data->input_depth_tx = e_data->temp_depth_tx_b;
+ e_data->input_color_tx = e_data->temp_color_tx_b;
+
+ if ((fxd->samples > 0) && ((bx > 0) || (by > 0))) {
+ for (int x = 0; x < fxd->samples; x++) {
+
+ /* horizontal */
+ fxd->blur[0] = bx;
+ fxd->blur[1] = 0;
+ draw_gpencil_rim_blur(e_data, vedata, fxd);
+
+ /* Vertical */
+ fxd->blur[0] = 0;
+ fxd->blur[1] = by;
+ draw_gpencil_rim_blur(e_data, vedata, fxd);
+
+ fxd->blur[0] = bx;
+ fxd->blur[1] = by;
+ }
+ }
+ /* resolve */
+ GPU_framebuffer_bind(fbl->temp_fb_b);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+ DRW_draw_pass_subset(
+ psl->fx_shader_pass_blend,
+ fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c);
+
+ /* copy pass from b to a for ping-pong frame buffers */
+ e_data->input_depth_tx = e_data->temp_depth_tx_b;
+ e_data->input_color_tx = e_data->temp_color_tx_b;
+
+ GPU_framebuffer_bind(fbl->temp_fb_a);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
+ DRW_draw_pass(psl->mix_pass_noblend);
+}
+
+/* apply all object fx effects */
+void DRW_gpencil_fx_draw(
+ struct GPENCIL_e_data *e_data,
+ struct GPENCIL_Data *vedata, struct tGPencilObjectCache *cache)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+ Object *ob = cache->ob;
+
+ /* loop FX modifiers */
+ for (ShaderFxData *fx = ob->shader_fx.first; fx; fx = fx->next) {
+ if (effect_is_active(ob, fx, stl->storage->is_render)) {
+ switch (fx->type) {
+ case eShaderFxType_Blur:
+ {
+ BlurShaderFxData *fxd = (BlurShaderFxData *)fx;
+ draw_gpencil_blur_passes(e_data, vedata, fxd);
+ break;
+ }
+ case eShaderFxType_Colorize:
+ {
+ ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ case eShaderFxType_Flip:
+ {
+ FlipShaderFxData *fxd = (FlipShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ case eShaderFxType_Light:
+ {
+ LightShaderFxData *fxd = (LightShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ case eShaderFxType_Pixel:
+ {
+ PixelShaderFxData *fxd = (PixelShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ case eShaderFxType_Rim:
+ {
+ RimShaderFxData *fxd = (RimShaderFxData *)fx;
+ draw_gpencil_rim_passes(e_data, vedata, fxd);
+ break;
+ }
+ case eShaderFxType_Swirl:
+ {
+ SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ case eShaderFxType_Wave:
+ {
+ WaveShaderFxData *fxd = (WaveShaderFxData *)fx;
+ gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl
new file mode 100644
index 00000000000..1bf1d025430
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl
@@ -0,0 +1,60 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+uniform int blur[2];
+
+uniform vec3 loc;
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+vec2 noffset = vec2(blur[0], blur[1]);
+
+out vec4 FragColor;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+
+ float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize);
+ float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize);
+
+ /* apply blurring, using a 9-tap filter with predefined gaussian weights */
+ /* depth */
+ float outdepth = 0;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x - 1.0 * dx, uv.y + 1.0 * dy), 0).r * 0.0947416;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x - 0.0 * dx, uv.y + 1.0 * dy), 0).r * 0.118318;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x + 1.0 * dx, uv.y + 1.0 * dy), 0).r * 0.0947416;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x - 1.0 * dx, uv.y + 0.0 * dy), 0).r * 0.118318;
+
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x, uv.y), 0).r * 0.147761;
+
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x + 1.0 * dx, uv.y + 0.0 * dy), 0).r * 0.118318;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x - 1.0 * dx, uv.y - 1.0 * dy), 0).r * 0.0947416;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x + 0.0 * dx, uv.y - 1.0 * dy), 0).r * 0.118318;
+ outdepth += texelFetch(strokeDepth, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0).r * 0.0947416;
+
+ gl_FragDepth = outdepth;
+
+ /* color */
+ vec4 outcolor = vec4(0.0);
+ outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x - 0.0 * dx, uv.y + 1.0 * dy), 0) * 0.118318;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318;
+
+ outcolor += texelFetch(strokeColor, ivec2(uv.x, uv.y), 0) * 0.147761;
+
+ outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x + 0.0 * dx, uv.y - 1.0 * dy), 0) * 0.118318;
+ outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416;
+
+ FragColor = clamp(outcolor, 0, 1.0);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl
new file mode 100644
index 00000000000..33b249ac09b
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl
@@ -0,0 +1,86 @@
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+uniform vec4 low_color;
+uniform vec4 high_color;
+uniform int mode;
+uniform float factor;
+
+out vec4 FragColor;
+
+#define MODE_GRAYSCALE 0
+#define MODE_SEPIA 1
+#define MODE_BITONE 2
+#define MODE_CUSTOM 3
+#define MODE_TRANSPARENT 4
+
+float get_luminance(vec4 color)
+{
+ float lum = (color.r * 0.2126) + (color.g * 0.7152) + (color.b * 0.723);
+ return lum;
+}
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
+ vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0);
+ float luminance = get_luminance(src_pixel);
+ vec4 outcolor;
+
+ /* is transparent */
+ if (src_pixel.a == 0.0f) {
+ discard;
+ }
+
+ switch(mode) {
+ case MODE_GRAYSCALE:
+ {
+ outcolor = vec4(luminance, luminance, luminance, src_pixel.a);
+ break;
+ }
+ case MODE_SEPIA:
+ {
+ float Red = (src_pixel.r * 0.393) + (src_pixel.g * 0.769) + (src_pixel.b * 0.189);
+ float Green = (src_pixel.r * 0.349) + (src_pixel.g * 0.686) + (src_pixel.b * 0.168);
+ float Blue = (src_pixel.r * 0.272) + (src_pixel.g * 0.534) + (src_pixel.b * 0.131);
+ outcolor = vec4(Red, Green, Blue, src_pixel.a);
+ break;
+ }
+ case MODE_BITONE:
+ {
+ if (luminance <= factor) {
+ outcolor = low_color;
+ }
+ else {
+ outcolor = high_color;
+ }
+ break;
+ }
+ case MODE_CUSTOM:
+ {
+ /* if below umbral, force custom color */
+ if (luminance <= factor) {
+ outcolor = low_color;
+ }
+ else {
+ outcolor = vec4(luminance * low_color.r, luminance * low_color.b, luminance * low_color.b, src_pixel.a);
+ }
+ break;
+ }
+ case MODE_TRANSPARENT:
+ {
+ outcolor = vec4(src_pixel.rgb, src_pixel.a * factor);
+ break;
+ }
+ default:
+ {
+ outcolor = src_pixel;
+ }
+
+ }
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl
new file mode 100644
index 00000000000..43589461cd1
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl
@@ -0,0 +1,37 @@
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform vec2 wsize;
+uniform int flipmode;
+
+void main()
+{
+ vec2 mode = vec2(0,0);
+ /* horz. */
+ if (flipmode >= 110) {
+ mode[0] = 1;
+ }
+ /* vert. */
+ if ((flipmode == 101) || (flipmode == 111)) {
+ mode[1] = 1;
+ }
+
+ vec2 uv = vec2(gl_FragCoord.xy);
+ float stroke_depth;
+ vec4 outcolor;
+
+ if (mode[0] > 0) {
+ uv.x = wsize.x - uv.x;
+ }
+ if (mode[1] > 0) {
+ uv.y = wsize.y - uv.y;
+ }
+
+ ivec2 iuv = ivec2(uv.x, uv.y);
+ stroke_depth = texelFetch(strokeDepth, iuv, 0).r;
+ outcolor = texelFetch(strokeColor, iuv, 0);
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl
new file mode 100644
index 00000000000..6dcd0499baf
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl
@@ -0,0 +1,70 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform vec2 Viewport;
+uniform vec4 loc;
+uniform float energy;
+uniform float ambient;
+
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+out vec4 FragColor;
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+
+#define height loc.w
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ /* need to calculate ndc because this is not done by vertex shader */
+ vec3 ndc = vec3(vertex).xyz / vertex.w;
+
+ vec2 sc;
+ sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
+ sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
+
+ return sc;
+}
+
+void main()
+{
+ float stroke_depth;
+ vec4 objcolor;
+
+ vec4 light_loc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+ vec2 light2d = toScreenSpace(light_loc);
+
+ /* calc pixel scale */
+ float pxscale = (ProjectionMatrix[3][3] == 0.0) ? (10.0 / (light_loc.z * defaultpixsize)) : (10.0 / defaultpixsize);
+ pxscale = max(pxscale, 0.000001);
+
+ /* the height over plane is received in the w component of the loc
+ * and needs a factor to adapt to pixels
+ */
+ float peak = height * 10.0 * pxscale;
+ vec3 light3d = vec3(light2d.x, light2d.y, peak);
+
+ vec2 uv = vec2(gl_FragCoord.xy);
+ vec3 frag_loc = vec3(uv.x, uv.y, 0);
+ vec3 norm = vec3(0, 0, 1.0); /* always z-up */
+
+ ivec2 iuv = ivec2(uv.x, uv.y);
+ stroke_depth = texelFetch(strokeDepth, iuv, 0).r;
+ objcolor = texelFetch(strokeColor, iuv, 0);
+
+ /* diffuse light */
+ vec3 lightdir = normalize(light3d - frag_loc);
+ float diff = max(dot(norm, lightdir), 0.0);
+ float dist = length(light3d - frag_loc) / pxscale;
+ float factor = diff * ((energy * 100.0) / (dist * dist));
+
+ vec3 result = factor * max(ambient, 0.1) * vec3(objcolor);
+
+ gl_FragDepth = stroke_depth;
+ FragColor = vec4(result.r, result.g, result.b, objcolor.a);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl
new file mode 100644
index 00000000000..0b25dbbd012
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl
@@ -0,0 +1,50 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+uniform int size[3];
+uniform vec4 color;
+
+uniform vec3 loc;
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+out vec4 FragColor;
+
+int uselines = size[2];
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+vec2 nsize = max(vec2(size[0], size[1]), 3.0);
+
+/* This pixelation shader is a modified version of original Geeks3d.com code */
+void main()
+{
+ vec2 uv = vec2(gl_FragCoord.xy);
+ vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+
+ float dx = (ProjectionMatrix[3][3] == 0.0) ? (nsize[0] / (nloc.z * defaultpixsize)) : (nsize[0] / defaultpixsize);
+ float dy = (ProjectionMatrix[3][3] == 0.0) ? (nsize[1] / (nloc.z * defaultpixsize)) : (nsize[1] / defaultpixsize);
+
+ dx = max(abs(dx), 3.0);
+ dy = max(abs(dy), 3.0);
+
+ vec2 coord = vec2(dx * floor(uv.x / dx), dy * floor(uv.y / dy));
+
+ float stroke_depth = texelFetch(strokeDepth, ivec2(coord), 0).r;
+ vec4 outcolor = texelFetch(strokeColor, ivec2(coord), 0);
+
+ if (uselines == 1) {
+ float difx = uv.x - (floor(uv.x / nsize[0]) * nsize[0]);
+ if ((difx == 0.5) && (outcolor.a > 0)) {
+ outcolor = color;
+ }
+ float dify = uv.y - (floor(uv.y / nsize[1]) * nsize[1]);
+ if ((dify == 0.5) && (outcolor.a > 0)) {
+ outcolor = color;
+ }
+ }
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl
new file mode 100644
index 00000000000..6ea4faf11fd
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl
@@ -0,0 +1,64 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+/* ******************************************************************* */
+/* create rim and mask */
+/* ******************************************************************* */
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform vec2 Viewport;
+
+uniform int offset[2];
+uniform vec3 rim_color;
+uniform vec3 mask_color;
+
+uniform vec3 loc;
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+vec2 noffset = vec2(offset[0], offset[1]);
+
+out vec4 FragColor;
+
+void main()
+{
+ vec2 uv = vec2(gl_FragCoord.xy);
+ vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+
+ float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize);
+ float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize);
+
+ float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r;
+ vec4 src_pixel= texelFetch(strokeColor, ivec2(uv.xy), 0);
+ vec4 offset_pixel= texelFetch(strokeColor, ivec2(uv.x - dx, uv.y - dy), 0);
+ vec4 outcolor;
+
+ /* is transparent */
+ if (src_pixel.a == 0.0f) {
+ discard;
+ }
+ /* check inside viewport */
+ else if ((uv.x - dx < 0) || (uv.x - dx > Viewport[0])) {
+ discard;
+ }
+ else if ((uv.y - dy < 0) || (uv.y - dy > Viewport[1])) {
+ discard;
+ }
+ /* pixel is equal to mask color, keep */
+ else if (src_pixel.rgb == mask_color.rgb) {
+ discard;
+ }
+ else {
+ if ((src_pixel.a > 0) && (offset_pixel.a > 0)) {
+ discard;
+ }
+ else {
+ outcolor = vec4(rim_color, 1.0);
+ }
+ }
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl
new file mode 100644
index 00000000000..0a7eb65d564
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl
@@ -0,0 +1,98 @@
+/* ******************************************************************* */
+/* Resolve RIM pass and add blur if needed */
+/* ******************************************************************* */
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform sampler2D strokeRim;
+
+uniform vec3 mask_color;
+uniform int mode;
+
+out vec4 FragColor;
+
+#define MODE_NORMAL 0
+#define MODE_OVERLAY 1
+#define MODE_ADD 2
+#define MODE_SUB 3
+#define MODE_MULTIPLY 4
+#define MODE_DIVIDE 5
+
+float overlay_color(float a, float b)
+{
+ float rtn;
+ if (a < 0.5) {
+ rtn = 2.0 * a * b;
+ }
+ else {
+ rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
+ }
+
+ return rtn;
+}
+
+vec4 get_blend_color(int mode, vec4 src_color, vec4 mix_color)
+{
+ vec4 outcolor;
+ if (mode == MODE_NORMAL) {
+ outcolor = mix_color;
+ }
+ else if (mode == MODE_OVERLAY) {
+ outcolor.r = overlay_color(src_color.r, mix_color.r);
+ outcolor.g = overlay_color(src_color.g, mix_color.g);
+ outcolor.b = overlay_color(src_color.b, mix_color.b);
+ }
+ else if (mode == MODE_ADD){
+ outcolor = src_color + mix_color;
+ }
+ else if (mode == MODE_SUB){
+ outcolor = src_color - mix_color;
+ }
+ else if (mode == MODE_MULTIPLY) {
+ outcolor = src_color * mix_color;
+ }
+ else if (mode == MODE_DIVIDE) {
+ outcolor = src_color / mix_color;
+ }
+ else {
+ outcolor = mix_color;
+ }
+
+ /* use always the alpha of source color */
+
+ outcolor.a = src_color.a;
+ /* use alpha to calculate the weight of the mixed color */
+ outcolor = mix(src_color, outcolor, mix_color.a);
+
+ return outcolor;
+}
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
+ vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0);
+ vec4 rim_pixel= texelFetch(strokeRim, uv.xy, 0);
+
+ vec4 outcolor = src_pixel;
+
+ /* is transparent */
+ if (src_pixel.a == 0.0f) {
+ discard;
+ }
+ /* pixel is equal to mask color, keep */
+ else if (src_pixel.rgb == mask_color.rgb) {
+ outcolor = src_pixel;
+ }
+ else {
+ if (rim_pixel.a == 0.0f) {
+ outcolor = src_pixel;
+ }
+ else {
+ outcolor = get_blend_color(mode, src_pixel, rim_pixel);
+ }
+ }
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl
new file mode 100644
index 00000000000..78aacafdcb7
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl
@@ -0,0 +1,70 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+uniform vec2 Viewport;
+uniform vec3 loc;
+uniform int radius;
+uniform float angle;
+uniform int transparent;
+
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+out vec4 FragColor;
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ /* need to calculate ndc because this is not done by vertex shader */
+ vec3 ndc = vec3(vertex).xyz / vertex.w;
+
+ vec2 sc;
+ sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
+ sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
+
+ return sc;
+}
+
+/* This swirl shader is a modified version of original Geeks3d.com code */
+void main()
+{
+ vec2 uv = vec2(gl_FragCoord.xy);
+ float stroke_depth;
+ vec4 outcolor;
+
+ vec4 center3d = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+ vec2 center = toScreenSpace(center3d);
+ vec2 tc = uv - center;
+
+ float dist = length(tc);
+ float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / (loc.z * defaultpixsize)) : (radius / defaultpixsize);
+ pxradius = max(pxradius, 1);
+
+ if (dist <= pxradius) {
+ float percent = (pxradius - dist) / pxradius;
+ float theta = percent * percent * angle * 8.0;
+ float s = sin(theta);
+ float c = cos(theta);
+ tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c)));
+ tc += center;
+
+ stroke_depth = texelFetch(strokeDepth, ivec2(tc), 0).r;
+ outcolor = texelFetch(strokeColor, ivec2(tc), 0);
+ }
+ else {
+ if (transparent == 1) {
+ discard;
+ }
+ stroke_depth = texelFetch(strokeDepth, ivec2(uv), 0).r;
+ outcolor = texelFetch(strokeColor, ivec2(uv), 0);
+ }
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl
new file mode 100644
index 00000000000..882b2cf59f1
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl
@@ -0,0 +1,40 @@
+
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+uniform float amplitude;
+uniform float period;
+uniform float phase;
+uniform int orientation;
+uniform vec2 wsize;
+
+#define M_PI 3.1415926535897932384626433832795
+
+#define HORIZONTAL 0
+#define VERTICAL 1
+
+void main()
+{
+ vec4 outcolor;
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float stroke_depth;
+
+ float value;
+ if (orientation == HORIZONTAL) {
+ float pval = (uv.x * M_PI) / wsize[0];
+ value = amplitude * sin((period * pval) + phase);
+ outcolor = texelFetch(strokeColor, ivec2(uv.x, uv.y + value), 0);
+ stroke_depth = texelFetch(strokeDepth, ivec2(uv.x, uv.y + value), 0).r;
+ }
+ else {
+ float pval = (uv.y * M_PI) / wsize[1];
+ value = amplitude * sin((period * pval) + phase);
+ outcolor = texelFetch(strokeColor, ivec2(uv.x + value, uv.y), 0);
+ stroke_depth = texelFetch(strokeDepth, ivec2(uv.x + value, uv.y), 0).r;
+ }
+
+ FragColor = outcolor;
+ gl_FragDepth = stroke_depth;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl
new file mode 100644
index 00000000000..cbd7a461dd3
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl
@@ -0,0 +1,12 @@
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ gl_FragDepth = texelFetch(strokeDepth, uv, 0).r;
+ FragColor = texelFetch(strokeColor, uv, 0);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl
new file mode 100644
index 00000000000..b3bd8e488f2
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl
@@ -0,0 +1,17 @@
+in vec4 mColor;
+in vec2 mTexCoord;
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = mTexCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared) {
+ discard;
+ }
+
+ fragColor = mColor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
new file mode 100644
index 00000000000..0d2da00db66
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
@@ -0,0 +1,48 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 Viewport;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 finalColor[1];
+in float finalThickness[1];
+
+out vec4 mColor;
+out vec2 mTexCoord;
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ return vec2(vertex.xy / vertex.w) * Viewport;
+}
+
+void main(void)
+{
+ vec4 P0 = gl_in[0].gl_Position;
+ vec2 sp0 = toScreenSpace(P0);
+
+ float size = finalThickness[0];
+
+ /* generate the triangle strip */
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, 0, 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, 0, 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(1, 1);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, 0, 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(1, 0);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, 0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
new file mode 100644
index 00000000000..77fdf58bea0
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
@@ -0,0 +1,15 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+in float size;
+
+out vec4 finalColor;
+out float finalThickness;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ finalColor = color;
+ finalThickness = size;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
new file mode 100644
index 00000000000..d2cad4e44f7
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
@@ -0,0 +1,143 @@
+uniform vec4 color2;
+uniform int fill_type;
+uniform float mix_factor;
+
+uniform float gradient_angle;
+uniform float gradient_radius;
+uniform float pattern_gridsize;
+uniform vec2 gradient_scale;
+uniform vec2 gradient_shift;
+
+uniform float texture_angle;
+uniform vec2 texture_scale;
+uniform vec2 texture_offset;
+uniform int texture_mix;
+uniform int texture_flip;
+uniform float texture_opacity;
+uniform int xraymode;
+
+uniform sampler2D myTexture;
+uniform int texture_clamp;
+
+/* keep this list synchronized with list in gpencil_draw_utils.c */
+#define SOLID 0
+#define GRADIENT 1
+#define RADIAL 2
+#define CHESS 3
+#define TEXTURE 4
+#define PATTERN 5
+
+#define GP_XRAY_FRONT 0
+#define GP_XRAY_3DSPACE 1
+#define GP_XRAY_BACK 2
+
+in vec4 finalColor;
+in vec2 texCoord_interp;
+out vec4 fragColor;
+#define texture2D texture
+
+void set_color(in vec4 color, in vec4 color2, in vec4 tcolor, in float mixv, in float factor,
+ in int tmix, in int flip, out vec4 ocolor)
+{
+ /* full color A */
+ if (mixv == 1.0) {
+ if (tmix == 1) {
+ ocolor = (flip == 0) ? color : tcolor;
+ }
+ else {
+ ocolor = (flip == 0) ? color : color2;
+ }
+ }
+ /* full color B */
+ else if (mixv == 0.0) {
+ if (tmix == 1) {
+ ocolor = (flip == 0) ? tcolor : color;
+ }
+ else {
+ ocolor = (flip == 0) ? color2 : color;
+ }
+ }
+ /* mix of colors */
+ else {
+ if (tmix == 1) {
+ ocolor = (flip == 0) ? mix(color, tcolor, factor) : mix(tcolor, color, factor);
+ }
+ else {
+ ocolor = (flip == 0) ? mix(color, color2, factor) : mix(color2, color, factor);
+ }
+ }
+}
+
+void main()
+{
+ vec2 t_center = vec2(0.5, 0.5);
+ mat2 matrot_tex = mat2(cos(texture_angle), -sin(texture_angle), sin(texture_angle), cos(texture_angle));
+ vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset;
+ vec4 tmp_color;
+ tmp_color = (texture_clamp == 0) ? texture2D(myTexture, rot_tex * texture_scale) : texture2D(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0));
+ vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity);
+ vec4 chesscolor;
+
+ /* solid fill */
+ if (fill_type == SOLID) {
+ fragColor = finalColor;
+ }
+ else {
+ vec2 center = vec2(0.5, 0.5) + gradient_shift;
+ mat2 matrot = mat2(cos(gradient_angle), -sin(gradient_angle), sin(gradient_angle), cos(gradient_angle));
+ vec2 rot = (((matrot * (texCoord_interp - center)) + center) * gradient_scale) + gradient_shift;
+ /* gradient */
+ if (fill_type == GRADIENT) {
+ set_color(finalColor, color2, text_color, mix_factor, rot.x - mix_factor + 0.5, texture_mix, texture_flip, fragColor);
+ }
+ /* radial gradient */
+ if (fill_type == RADIAL) {
+ float in_rad = gradient_radius * mix_factor;
+ float ex_rad = gradient_radius - in_rad;
+ float intensity = 0;
+ float distance = length((center - texCoord_interp) * gradient_scale);
+ if (distance > gradient_radius) {
+ discard;
+ }
+ if (distance > in_rad) {
+ intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0);
+ }
+ set_color(finalColor, color2, text_color, mix_factor, intensity, texture_mix, texture_flip, fragColor);
+ }
+ /* chessboard */
+ if (fill_type == CHESS) {
+ vec2 pos = rot / pattern_gridsize;
+ if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) {
+ chesscolor = (texture_flip == 0) ? finalColor : color2;
+ }
+ else {
+ chesscolor = (texture_flip == 0) ? color2 : finalColor;
+ }
+ /* mix with texture */
+ fragColor = (texture_mix == 1) ? mix(chesscolor, text_color, mix_factor) : chesscolor;
+ }
+ /* texture */
+ if (fill_type == TEXTURE) {
+ fragColor = (texture_mix == 1) ? mix(text_color, finalColor, mix_factor) : text_color;
+ }
+ /* pattern */
+ if (fill_type == PATTERN) {
+ fragColor = finalColor;
+ fragColor.a = min(text_color.a, finalColor.a);
+ }
+ }
+
+ /* set zdepth */
+ if (xraymode == GP_XRAY_FRONT) {
+ gl_FragDepth = 0.000001;
+ }
+ else if (xraymode == GP_XRAY_3DSPACE) {
+ gl_FragDepth = gl_FragCoord.z;
+ }
+ else if (xraymode == GP_XRAY_BACK) {
+ gl_FragDepth = 0.999999;
+ }
+ else {
+ gl_FragDepth = 0.000001;
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
new file mode 100644
index 00000000000..52da354a562
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
@@ -0,0 +1,14 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+in vec2 texCoord;
+out vec4 finalColor;
+out vec2 texCoord_interp;
+
+void main(void)
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ finalColor = color;
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
new file mode 100644
index 00000000000..c2e3f787bec
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
@@ -0,0 +1,9 @@
+uniform vec3 color;
+uniform float opacity;
+
+out vec4 FragColor;
+
+void main()
+{
+ FragColor = vec4(color, opacity);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
new file mode 100644
index 00000000000..0d6d2b22a55
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
@@ -0,0 +1,49 @@
+uniform int color_type;
+uniform int mode;
+uniform sampler2D myTexture;
+
+in vec4 mColor;
+in vec2 mTexCoord;
+out vec4 fragColor;
+
+#define texture2D texture
+
+#define GPENCIL_MODE_LINE 0
+#define GPENCIL_MODE_DOTS 1
+#define GPENCIL_MODE_BOX 2
+
+/* keep this list synchronized with list in gpencil_engine.h */
+#define GPENCIL_COLOR_SOLID 0
+#define GPENCIL_COLOR_TEXTURE 1
+#define GPENCIL_COLOR_PATTERN 2
+
+void main()
+{
+ vec2 centered = mTexCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if ((mode != GPENCIL_MODE_BOX) && (dist_squared > rad_squared))
+ discard;
+
+ vec4 tmp_color = texture2D(myTexture, mTexCoord);
+
+ /* Solid */
+ if (color_type == GPENCIL_COLOR_SOLID) {
+ fragColor = mColor;
+ }
+ /* texture */
+ if (color_type == GPENCIL_COLOR_TEXTURE) {
+ fragColor = texture2D(myTexture, mTexCoord);
+ /* mult both alpha factor to use strength factor with texture */
+ fragColor.a = min(fragColor.a * mColor.a, fragColor.a);
+ }
+ /* pattern */
+ if (color_type == GPENCIL_COLOR_PATTERN) {
+ vec4 text_color = texture2D(myTexture, mTexCoord);
+ fragColor = mColor;
+ /* mult both alpha factor to use strength factor with color alpha limit */
+ fragColor.a = min(text_color.a * mColor.a, mColor.a);
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
new file mode 100644
index 00000000000..63f22e0f812
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
@@ -0,0 +1,82 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 Viewport;
+uniform int xraymode;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 finalColor[1];
+in float finalThickness[1];
+in vec2 finaluvdata[1];
+
+out vec4 mColor;
+out vec2 mTexCoord;
+
+#define GP_XRAY_FRONT 0
+#define GP_XRAY_3DSPACE 1
+#define GP_XRAY_BACK 2
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ return vec2(vertex.xy / vertex.w) * Viewport;
+}
+
+/* get zdepth value */
+float getZdepth(vec4 point)
+{
+ if (xraymode == GP_XRAY_FRONT) {
+ return 0.000001;
+ }
+ if (xraymode == GP_XRAY_3DSPACE) {
+ return (point.z / point.w);
+ }
+ if (xraymode == GP_XRAY_BACK) {
+ return 0.999999;
+ }
+
+ /* in front by default */
+ return 0.000001;
+}
+
+vec2 rotateUV(vec2 uv, float angle)
+{
+ /* translate center of rotation to the center of texture */
+ vec2 new_uv = uv - vec2(0.5f, 0.5f);
+ vec2 rot_uv;
+ rot_uv.x = new_uv.x * cos(angle) - new_uv.y * sin(angle);
+ rot_uv.y = new_uv.y * cos(angle) + new_uv.x * sin(angle);
+ return rot_uv + vec2(0.5f, 0.5f);
+}
+
+void main(void)
+{
+ /* receive 4 points */
+ vec4 P0 = gl_in[0].gl_Position;
+ vec2 sp0 = toScreenSpace(P0);
+
+ float size = finalThickness[0];
+ float aspect = 1.0;
+ /* generate the triangle strip */
+ mTexCoord = rotateUV(vec2(0, 1), finaluvdata[0].y);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x - size, sp0.y + size * aspect) / Viewport, getZdepth(P0), 1.0);
+ EmitVertex();
+
+ mTexCoord = rotateUV(vec2(0, 0), finaluvdata[0].y);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x - size, sp0.y - size * aspect) / Viewport, getZdepth(P0), 1.0);
+ EmitVertex();
+
+ mTexCoord = rotateUV(vec2(1, 1), finaluvdata[0].y);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x + size, sp0.y + size * aspect) / Viewport, getZdepth(P0), 1.0);
+ EmitVertex();
+
+ mTexCoord = rotateUV(vec2(1, 0), finaluvdata[0].y);
+ mColor = finalColor[0];
+ gl_Position = vec4(vec2(sp0.x + size, sp0.y - size * aspect) / Viewport, getZdepth(P0), 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
new file mode 100644
index 00000000000..5e89bf8e5ce
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
@@ -0,0 +1,37 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform int keep_size;
+uniform float objscale;
+uniform float pixfactor;
+
+in vec3 pos;
+in vec4 color;
+in float thickness;
+in vec2 uvdata;
+
+out vec4 finalColor;
+out float finalThickness;
+out vec2 finaluvdata;
+
+#define TRUE 1
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ finalColor = color;
+
+ if (keep_size == TRUE) {
+ finalThickness = thickness;
+ }
+ else {
+ float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize);
+ finalThickness = max(size * objscale, 4.0); /* minimum 4 pixels */
+ }
+
+ finaluvdata = uvdata;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl
new file mode 100644
index 00000000000..dd54e38c3d0
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl
@@ -0,0 +1,15 @@
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
+ vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
+
+ FragColor = stroke_color;
+ gl_FragDepth = stroke_depth;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
new file mode 100644
index 00000000000..d57921c1629
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
@@ -0,0 +1,46 @@
+uniform int color_type;
+uniform sampler2D myTexture;
+
+in vec4 mColor;
+in vec2 mTexCoord;
+in float uvfac;
+
+out vec4 fragColor;
+
+#define texture2D texture
+
+/* keep this list synchronized with list in gpencil_engine.h */
+#define GPENCIL_COLOR_SOLID 0
+#define GPENCIL_COLOR_TEXTURE 1
+#define GPENCIL_COLOR_PATTERN 2
+
+void main()
+{
+ vec4 tColor = vec4(mColor);
+ /* if alpha < 0, then encap (only solid mode ) */
+ if ((mColor.a < 0) && (color_type == GPENCIL_COLOR_SOLID)) {
+ vec2 center = vec2(uvfac, 1.0);
+ tColor.a = tColor.a * -1.0;
+ float dist = length(mTexCoord - center);
+ if (dist > 0.50) {
+ discard;
+ }
+ }
+ /* Solid */
+ if (color_type == GPENCIL_COLOR_SOLID) {
+ fragColor = tColor;
+ }
+ /* texture */
+ if (color_type == GPENCIL_COLOR_TEXTURE) {
+ fragColor = texture2D(myTexture, mTexCoord);
+ /* mult both alpha factor to use strength factor */
+ fragColor.a = min(fragColor.a * tColor.a, fragColor.a);
+ }
+ /* pattern */
+ if (color_type == GPENCIL_COLOR_PATTERN) {
+ vec4 text_color = texture2D(myTexture, mTexCoord);
+ fragColor = tColor;
+ /* mult both alpha factor to use strength factor with color alpha limit */
+ fragColor.a = min(text_color.a * tColor.a, tColor.a);
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
new file mode 100644
index 00000000000..f9054b44996
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
@@ -0,0 +1,208 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 Viewport;
+uniform int xraymode;
+uniform int color_type;
+
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 13) out;
+
+in vec4 finalColor[4];
+in float finalThickness[4];
+in vec2 finaluvdata[4];
+
+out vec4 mColor;
+out vec2 mTexCoord;
+out float uvfac;
+
+#define GP_XRAY_FRONT 0
+#define GP_XRAY_3DSPACE 1
+#define GP_XRAY_BACK 2
+
+/* keep this list synchronized with list in gpencil_engine.h */
+#define GPENCIL_COLOR_SOLID 0
+#define GPENCIL_COLOR_TEXTURE 1
+#define GPENCIL_COLOR_PATTERN 2
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ return vec2(vertex.xy / vertex.w) * Viewport;
+}
+
+/* get zdepth value */
+float getZdepth(vec4 point)
+{
+ if (xraymode == GP_XRAY_FRONT) {
+ return 0.000001;
+ }
+ if (xraymode == GP_XRAY_3DSPACE) {
+ return (point.z / point.w);
+ }
+ if (xraymode == GP_XRAY_BACK) {
+ return 0.999999;
+ }
+
+ /* in front by default */
+ return 0.000001;
+}
+void main(void)
+{
+ float MiterLimit = 0.75;
+ uvfac = 0;
+
+ /* receive 4 points */
+ vec4 P0 = gl_in[0].gl_Position;
+ vec4 P1 = gl_in[1].gl_Position;
+ vec4 P2 = gl_in[2].gl_Position;
+ vec4 P3 = gl_in[3].gl_Position;
+
+ /* get the four vertices passed to the shader */
+ vec2 sp0 = toScreenSpace(P0); // start of previous segment
+ vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment
+ vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment
+ vec2 sp3 = toScreenSpace(P3); // end of next segment
+
+ /* culling outside viewport */
+ vec2 area = Viewport * 4.0;
+ if (sp1.x < -area.x || sp1.x > area.x) return;
+ if (sp1.y < -area.y || sp1.y > area.y) return;
+ if (sp2.x < -area.x || sp2.x > area.x) return;
+ if (sp2.y < -area.y || sp2.y > area.y) return;
+
+ /* determine the direction of each of the 3 segments (previous, current, next) */
+ vec2 v0 = normalize(sp1 - sp0);
+ vec2 v1 = normalize(sp2 - sp1);
+ vec2 v2 = normalize(sp3 - sp2);
+
+ /* determine the normal of each of the 3 segments (previous, current, next) */
+ vec2 n0 = vec2(-v0.y, v0.x);
+ vec2 n1 = vec2(-v1.y, v1.x);
+ vec2 n2 = vec2(-v2.y, v2.x);
+
+ /* determine miter lines by averaging the normals of the 2 segments */
+ vec2 miter_a = normalize(n0 + n1); // miter at start of current segment
+ vec2 miter_b = normalize(n1 + n2); // miter at end of current segment
+
+ /* determine the length of the miter by projecting it onto normal and then inverse it */
+ float an1 = dot(miter_a, n1);
+ float bn1 = dot(miter_b, n2);
+ if (an1 == 0) an1 = 1;
+ if (bn1 == 0) bn1 = 1;
+ float length_a = finalThickness[1] / an1;
+ float length_b = finalThickness[2] / bn1;
+ if (length_a <= 0.0) length_a = 0.01;
+ if (length_b <= 0.0) length_b = 0.01;
+
+ /* prevent excessively long miters at sharp corners */
+ if (dot(v0, v1) < -MiterLimit) {
+ miter_a = n1;
+ length_a = finalThickness[1];
+
+ /* close the gap */
+ if (dot(v0, n1) > 0) {
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0.5);
+ mColor = finalColor[1];
+ gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+ }
+ else {
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0.5);
+ mColor = finalColor[1];
+ gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+ }
+ }
+
+ if (dot(v1, v2) < -MiterLimit) {
+ miter_b = n1;
+ length_b = finalThickness[2];
+ }
+
+ /* generate the start endcap (alpha < 0 used as endcap flag)*/
+ if ((P0 == P2) && (color_type == GPENCIL_COLOR_SOLID)){
+ mTexCoord = vec2(2, 1);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0;
+ gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 2);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+ }
+
+ /* generate the triangle strip */
+ mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 0) : vec2(finaluvdata[1].x, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 1) : vec2(finaluvdata[1].x, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 0) : vec2(finaluvdata[2].x, 0);
+ mColor = finalColor[2];
+ gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 1) : vec2(finaluvdata[2].x, 1);
+ mColor = finalColor[2];
+ gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ /* generate the end endcap (alpha < 0 used as endcap flag)*/
+ if ((P1 == P3) && (color_type == GPENCIL_COLOR_SOLID)){
+ mTexCoord = vec2(finaluvdata[2].x, 2);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ uvfac = finaluvdata[2].x;
+ gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(finaluvdata[2].x, 0);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ uvfac = finaluvdata[2].x;
+ gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(finaluvdata[2].x + 2, 1);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ uvfac = finaluvdata[2].x;
+ vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0;
+ gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
new file mode 100644
index 00000000000..2f9a105e911
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
@@ -0,0 +1,37 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform int keep_size;
+uniform float objscale;
+uniform float pixfactor;
+
+in vec3 pos;
+in vec4 color;
+in float thickness;
+in vec2 uvdata;
+
+out vec4 finalColor;
+out float finalThickness;
+out vec2 finaluvdata;
+
+#define TRUE 1
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+
+void main(void)
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ finalColor = color;
+
+ if (keep_size == TRUE) {
+ finalThickness = thickness;
+ }
+ else {
+ float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize);
+ finalThickness = max(size * objscale, 1.0);
+ }
+
+ finaluvdata = uvdata;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl
new file mode 100644
index 00000000000..0983e6c4d87
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl
@@ -0,0 +1,45 @@
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform int tonemapping;
+
+float srgb_to_linearrgb(float c)
+{
+ if (c < 0.04045)
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
+ else
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
+}
+
+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 main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
+ vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
+
+ /* premult alpha factor to remove double blend effects */
+ if (stroke_color.a > 0) {
+ stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a);
+ }
+
+ /* apply color correction for render only */
+ if (tonemapping == 1) {
+ stroke_color.r = srgb_to_linearrgb(stroke_color.r);
+ stroke_color.g = srgb_to_linearrgb(stroke_color.g);
+ stroke_color.b = srgb_to_linearrgb(stroke_color.b);
+ }
+
+ FragColor = stroke_color;
+ gl_FragDepth = stroke_depth;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
index 81b6b2567a9..67a22073a4b 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
@@ -19,7 +19,7 @@ in vec3 normal_viewport;
#ifdef V3D_SHADING_TEXTURE_COLOR
in vec2 uv_interp;
#endif
-#ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
+#ifdef V3D_LIGHTING_MATCAP
uniform sampler2D matcapImage;
#endif
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
new file mode 100644
index 00000000000..1f14e506dcf
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -0,0 +1,181 @@
+
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelMatrixInverse;
+uniform mat4 ModelViewMatrixInverse;
+uniform mat4 ModelMatrix;
+
+uniform sampler2D depthBuffer;
+uniform sampler3D densityTexture;
+
+uniform int samplesLen = 256;
+uniform float stepLength; /* Step length in local space. */
+uniform float densityScale; /* Simple Opacity multiplicator. */
+uniform vec4 viewvecs[3];
+
+uniform float slicePosition;
+uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+
+#ifdef VOLUME_SLICE
+in vec3 localPos;
+#endif
+
+out vec4 fragColor;
+
+#define M_PI 3.1415926535897932 /* pi */
+
+float phase_function_isotropic()
+{
+ return 1.0 / (4.0 * M_PI);
+}
+
+float get_view_z_from_depth(float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ float d = 2.0 * depth - 1.0;
+ return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
+ }
+ else {
+ return viewvecs[0].z + depth * viewvecs[1].z;
+ }
+}
+
+vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return vec3(viewvecs[0].xy + uvcoords * viewvecs[1].xy, 1.0) * get_view_z_from_depth(depth);
+ }
+ else {
+ return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
+ }
+}
+
+float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
+
+float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
+{
+ /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */
+ vec3 firstplane = (vec3( 1.0) - lineorigin) / linedirection;
+ vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection;
+ vec3 furthestplane = min(firstplane, secondplane);
+ return max_v3(furthestplane);
+}
+
+void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
+{
+ scattering = vec3(0.0);
+ extinction = 1e-8;
+
+ vec4 density = texture(densityTexture, ls_pos * 0.5 + 0.5);
+ density.rgb /= density.a;
+ density *= densityScale;
+
+ scattering = density.rgb;
+ extinction = max(1e-8, density.a);
+}
+
+#define P(x) ((x + 0.5) * (1.0 / 16.0))
+const vec4 dither_mat[4] = vec4[4](
+ vec4( P(0.0), P(8.0), P(2.0), P(10.0)),
+ vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
+ vec4( P(3.0), P(11.0), P(1.0), P(9.0)),
+ vec4(P(15.0), P(7.0), P(13.0), P(5.0))
+);
+
+vec4 volume_integration(
+ vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max, float step_len)
+{
+ /* Start with full transmittance and no scattered light. */
+ vec3 final_scattering = vec3(0.0);
+ float final_transmittance = 1.0;
+
+ ivec2 tx = ivec2(gl_FragCoord.xy) % 4;
+ float noise = dither_mat[tx.x][tx.y];
+
+ float ray_len = noise * ray_inc;
+ for (int i = 0; i < samplesLen && ray_len < ray_max; ++i, ray_len += ray_inc) {
+ vec3 ls_pos = ray_ori + ray_dir * ray_len;
+
+ vec3 Lscat;
+ float s_extinction;
+ volume_properties(ls_pos, Lscat, s_extinction);
+ /* Evaluate Scattering */
+ float Tr = exp(-s_extinction * step_len);
+ /* integrate along the current step segment */
+ Lscat = (Lscat - Lscat * Tr) / s_extinction;
+ /* accumulate and also take into account the transmittance from previous steps */
+ final_scattering += final_transmittance * Lscat;
+ final_transmittance *= Tr;
+ }
+
+ return vec4(final_scattering, 1.0 - final_transmittance);
+}
+
+void main()
+{
+#ifdef VOLUME_SLICE
+ /* Manual depth test. TODO remove. */
+ float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
+ if (gl_FragCoord.z >= depth) {
+ discard;
+ }
+
+ ivec3 volume_size = textureSize(densityTexture, 0);
+ float step_len;
+ if (sliceAxis == 0) {
+ step_len = float(volume_size.x);
+ }
+ else if (sliceAxis == 1) {
+ step_len = float(volume_size.y);
+ }
+ else {
+ step_len = float(volume_size.z);
+ }
+ /* FIXME Should be in world space but is in local space. */
+ step_len = 1.0 / step_len;
+
+ vec3 Lscat;
+ float s_extinction;
+ volume_properties(localPos, Lscat, s_extinction);
+ /* Evaluate Scattering */
+ float Tr = exp(-s_extinction * step_len);
+ /* integrate along the current step segment */
+ Lscat = (Lscat - Lscat * Tr) / s_extinction;
+
+ fragColor = vec4(Lscat, 1.0 - Tr);
+
+#else
+ vec2 screen_uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy);
+ bool is_persp = ProjectionMatrix[3][3] == 0.0;
+
+ vec3 volume_center = ModelMatrix[3].xyz;
+
+ float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
+ float depth_end = min(depth, gl_FragCoord.z);
+ vec3 vs_ray_end = get_view_space_from_depth(screen_uv, depth_end);
+ vec3 vs_ray_ori = get_view_space_from_depth(screen_uv, 0.0);
+ vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0);
+ vs_ray_dir /= abs(vs_ray_dir.z);
+
+ vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir;
+ vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz;
+ vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz;
+
+ /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */
+
+ float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir);
+ if (dist > 0.0) {
+ ls_ray_ori = ls_ray_dir * dist + ls_ray_ori;
+ }
+
+ vec3 ls_vol_isect = ls_ray_end - ls_ray_ori;
+ if (dot(ls_ray_dir, ls_vol_isect) < 0.0) {
+ /* Start is further away than the end.
+ * That means no volume is intersected. */
+ discard;
+ }
+
+ fragColor = volume_integration(ls_ray_ori, ls_ray_dir, stepLength,
+ length(ls_vol_isect) / length(ls_ray_dir),
+ length(vs_ray_dir) * stepLength);
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
new file mode 100644
index 00000000000..90a22d9d02f
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
@@ -0,0 +1,31 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float slicePosition;
+uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+
+in vec3 pos;
+
+#ifdef VOLUME_SLICE
+in vec3 uvs;
+
+out vec3 localPos;
+#endif
+
+void main()
+{
+#ifdef VOLUME_SLICE
+ if (sliceAxis == 0) {
+ localPos = vec3(slicePosition * 2.0 - 1.0, pos.xy);
+ }
+ else if (sliceAxis == 1) {
+ localPos = vec3(pos.x, slicePosition * 2.0 - 1.0, pos.y);
+ }
+ else {
+ localPos = vec3(pos.xy, slicePosition * 2.0 - 1.0);
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(localPos, 1.0);
+#else
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c
index b28263d48cf..5c64cebd981 100644
--- a/source/blender/draw/engines/workbench/solid_mode.c
+++ b/source/blender/draw/engines/workbench/solid_mode.c
@@ -30,6 +30,8 @@
#include "GPU_shader.h"
+#include "RE_pipeline.h"
+
#include "workbench_private.h"
/* Functions */
@@ -69,6 +71,7 @@ static void workbench_solid_draw_scene(void *vedata)
{
WORKBENCH_Data *data = vedata;
workbench_deferred_draw_scene(data);
+ workbench_deferred_draw_finish(data);
}
static void workbench_solid_engine_free(void)
@@ -82,6 +85,11 @@ static void workbench_solid_view_update(void *vedata)
workbench_taa_view_updated(data);
}
+static void workbench_render_to_image(void *vedata, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect)
+{
+ workbench_render(vedata, engine, render_layer, rect);
+}
+
static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
DrawEngineType draw_engine_workbench_solid = {
@@ -97,5 +105,5 @@ DrawEngineType draw_engine_workbench_solid = {
&workbench_solid_draw_scene,
&workbench_solid_view_update,
NULL,
- NULL,
+ &workbench_render_to_image,
};
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 1f5a1e17277..49cdab256f0 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -19,37 +19,53 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->user_preferences = &U;
View3D *v3d = draw_ctx->v3d;
- if (v3d) {
+ if (!v3d) {
+ wpd->shading = scene->display.shading;
+ wpd->use_color_view_settings = true;
+ }
+ else if (v3d->shading.type == OB_RENDER &&
+ BKE_scene_uses_blender_opengl(scene))
+ {
+ wpd->shading = scene->display.shading;
+ wpd->use_color_view_settings = true;
+ }
+ else {
wpd->shading = v3d->shading;
- if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
- wpd->studio_light = BKE_studiolight_find(
- wpd->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
- }
- else {
- wpd->studio_light = BKE_studiolight_find(
- wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD);
- }
+ wpd->use_color_view_settings = false;
+ }
+
+ if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
+ wpd->studio_light = BKE_studiolight_find(
+ wpd->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
}
else {
- memset(&wpd->shading, 0, sizeof(wpd->shading));
- wpd->shading.light = V3D_LIGHTING_STUDIO;
- wpd->shading.shadow_intensity = 0.5;
- copy_v3_fl(wpd->shading.single_color, 0.8f);
- wpd->studio_light = BKE_studiolight_find_first(STUDIOLIGHT_INTERNAL);
+ wpd->studio_light = BKE_studiolight_find(
+ wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD);
}
+
+ /* If matcaps are missing, use this as fallback. */
+ if (UNLIKELY(wpd->studio_light == NULL)) {
+ wpd->studio_light = BKE_studiolight_find(
+ wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD);
+ }
+
wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity;
WORKBENCH_UBO_World *wd = &wpd->world_data;
wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
- wd->background_alpha = 1.0f;
+ wd->background_alpha = (v3d || scene->r.alphamode == R_ADDSKY) ? 1.0f : 0.0f;
- if ((v3d->flag3 & V3D_SHOW_WORLD) &&
- (scene->world != NULL))
+ if (!v3d || ((v3d->shading.background_type & V3D_SHADING_BACKGROUND_WORLD) &&
+ (scene->world != NULL)))
{
copy_v3_v3(wd->background_color_low, &scene->world->horr);
copy_v3_v3(wd->background_color_high, &scene->world->horr);
}
- else {
+ else if (v3d->shading.background_type & V3D_SHADING_BACKGROUND_VIEWPORT) {
+ copy_v3_v3(wd->background_color_low, v3d->shading.background_color);
+ copy_v3_v3(wd->background_color_high, v3d->shading.background_color);
+ }
+ else if (v3d) {
UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_LOW_GRAD : TH_HIGH_GRAD, wd->background_color_low);
UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high);
@@ -58,6 +74,10 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high);
srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low);
}
+ else {
+ zero_v3(wd->background_color_low);
+ zero_v3(wd->background_color_high);
+ }
studiolight_update_world(wpd->studio_light, wd);
@@ -119,6 +139,9 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->viewvecs[1][2] = vec_far[2] - wpd->viewvecs[0][2];
}
}
+
+ wpd->volumes_do = false;
+ BLI_listbase_clear(&wpd->smoke_domains);
}
void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float r_light_direction[3])
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 7625d9d1e48..0442d6aef56 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -33,6 +33,7 @@
#include "BLI_rand.h"
#include "BKE_node.h"
+#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "DNA_image_types.h"
@@ -141,9 +142,12 @@ static char *workbench_build_prepass_frag(void)
return str;
}
-static char *workbench_build_prepass_vert(void)
+static char *workbench_build_prepass_vert(bool is_hair)
{
char *str = NULL;
+ if (!is_hair) {
+ return BLI_strdup(datatoc_workbench_prepass_vert_glsl);
+ }
DynStr *ds = BLI_dynstr_new();
@@ -175,7 +179,7 @@ static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, bool
if (e_data.prepass_sh_cache[index] == NULL) {
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
char *composite_frag = workbench_build_composite_frag(wpd);
- char *prepass_vert = workbench_build_prepass_vert();
+ char *prepass_vert = workbench_build_prepass_vert(is_hair);
char *prepass_frag = workbench_build_prepass_frag();
e_data.prepass_sh_cache[index] = DRW_shader_create(
prepass_vert, NULL,
@@ -271,6 +275,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PassList *psl = vedata->psl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
if (!stl->g_data) {
/* Alloc transient pointers */
@@ -327,12 +332,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
char *cavity_frag = workbench_build_cavity_frag();
e_data.cavity_sh = DRW_shader_create_fullscreen(cavity_frag, NULL);
MEM_freeN(cavity_frag);
-
}
+ workbench_volume_engine_init();
workbench_fxaa_engine_init();
workbench_taa_engine_init(vedata);
-
WORKBENCH_PrivateData *wpd = stl->g_data;
workbench_private_data_init(wpd);
@@ -370,6 +374,10 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
});
+ GPU_framebuffer_ensure_config(&fbl->volume_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
+ });
GPU_framebuffer_ensure_config(&fbl->effect_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
@@ -377,7 +385,6 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
}
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
/* AO Samples Tex */
int num_iterations = workbench_taa_calculate_num_iterations(vedata);
@@ -401,8 +408,10 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
/* Prepass */
{
+ const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
+
int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- psl->prepass_pass = DRW_pass_create("Prepass", state);
+ psl->prepass_pass = DRW_pass_create("Prepass", (do_cull) ? state | DRW_STATE_CULL_BACK : state);
psl->prepass_hair_pass = DRW_pass_create("Prepass", state);
}
@@ -446,6 +455,7 @@ void workbench_deferred_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh);
+ workbench_volume_engine_free();
workbench_fxaa_engine_free();
workbench_taa_engine_free();
}
@@ -485,7 +495,10 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
Scene *scene = draw_ctx->scene;
+ workbench_volume_cache_init(vedata);
+
select_deferred_shaders(wpd);
+
/* Deferred Mix Pass */
{
workbench_private_data_get_light_direction(wpd, e_data.display.light_direction);
@@ -636,6 +649,9 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
if (!DRW_object_is_renderable(ob))
return;
@@ -643,13 +659,22 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
workbench_cache_populate_particles(vedata, ob);
}
+ ModifierData *md;
+ if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
+ (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
+ (((SmokeModifierData *)md)->domain != NULL))
+ {
+ workbench_volume_cache_populate(vedata, scene, ob, md);
+ return; /* Do not draw solid in this case. */
+ }
+
if (!DRW_check_object_visible_within_active_context(ob)) {
return;
}
WORKBENCH_MaterialData *material;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
bool is_drawn = false;
@@ -658,7 +683,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
+ struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if (materials_len > 0 && geom_array) {
for (int i = 0; i < materials_len; i++) {
if (geom_array[i] == NULL) {
@@ -681,7 +706,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (!is_drawn) {
if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_RANDOM_COLOR)) {
/* No material split needed */
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
if (is_sculpt_mode) {
@@ -699,7 +724,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
gpumat_array[i] = NULL;
}
- struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, NULL, NULL, NULL);
if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
@@ -722,7 +747,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (SHADOW_ENABLED(wpd) && (ob->display.flag & OB_SHOW_SHADOW)) {
bool is_manifold;
- struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold);
+ struct GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold);
if (geom_shadow) {
if (is_sculpt_mode) {
/* Currently unsupported in sculpt mode. We could revert to the slow
@@ -860,6 +885,19 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
DRW_draw_pass(psl->composite_pass);
}
+ if (wpd->volumes_do) {
+ GPU_framebuffer_bind(fbl->volume_fb);
+ DRW_draw_pass(psl->volume_pass);
+ }
+
workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx);
+}
+
+void workbench_deferred_draw_finish(WORKBENCH_Data *vedata)
+{
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+
workbench_private_data_free(wpd);
+ workbench_volume_smoke_textures_free(wpd);
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c
index f1d5d5d6078..deb9a517f96 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_aa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c
@@ -23,6 +23,8 @@
* \ingroup draw_engine
*/
+#include "ED_screen.h"
+
#include "workbench_private.h"
@@ -32,6 +34,15 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx)
WORKBENCH_PrivateData *wpd = stl->g_data;
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_EffectInfo *effect_info = stl->effects;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if (draw_ctx->evil_C != NULL) {
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+ wpd->is_playback = ED_screen_animation_playing(wm) != NULL;
+ }
+ else {
+ wpd->is_playback = false;
+ }
if (TAA_ENABLED(wpd)) {
psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx);
@@ -45,6 +56,18 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx)
}
}
+static void workspace_aa_draw_transform(GPUTexture *tx, WORKBENCH_PrivateData *wpd)
+{
+ if (DRW_state_is_image_render()) {
+ /* Linear result for render. */
+ DRW_transform_none(tx);
+ }
+ else {
+ /* Display space result for viewport. */
+ DRW_transform_to_display(tx, wpd->use_color_view_settings);
+ }
+}
+
void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx)
{
WORKBENCH_StorageList *stl = vedata->stl;
@@ -56,7 +79,7 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
if (FXAA_ENABLED(wpd)) {
GPU_framebuffer_bind(fbl->effect_fb);
- DRW_transform_to_display(tx);
+ workspace_aa_draw_transform(tx, wpd);
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->effect_aa_pass);
}
@@ -69,11 +92,11 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx)
*/
if (effect_info->jitter_index == 1) {
GPU_framebuffer_bind(dfbl->color_only_fb);
- DRW_transform_to_display(tx);
+ workspace_aa_draw_transform(tx, wpd);
}
else {
GPU_framebuffer_bind(fbl->effect_fb);
- DRW_transform_to_display(tx);
+ workspace_aa_draw_transform(tx, wpd);
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->effect_aa_pass);
}
@@ -81,6 +104,6 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx)
}
else {
GPU_framebuffer_bind(dfbl->color_only_fb);
- DRW_transform_to_display(tx);
+ workspace_aa_draw_transform(tx, wpd);
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c
index fbeccc19660..403338d55c4 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_taa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c
@@ -93,15 +93,19 @@ int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata)
WORKBENCH_PrivateData *wpd = stl->g_data;
int result = 1;
if (TAA_ENABLED(wpd)) {
- if (IN_RANGE_INCL(
+ if (DRW_state_is_image_render()) {
+ const Scene *scene = DRW_context_state_get()->scene;
+ result = (scene->r.mode & R_OSA) ? scene->r.osa : 1;
+ }
+ else if (IN_RANGE_INCL(
wpd->user_preferences->gpu_viewport_quality,
GPU_VIEWPORT_QUALITY_TAA8, GPU_VIEWPORT_QUALITY_TAA16))
{
result = 8;
}
else if (IN_RANGE_INCL(
- wpd->user_preferences->gpu_viewport_quality,
- GPU_VIEWPORT_QUALITY_TAA16, GPU_VIEWPORT_QUALITY_TAA32))
+ wpd->user_preferences->gpu_viewport_quality,
+ GPU_VIEWPORT_QUALITY_TAA16, GPU_VIEWPORT_QUALITY_TAA32))
{
result = 16;
}
@@ -276,10 +280,12 @@ void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata)
GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT);
- DRW_viewport_matrix_override_unset_all();
+ if (!DRW_state_is_image_render()) {
+ DRW_viewport_matrix_override_unset_all();
+ }
copy_m4_m4(effect_info->last_mat, effect_info->curr_mat);
- if (effect_info->jitter_index != 0) {
+ if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) {
DRW_viewport_request_redraw();
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 26ae1c289c8..642c5820895 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -29,16 +29,16 @@
#include "DRW_render.h"
#include "workbench_engine.h"
-/* Shaders */
-
-#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
+#include "workbench_private.h"
+#define OPENGL_ENGINE "BLENDER_OPENGL"
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
-RenderEngineType DRW_engine_viewport_workbench_type = {
+RenderEngineType DRW_engine_viewport_opengl_type = {
NULL, NULL,
- WORKBENCH_ENGINE, N_("Workbench"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ OPENGL_ENGINE, N_("OpenGL"), RE_INTERNAL,
+ NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL,
+ &workbench_render_update_passes,
&draw_engine_workbench_solid,
{NULL, NULL, NULL}
};
diff --git a/source/blender/draw/engines/workbench/workbench_engine.h b/source/blender/draw/engines/workbench/workbench_engine.h
index a7f168db093..24f68cacd21 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.h
+++ b/source/blender/draw/engines/workbench/workbench_engine.h
@@ -28,6 +28,6 @@
extern DrawEngineType draw_engine_workbench_solid;
extern DrawEngineType draw_engine_workbench_transparent;
-extern RenderEngineType DRW_engine_viewport_workbench_type;
+extern RenderEngineType DRW_engine_viewport_opengl_type;
#endif /* __WORKBENCH_ENGINE_H__ */
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 3cc04d7936a..6d595ec00bd 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -33,6 +33,7 @@
#include "BKE_node.h"
#include "BKE_particle.h"
+#include "BKE_modifier.h"
#include "DNA_image_types.h"
#include "DNA_mesh_types.h"
@@ -79,9 +80,12 @@ extern char datatoc_workbench_common_lib_glsl[];
extern char datatoc_workbench_world_light_lib_glsl[];
/* static functions */
-static char *workbench_build_forward_vert(void)
+static char *workbench_build_forward_vert(bool is_hair)
{
char *str = NULL;
+ if (!is_hair) {
+ return BLI_strdup(datatoc_workbench_prepass_vert_glsl);
+ }
DynStr *ds = BLI_dynstr_new();
@@ -205,7 +209,7 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool u
if (e_data.transparent_accum_sh_cache[index] == NULL) {
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
- char *transparent_accum_vert = workbench_build_forward_vert();
+ char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag();
e_data.transparent_accum_sh_cache[index] = DRW_shader_create(
transparent_accum_vert, NULL,
@@ -242,14 +246,15 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_StorageList *stl = vedata->stl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
DRWShadingGroup *grp;
if (!stl->g_data) {
/* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
if (!stl->effects) {
- stl->effects = MEM_mallocN(sizeof(*stl->effects), __func__);
+ stl->effects = MEM_callocN(sizeof(*stl->effects), __func__);
workbench_effect_info_init(stl->effects);
}
WORKBENCH_PrivateData *wpd = stl->g_data;
@@ -265,7 +270,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
char *defines = workbench_material_build_defines(wpd, false, false);
char *defines_texture = workbench_material_build_defines(wpd, true, false);
char *defines_hair = workbench_material_build_defines(wpd, false, true);
- char *forward_vert = workbench_build_forward_vert();
+ char *forward_vert = workbench_build_forward_vert(false);
+ char *forward_hair_vert = workbench_build_forward_vert(true);
e_data.object_outline_sh = DRW_shader_create(
forward_vert, NULL,
datatoc_workbench_forward_depth_frag_glsl, defines);
@@ -273,17 +279,19 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
forward_vert, NULL,
datatoc_workbench_forward_depth_frag_glsl, defines_texture);
e_data.object_outline_hair_sh = DRW_shader_create(
- forward_vert, NULL,
+ forward_hair_vert, NULL,
datatoc_workbench_forward_depth_frag_glsl, defines_hair);
e_data.checker_depth_sh = DRW_shader_create_fullscreen(
datatoc_workbench_checkerboard_depth_frag_glsl, NULL);
+ MEM_freeN(forward_hair_vert);
MEM_freeN(forward_vert);
MEM_freeN(defines);
MEM_freeN(defines_texture);
MEM_freeN(defines_hair);
}
+ workbench_volume_engine_init();
workbench_fxaa_engine_init();
workbench_taa_engine_init(vedata);
@@ -305,13 +313,11 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
});
-
GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx),
GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx),
});
-
GPU_framebuffer_ensure_config(&fbl->composite_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
@@ -321,14 +327,18 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx),
});
+ workbench_volume_cache_init(vedata);
+ const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
+ const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0;
+
/* Transparency Accum */
{
- int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT;
+ int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | cull_state;
psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state);
}
/* Depth */
{
- int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state;
psl->object_outline_pass = DRW_pass_create("Object Outline Pass", state);
}
/* Composite */
@@ -372,7 +382,9 @@ void workbench_forward_engine_free()
DRW_SHADER_FREE_SAFE(e_data.object_outline_hair_sh);
DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh);
+ workbench_volume_engine_free();
workbench_fxaa_engine_free();
+ workbench_taa_engine_free();
}
void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata))
@@ -444,6 +456,8 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
{
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
if (!DRW_object_is_renderable(ob))
return;
@@ -452,13 +466,22 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
workbench_forward_cache_populate_particles(vedata, ob);
}
+ ModifierData *md;
+ if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
+ (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
+ (((SmokeModifierData *)md)->domain != NULL))
+ {
+ workbench_volume_cache_populate(vedata, scene, ob, md);
+ return; /* Do not draw solid in this case. */
+ }
+
if (!DRW_check_object_visible_within_active_context(ob)) {
return;
}
WORKBENCH_MaterialData *material;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
bool is_drawn = false;
@@ -468,7 +491,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
+ struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if (materials_len > 0 && geom_array) {
for (int i = 0; i < materials_len; i++) {
if (geom_array[i] == NULL) {
@@ -501,7 +524,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (!is_drawn) {
if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_RANDOM_COLOR)) {
/* No material split needed */
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
if (is_sculpt_mode) {
@@ -521,7 +544,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
gpumat_array[i] = NULL;
}
- struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, NULL, NULL, NULL);
if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
@@ -595,6 +618,7 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata)
/* Composite */
GPU_framebuffer_bind(fbl->composite_fb);
DRW_draw_pass(psl->composite_pass);
+ DRW_draw_pass(psl->volume_pass);
/* Color correct and Anti aliasing */
workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx);
@@ -604,4 +628,5 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata)
DRW_draw_pass(psl->checker_depth_pass);
workbench_private_data_free(wpd);
+ workbench_volume_smoke_textures_free(wpd);
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 4210e03f470..10ea0152b90 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -36,6 +36,7 @@
#include "DRW_render.h"
+#include "workbench_engine.h"
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
@@ -51,9 +52,11 @@
#define CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY)
#define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW)
-#define IS_NAVIGATING(wpd) (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)
-#define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && (IN_RANGE(wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || ((wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8) && IS_NAVIGATING(wpd))))
-#define TAA_ENABLED(wpd) (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd))
+#define IS_NAVIGATING(wpd) ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING))
+#define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && \
+ (IN_RANGE(wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || \
+ ((IS_NAVIGATING(wpd) || wpd->is_playback) && (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8))))
+#define TAA_ENABLED(wpd) (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && !wpd->is_playback)
#define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)))
#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd))
@@ -61,6 +64,11 @@
#define NORMAL_ENCODING_ENABLED() (true)
+struct RenderEngine;
+struct RenderLayer;
+struct rcti;
+
+
typedef struct WORKBENCH_FramebufferList {
/* Deferred render buffers */
struct GPUFrameBuffer *prepass_fb;
@@ -70,6 +78,7 @@ typedef struct WORKBENCH_FramebufferList {
struct GPUFrameBuffer *effect_fb;
struct GPUFrameBuffer *effect_taa_fb;
struct GPUFrameBuffer *depth_buffer_fb;
+ struct GPUFrameBuffer *volume_fb;
/* Forward render buffers */
struct GPUFrameBuffer *object_outline_fb;
@@ -101,6 +110,7 @@ typedef struct WORKBENCH_PassList {
struct DRWPass *composite_pass;
struct DRWPass *composite_shadow_pass;
struct DRWPass *effect_aa_pass;
+ struct DRWPass *volume_pass;
/* forward rendering */
struct DRWPass *transparent_accum_pass;
@@ -166,12 +176,20 @@ typedef struct WORKBENCH_PrivateData {
float shadow_near_max[3];
float shadow_near_sides[2][4]; /* This is a parallelogram, so only 2 normal and distance to the edges. */
bool shadow_changed;
+ bool is_playback;
+
+ /* Volumes */
+ bool volumes_do;
+ ListBase smoke_domains;
/* Ssao */
float winmat[4][4];
float viewvecs[3][4];
float ssao_params[4];
float ssao_settings[4];
+
+ /* Color Management */
+ bool use_color_view_settings;
} WORKBENCH_PrivateData; /* Transient data */
typedef struct WORKBENCH_EffectInfo {
@@ -225,6 +243,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata);
void workbench_deferred_engine_free(void);
void workbench_deferred_draw_background(WORKBENCH_Data *vedata);
void workbench_deferred_draw_scene(WORKBENCH_Data *vedata);
+void workbench_deferred_draw_finish(WORKBENCH_Data *vedata);
void workbench_deferred_cache_init(WORKBENCH_Data *vedata);
void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob);
void workbench_deferred_cache_finish(WORKBENCH_Data *vedata);
@@ -280,7 +299,15 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd);
void workbench_private_data_free(WORKBENCH_PrivateData *wpd);
void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float r_light_direction[3]);
-extern DrawEngineType draw_engine_workbench_solid;
-extern DrawEngineType draw_engine_workbench_transparent;
+/* workbench_volume.c */
+void workbench_volume_engine_init(void);
+void workbench_volume_engine_free(void);
+void workbench_volume_cache_init(WORKBENCH_Data *vedata);
+void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, struct ModifierData *md);
+void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd);
+
+/* workbench_render.c */
+void workbench_render(WORKBENCH_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect);
+void workbench_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
#endif
diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c
new file mode 100644
index 00000000000..1b25d4c875c
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_render.c
@@ -0,0 +1,172 @@
+/*
+ * 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 workbench_render.c
+ * \ingroup draw_engine
+ *
+ * Render functions for final render output.
+ */
+
+#include "BLI_rect.h"
+
+#include "BKE_report.h"
+
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "RE_pipeline.h"
+
+#include "workbench_private.h"
+
+static void workbench_render_cache(
+ void *vedata, struct Object *ob,
+ struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
+{
+ workbench_deferred_solid_cache_populate(vedata, ob);
+}
+
+static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph)
+{
+ /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+ float frame = BKE_scene_frame_get(scene);
+
+ /* Set the persective, view and window matrix. */
+ float winmat[4][4], wininv[4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float persmat[4][4], persinv[4][4];
+
+ RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
+ RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
+
+ invert_m4_m4(viewmat, viewinv);
+ mul_m4_m4m4(persmat, winmat, viewmat);
+ invert_m4_m4(persinv, persmat);
+ invert_m4_m4(wininv, winmat);
+
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+}
+
+static bool workbench_render_framebuffers_init(void)
+{
+ /* For image render, allocate own buffers because we don't have a viewport. */
+ const float *viewport_size = DRW_viewport_size_get();
+ const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ dtxl->color = GPU_texture_create_2D(size[0], size[1], GPU_RGBA8, NULL, NULL);
+ dtxl->depth = GPU_texture_create_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
+
+ if (!(dtxl->depth && dtxl->color)) {
+ return false;
+ }
+
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ bool ok = true;
+ ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
+
+ return ok;
+}
+
+static void workbench_render_framebuffers_finish(void)
+{
+}
+
+void workbench_render(WORKBENCH_Data *data, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ Depsgraph *depsgraph = draw_ctx->depsgraph;
+ workbench_render_matrices_init(engine, depsgraph);
+
+ if (!workbench_render_framebuffers_init()) {
+ RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers");
+ return;
+ }
+
+ /* Init engine. */
+ workbench_deferred_engine_init(data);
+
+ /* Init objects. */
+ workbench_deferred_cache_init(data);
+ DRW_render_object_iter(data, engine, depsgraph, workbench_render_cache);
+ workbench_deferred_cache_finish(data);
+ DRW_render_instance_buffer_finish();
+
+ /* Draw. */
+ int num_samples = workbench_taa_calculate_num_iterations(data);
+ for (int sample = 0; sample < num_samples; sample++) {
+ if (RE_engine_test_break(engine)) {
+ break;
+ }
+
+ workbench_deferred_draw_background(data);
+ workbench_deferred_draw_scene(data);
+ }
+
+ workbench_deferred_draw_finish(data);
+
+ /* Write render output. */
+ const char *viewname = RE_GetActiveRenderView(engine->re);
+ RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
+
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ GPU_framebuffer_bind(dfbl->color_only_fb);
+ GPU_framebuffer_read_color(dfbl->color_only_fb,
+ rect->xmin, rect->ymin,
+ BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+ 4, 0, rp->rect);
+
+ workbench_render_framebuffers_finish();
+}
+
+void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
+{
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+}
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
new file mode 100644
index 00000000000..ea4152486af
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018, 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 workbench_volume.c
+ * \ingroup draw_engine
+ */
+
+#include "workbench_private.h"
+
+#include "BKE_modifier.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_object_force_types.h"
+#include "DNA_smoke_types.h"
+
+#include "GPU_draw.h"
+
+static struct {
+ struct GPUShader *volume_sh;
+ struct GPUShader *volume_slice_sh;
+} e_data = {NULL};
+
+extern char datatoc_workbench_volume_vert_glsl[];
+extern char datatoc_workbench_volume_frag_glsl[];
+
+void workbench_volume_engine_init(void)
+{
+ if (!e_data.volume_sh) {
+ e_data.volume_sh = DRW_shader_create(
+ datatoc_workbench_volume_vert_glsl, NULL,
+ datatoc_workbench_volume_frag_glsl, NULL);
+ e_data.volume_slice_sh = DRW_shader_create(
+ datatoc_workbench_volume_vert_glsl, NULL,
+ datatoc_workbench_volume_frag_glsl, "#define VOLUME_SLICE");
+ }
+}
+
+void workbench_volume_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.volume_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volume_slice_sh);
+}
+
+void workbench_volume_cache_init(WORKBENCH_Data *vedata)
+{
+ vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | DRW_STATE_CULL_FRONT);
+}
+
+void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ SmokeDomainSettings *sds = smd->domain;
+ WORKBENCH_PrivateData *wpd = vedata->stl->g_data;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* Don't show smoke before simulation starts, this could be made an option in the future. */
+ if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) {
+ return;
+ }
+
+ wpd->volumes_do = true;
+
+ if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+ GPU_create_smoke(smd, 0);
+ }
+ else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+ GPU_create_smoke(smd, 1);
+ }
+
+ if (sds->tex == NULL) {
+ return;
+ }
+
+ if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED &&
+ sds->axis_slice_method == AXIS_SLICE_SINGLE)
+ {
+ float invviewmat[4][4];
+ DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+
+ const int axis = (sds->slice_axis == SLICE_AXIS_AUTO)
+ ? axis_dominant_v3_single(invviewmat[2])
+ : sds->slice_axis - 1;
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_slice_sh, vedata->psl->volume_pass);
+ DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth);
+ DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
+ DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT);
+ BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd));
+
+ /* TODO Flame rendering */
+ /* TODO COBA Rendering */
+
+ DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob);
+ }
+ else {
+ int max_slices = max_iii(sds->res[0], sds->res[1], sds->res[2]) * sds->slice_per_voxel;
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_sh, vedata->psl->volume_pass);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex);
+ DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness);
+ DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slices);
+ /* TODO FIXME : This step size is in object space but the ray itself
+ * is NOT unit length in object space so the required number of subdivisions
+ * is tricky to get. */
+ DRW_shgroup_uniform_float_copy(grp, "stepLength", 8.0f / max_slices);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
+ BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd));
+
+ /* TODO Flame rendering */
+ /* TODO COBA Rendering */
+
+ DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob);
+ }
+}
+
+void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd)
+{
+ /* Free Smoke Textures after rendering */
+ /* XXX This is a waste of processing and GPU bandwidth if nothing
+ * is updated. But the problem is since Textures are stored in the
+ * modifier we don't want them to take precious VRAM if the
+ * modifier is not used for display. We should share them for
+ * all viewport in a redraw at least. */
+ for (LinkData *link = wpd->smoke_domains.first; link; link = link->next) {
+ SmokeModifierData *smd = (SmokeModifierData *)link->data;
+ GPU_free_smoke(smd);
+ }
+ BLI_freelistN(&wpd->smoke_domains);
+}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 4d1b8269494..0812fe0bbe7 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -55,6 +55,7 @@
#include "draw_view.h"
#include "draw_manager_profiling.h"
+#include "draw_debug.h"
#include "MEM_guardedalloc.h"
@@ -70,7 +71,7 @@ struct GPUMaterial;
struct GPUTexture;
struct GPUUniformBuffer;
struct Object;
-struct Gwn_Batch;
+struct GPUBatch;
struct DefaultFramebufferList;
struct DefaultTextureList;
struct DRWTextStore;
@@ -119,11 +120,21 @@ typedef char DRWViewportEmptyList;
if (dfbl->multisample_fb != NULL) { \
DRW_stats_query_start("Multisample Resolve"); \
GPU_framebuffer_bind(dfbl->default_fb); \
- DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color); \
+ DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, true); \
DRW_stats_query_end(); \
} \
}
+#define MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl) { \
+ if (dfbl->multisample_fb != NULL) { \
+ DRW_stats_query_start("Multisample Resolve"); \
+ GPU_framebuffer_bind(dfbl->default_fb); \
+ DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, false); \
+ DRW_stats_query_end(); \
+ } \
+}
+
+
typedef struct DrawEngineDataSize {
@@ -224,9 +235,10 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
} \
} while (0)
-void DRW_transform_to_display(struct GPUTexture *tex);
+void DRW_transform_to_display(struct GPUTexture *tex, bool use_view_settings);
+void DRW_transform_none(struct GPUTexture *tex);
void DRW_multisamples_resolve(
- struct GPUTexture *src_depth, struct GPUTexture *src_color);
+ struct GPUTexture *src_depth, struct GPUTexture *src_color, bool use_depth);
/* Shaders */
struct GPUShader *DRW_shader_create(
@@ -240,14 +252,14 @@ 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);
-struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options, bool no_deferred);
-struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options, bool no_deferred);
+struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options, bool deferred);
+struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options, bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(
struct Scene *scene, struct World *wo, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred);
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred);
struct GPUMaterial *DRW_shader_create_from_material(
struct Scene *scene, struct Material *ma, const void *engine_type, int options,
- const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred);
+ const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred);
void DRW_shader_free(struct GPUShader *shader);
#define DRW_SHADER_FREE_SAFE(shader) do { \
if (shader != NULL) { \
@@ -304,7 +316,7 @@ typedef struct DRWInstanceAttribFormat {
int components;
} DRWInstanceAttribFormat;
-struct Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize);
+struct GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize);
#define DRW_shgroup_instance_format(format, ...) do { \
if (format == NULL) { \
DRWInstanceAttribFormat drw_format[] = __VA_ARGS__;\
@@ -315,25 +327,25 @@ struct Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrib
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_instance_create(
- struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob,
- struct Gwn_VertFormat *format);
+ struct GPUMaterial *material, DRWPass *pass, struct GPUBatch *geom, struct Object *ob,
+ struct GPUVertFormat *format);
DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, DRWPass *pass, int size);
DRWShadingGroup *DRW_shgroup_instance_create(
- struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format);
+ struct GPUShader *shader, DRWPass *pass, struct GPUBatch *geom, struct GPUVertFormat *format);
DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(
- struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format);
+ struct GPUShader *shader, DRWPass *pass, struct GPUVertFormat *format);
DRWShadingGroup *DRW_shgroup_line_batch_create(
struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(
struct GPUShader *shader, DRWPass *pass, int size);
DRWShadingGroup *DRW_shgroup_transform_feedback_create(
- struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target);
+ struct GPUShader *shader, DRWPass *pass, struct GPUVertBuf *tf_target);
typedef void (DRWCallGenerateFn)(
DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, struct Gwn_Batch *geom),
+ void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom),
void *user_data);
/* return final visibility */
@@ -341,27 +353,27 @@ typedef bool (DRWCallVisibilityFn)(
bool vis_in,
void *user_data);
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch);
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch);
void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
-void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4]);
void DRW_shgroup_call_range_add(
- DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count);
+ DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count);
void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, uint point_len, float (*obmat)[4]);
void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, uint line_count, float (*obmat)[4]);
void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, uint tria_count, float (*obmat)[4]);
void DRW_shgroup_call_object_procedural_triangles_culled_add(DRWShadingGroup *shgroup, uint tria_count, struct Object *ob);
-void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, bool bypass_culling);
+void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, struct GPUBatch *geom, struct Object *ob, bool bypass_culling);
#define DRW_shgroup_call_object_add(shgroup, geom, ob) DRW_shgroup_call_object_add_ex(shgroup, geom, ob, false)
#define DRW_shgroup_call_object_add_no_cull(shgroup, geom, ob) DRW_shgroup_call_object_add_ex(shgroup, geom, ob, true)
void DRW_shgroup_call_object_add_with_callback(
- DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob,
+ DRWShadingGroup *shgroup, struct GPUBatch *geom, struct Object *ob,
DRWCallVisibilityFn *callback, void *user_data);
/* Used for drawing a batch with instancing without instance attribs. */
void DRW_shgroup_call_instances_add(
- DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], uint *count);
+ DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4], uint *count);
void DRW_shgroup_call_object_instances_add(
- DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, uint *count);
+ DRWShadingGroup *shgroup, struct GPUBatch *geom, struct Object *ob, uint *count);
void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
void DRW_shgroup_call_generate_add(
DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]);
@@ -400,6 +412,8 @@ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, co
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value);
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value);
+bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
+
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
void DRW_pass_state_set(DRWPass *pass, DRWState state);
@@ -408,6 +422,8 @@ void DRW_pass_state_remove(DRWPass *pass, DRWState state);
void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData);
void DRW_pass_sort_shgroup_z(DRWPass *pass);
+bool DRW_pass_is_empty(DRWPass *pass);
+
/* Viewport */
typedef enum {
/* keep in sync with the union struct DRWMatrixState. */
diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c
index e634710980a..7ddcb306cea 100644
--- a/source/blender/draw/intern/draw_anim_viz.c
+++ b/source/blender/draw/intern/draw_anim_viz.c
@@ -90,44 +90,46 @@ typedef struct MPATH_Data {
MPATH_StorageList *stl;
} MPATH_Data;
-struct {
+#if 0
+static struct {
GPUShader *mpath_line_sh;
GPUShader *mpath_points_sh;
} e_data = {0};
+#endif
/* *************************** Path Cache *********************************** */
/* Just convert the CPU cache to GPU cache. */
-static Gwn_VertBuf *mpath_vbo_get(bMotionPath *mpath)
+static GPUVertBuf *mpath_vbo_get(bMotionPath *mpath)
{
if (!mpath->points_vbo) {
- Gwn_VertFormat format = {0};
+ GPUVertFormat format = {0};
/* Match structure of bMotionPathVert. */
- uint pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- GWN_vertformat_attr_add(&format, "flag", GWN_COMP_I32, 1, GWN_FETCH_INT);
- mpath->points_vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
+ uint pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "flag", GPU_COMP_I32, 1, GPU_FETCH_INT);
+ mpath->points_vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
/* meh... a useless memcpy. */
- Gwn_VertBufRaw raw_data;
- GWN_vertbuf_attr_get_raw_data(mpath->points_vbo, pos, &raw_data);
- memcpy(GWN_vertbuf_raw_step(&raw_data), mpath->points, sizeof(bMotionPathVert) * mpath->length);
+ GPUVertBufRaw raw_data;
+ GPU_vertbuf_attr_get_raw_data(mpath->points_vbo, pos, &raw_data);
+ memcpy(GPU_vertbuf_raw_step(&raw_data), mpath->points, sizeof(bMotionPathVert) * mpath->length);
}
return mpath->points_vbo;
}
-static Gwn_Batch *mpath_batch_line_get(bMotionPath *mpath)
+static GPUBatch *mpath_batch_line_get(bMotionPath *mpath)
{
if (!mpath->batch_line) {
- mpath->batch_line = GWN_batch_create(GWN_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
+ mpath->batch_line = GPU_batch_create(GPU_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_line;
}
-static Gwn_Batch *mpath_batch_points_get(bMotionPath *mpath)
+static GPUBatch *mpath_batch_points_get(bMotionPath *mpath)
{
if (!mpath->batch_points) {
- mpath->batch_points = GWN_batch_create(GWN_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
+ mpath->batch_points = GPU_batch_create(GPU_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_points;
}
@@ -322,12 +324,19 @@ static void MPATH_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ if (DRW_pass_is_empty(psl->lines) &&
+ DRW_pass_is_empty(psl->points))
+ {
+ /* Nothing to draw. */
+ return;
+ }
+
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl)
DRW_draw_pass(psl->lines);
DRW_draw_pass(psl->points);
- MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
+ MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl)
}
/* *************************** Draw Engine Defines ****************************** */
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 9bc8b70b67c..a84b3fdeb41 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -95,6 +95,8 @@ static struct {
DRWShadingGroup *lines_ik_spline;
DRWArmaturePasses passes;
+
+ bool transparent;
} g_data = {NULL};
@@ -134,12 +136,13 @@ static void drw_shgroup_bone_octahedral(
const float bone_color[4], const float hint_color[4], const float outline_color[4])
{
if (g_data.bone_octahedral_outline == NULL) {
- struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_get();
+ struct GPUBatch *geom = DRW_cache_bone_octahedral_wire_get();
g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom);
}
if (g_data.bone_octahedral_solid == NULL) {
- struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get();
- g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom);
+ struct GPUBatch *geom = DRW_cache_bone_octahedral_get();
+ g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom,
+ g_data.transparent);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@@ -155,12 +158,12 @@ static void drw_shgroup_bone_box(
const float bone_color[4], const float hint_color[4], const float outline_color[4])
{
if (g_data.bone_box_wire == NULL) {
- struct Gwn_Batch *geom = DRW_cache_bone_box_wire_get();
+ struct GPUBatch *geom = DRW_cache_bone_box_wire_get();
g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom);
}
if (g_data.bone_box_solid == NULL) {
- struct Gwn_Batch *geom = DRW_cache_bone_box_get();
- g_data.bone_box_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom);
+ struct GPUBatch *geom = DRW_cache_bone_box_get();
+ g_data.bone_box_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom, g_data.transparent);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@@ -234,13 +237,13 @@ static void drw_shgroup_bone_envelope(
g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire);
}
if (g_data.bone_point_solid == NULL) {
- g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid);
+ g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid, g_data.transparent);
}
if (g_data.bone_envelope_wire == NULL) {
g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.passes.bone_wire);
}
if (g_data.bone_envelope_solid == NULL) {
- g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.passes.bone_solid);
+ g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.passes.bone_solid, g_data.transparent);
/* We can have a lot of overdraw if we don't do this. Also envelope are not subject to
* inverted matrix. */
DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK);
@@ -319,9 +322,9 @@ static void drw_shgroup_bone_custom_solid(
Object *custom)
{
/* grr, not re-using instances! */
- struct Gwn_Batch *surf = DRW_cache_object_surface_get(custom);
- struct Gwn_Batch *edges = DRW_cache_object_edge_detection_get(custom, NULL);
- struct Gwn_Batch *ledges = DRW_cache_object_loose_edges_get(custom);
+ struct GPUBatch *surf = DRW_cache_object_surface_get(custom);
+ struct GPUBatch *edges = DRW_cache_object_edge_detection_get(custom, NULL);
+ struct GPUBatch *ledges = DRW_cache_object_loose_edges_get(custom);
float final_bonemat[4][4];
if (surf || edges || ledges) {
@@ -329,7 +332,8 @@ static void drw_shgroup_bone_custom_solid(
}
if (surf) {
- DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, surf);
+ DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, surf,
+ g_data.transparent);
DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color);
}
@@ -352,7 +356,7 @@ static void drw_shgroup_bone_custom_wire(
const float color[4], Object *custom)
{
/* grr, not re-using instances! */
- struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom);
+ struct GPUBatch *geom = DRW_cache_object_wire_outline_get(custom);
if (geom) {
DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom);
float final_bonemat[4][4], final_color[4];
@@ -372,7 +376,7 @@ static void drw_shgroup_bone_point(
g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire);
}
if (g_data.bone_point_solid == NULL) {
- g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid);
+ g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid, g_data.transparent);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@@ -456,7 +460,7 @@ static void drw_shgroup_bone_ik_spline_lines(const float start[3], const float e
* \{ */
/* global here is reset before drawing each bone */
-struct {
+static struct {
const ThemeWireColor *bcolor;
} g_color;
@@ -1623,7 +1627,7 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
/* We can't safely draw non-updated pose, might contain NULL bone pointers... */
if (ob->pose->flag & POSE_RECALC) {
- BKE_pose_rebuild(ob, arm);
+ return;
}
// if (!(base->flag & OB_FROMDUPLI)) // TODO
@@ -1732,11 +1736,12 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
/**
* This function set the object space to use for all subsequent `DRW_shgroup_bone_*` calls.
*/
-static void drw_shgroup_armature(Object *ob, DRWArmaturePasses passes)
+static void drw_shgroup_armature(Object *ob, DRWArmaturePasses passes, bool transp)
{
memset(&g_data, 0x0, sizeof(g_data));
g_data.ob = ob;
g_data.passes = passes;
+ g_data.transparent = transp;
memset(&g_color, 0x0, sizeof(g_color));
}
@@ -1745,19 +1750,19 @@ void DRW_shgroup_armature_object(Object *ob, ViewLayer *view_layer, DRWArmatureP
float *color;
DRW_object_wire_theme_get(ob, view_layer, &color);
passes.bone_envelope = NULL; /* Don't do envelope distance in object mode. */
- drw_shgroup_armature(ob, passes);
+ drw_shgroup_armature(ob, passes, false);
draw_armature_pose(ob, color);
}
-void DRW_shgroup_armature_pose(Object *ob, DRWArmaturePasses passes)
+void DRW_shgroup_armature_pose(Object *ob, DRWArmaturePasses passes, bool transp)
{
- drw_shgroup_armature(ob, passes);
+ drw_shgroup_armature(ob, passes, transp);
draw_armature_pose(ob, NULL);
}
-void DRW_shgroup_armature_edit(Object *ob, DRWArmaturePasses passes)
+void DRW_shgroup_armature_edit(Object *ob, DRWArmaturePasses passes, bool transp)
{
- drw_shgroup_armature(ob, passes);
+ drw_shgroup_armature(ob, passes, transp);
draw_armature_edit(ob);
}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 53e39671c78..85f38e2f5eb 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -47,80 +47,86 @@
/* Batch's only (free'd as an array) */
static struct DRWShapeCache {
- Gwn_Batch *drw_single_vertice;
- Gwn_Batch *drw_cursor;
- Gwn_Batch *drw_cursor_only_circle;
- Gwn_Batch *drw_fullscreen_quad;
- Gwn_Batch *drw_quad;
- Gwn_Batch *drw_sphere;
- Gwn_Batch *drw_screenspace_circle;
- Gwn_Batch *drw_plain_axes;
- Gwn_Batch *drw_single_arrow;
- Gwn_Batch *drw_cube;
- Gwn_Batch *drw_circle;
- Gwn_Batch *drw_square;
- Gwn_Batch *drw_line;
- Gwn_Batch *drw_line_endpoints;
- Gwn_Batch *drw_empty_sphere;
- Gwn_Batch *drw_empty_cone;
- Gwn_Batch *drw_arrows;
- Gwn_Batch *drw_axis_names;
- Gwn_Batch *drw_image_plane;
- Gwn_Batch *drw_image_plane_wire;
- Gwn_Batch *drw_field_wind;
- Gwn_Batch *drw_field_force;
- Gwn_Batch *drw_field_vortex;
- Gwn_Batch *drw_field_tube_limit;
- Gwn_Batch *drw_field_cone_limit;
- Gwn_Batch *drw_lamp;
- Gwn_Batch *drw_lamp_shadows;
- Gwn_Batch *drw_lamp_sunrays;
- Gwn_Batch *drw_lamp_area_square;
- Gwn_Batch *drw_lamp_area_disk;
- Gwn_Batch *drw_lamp_hemi;
- Gwn_Batch *drw_lamp_spot;
- Gwn_Batch *drw_lamp_spot_square;
- Gwn_Batch *drw_speaker;
- Gwn_Batch *drw_lightprobe_cube;
- Gwn_Batch *drw_lightprobe_planar;
- Gwn_Batch *drw_lightprobe_grid;
- Gwn_Batch *drw_bone_octahedral;
- Gwn_Batch *drw_bone_octahedral_wire;
- Gwn_Batch *drw_bone_box;
- Gwn_Batch *drw_bone_box_wire;
- Gwn_Batch *drw_bone_wire_wire;
- Gwn_Batch *drw_bone_envelope;
- Gwn_Batch *drw_bone_envelope_outline;
- Gwn_Batch *drw_bone_point;
- Gwn_Batch *drw_bone_point_wire;
- Gwn_Batch *drw_bone_stick;
- Gwn_Batch *drw_bone_arrows;
- Gwn_Batch *drw_camera;
- Gwn_Batch *drw_camera_frame;
- Gwn_Batch *drw_camera_tria;
- Gwn_Batch *drw_camera_focus;
- Gwn_Batch *drw_particle_cross;
- Gwn_Batch *drw_particle_circle;
- Gwn_Batch *drw_particle_axis;
+ GPUBatch *drw_single_vertice;
+ GPUBatch *drw_cursor;
+ GPUBatch *drw_cursor_only_circle;
+ GPUBatch *drw_fullscreen_quad;
+ GPUBatch *drw_fullscreen_quad_texcoord;
+ GPUBatch *drw_quad;
+ GPUBatch *drw_sphere;
+ GPUBatch *drw_screenspace_circle;
+ GPUBatch *drw_plain_axes;
+ GPUBatch *drw_single_arrow;
+ GPUBatch *drw_cube;
+ GPUBatch *drw_circle;
+ GPUBatch *drw_square;
+ GPUBatch *drw_line;
+ GPUBatch *drw_line_endpoints;
+ GPUBatch *drw_empty_cube;
+ GPUBatch *drw_empty_sphere;
+ GPUBatch *drw_empty_cylinder;
+ GPUBatch *drw_empty_capsule_body;
+ GPUBatch *drw_empty_capsule_cap;
+ GPUBatch *drw_empty_cone;
+ GPUBatch *drw_arrows;
+ GPUBatch *drw_axis_names;
+ GPUBatch *drw_image_plane;
+ GPUBatch *drw_image_plane_wire;
+ GPUBatch *drw_field_wind;
+ GPUBatch *drw_field_force;
+ GPUBatch *drw_field_vortex;
+ GPUBatch *drw_field_tube_limit;
+ GPUBatch *drw_field_cone_limit;
+ GPUBatch *drw_lamp;
+ GPUBatch *drw_lamp_shadows;
+ GPUBatch *drw_lamp_sunrays;
+ GPUBatch *drw_lamp_area_square;
+ GPUBatch *drw_lamp_area_disk;
+ GPUBatch *drw_lamp_hemi;
+ GPUBatch *drw_lamp_spot;
+ GPUBatch *drw_lamp_spot_square;
+ GPUBatch *drw_speaker;
+ GPUBatch *drw_lightprobe_cube;
+ GPUBatch *drw_lightprobe_planar;
+ GPUBatch *drw_lightprobe_grid;
+ GPUBatch *drw_bone_octahedral;
+ GPUBatch *drw_bone_octahedral_wire;
+ GPUBatch *drw_bone_box;
+ GPUBatch *drw_bone_box_wire;
+ GPUBatch *drw_bone_wire_wire;
+ GPUBatch *drw_bone_envelope;
+ GPUBatch *drw_bone_envelope_outline;
+ GPUBatch *drw_bone_point;
+ GPUBatch *drw_bone_point_wire;
+ GPUBatch *drw_bone_stick;
+ GPUBatch *drw_bone_arrows;
+ GPUBatch *drw_camera;
+ GPUBatch *drw_camera_frame;
+ GPUBatch *drw_camera_tria;
+ GPUBatch *drw_camera_focus;
+ GPUBatch *drw_particle_cross;
+ GPUBatch *drw_particle_circle;
+ GPUBatch *drw_particle_axis;
+ GPUBatch *drw_gpencil_axes;
} SHC = {NULL};
void DRW_shape_cache_free(void)
{
- uint i = sizeof(SHC) / sizeof(Gwn_Batch *);
- Gwn_Batch **batch = (Gwn_Batch **)&SHC;
+ uint i = sizeof(SHC) / sizeof(GPUBatch *);
+ GPUBatch **batch = (GPUBatch **)&SHC;
while (i--) {
- GWN_BATCH_DISCARD_SAFE(*batch);
+ GPU_BATCH_DISCARD_SAFE(*batch);
batch++;
}
}
void DRW_shape_cache_reset(void)
{
- uint i = sizeof(SHC) / sizeof(Gwn_Batch *);
- Gwn_Batch **batch = (Gwn_Batch **)&SHC;
+ uint i = sizeof(SHC) / sizeof(GPUBatch *);
+ GPUBatch **batch = (GPUBatch **)&SHC;
while (i--) {
if (*batch) {
- gwn_batch_vao_cache_clear(*batch);
+ GPU_batch_vao_cache_clear(*batch);
}
batch++;
}
@@ -132,22 +138,22 @@ void DRW_shape_cache_reset(void)
* \{ */
static void UNUSED_FUNCTION(add_fancy_edge)(
- Gwn_VertBuf *vbo, uint pos_id, uint n1_id, uint n2_id,
+ GPUVertBuf *vbo, uint pos_id, uint n1_id, uint n2_id,
uint *v_idx, const float co1[3], const float co2[3],
const float n1[3], const float n2[3])
{
- GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
- GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
- GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1);
+ GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
+ GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
+ GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1);
- GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
- GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
- GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2);
+ GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
+ GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
+ GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2);
}
#if 0 /* UNUSED */
static void add_lat_lon_vert(
- Gwn_VertBuf *vbo, uint pos_id, uint nor_id,
+ GPUVertBuf *vbo, uint pos_id, uint nor_id,
uint *v_idx, const float rad, const float lat, const float lon)
{
float pos[3], nor[3];
@@ -156,23 +162,23 @@ static void add_lat_lon_vert(
nor[2] = sinf(lat) * sinf(lon);
mul_v3_v3fl(pos, nor, rad);
- GWN_vertbuf_attr_set(vbo, nor_id, *v_idx, nor);
- GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos);
+ GPU_vertbuf_attr_set(vbo, nor_id, *v_idx, nor);
+ GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos);
}
#endif
-static Gwn_VertBuf *fill_arrows_vbo(const float scale)
+static GPUVertBuf *fill_arrows_vbo(const float scale)
{
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Line */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6 * 3);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 6 * 3);
float v1[3] = {0.0, 0.0, 0.0};
float v2[3] = {0.0, 0.0, 0.0};
@@ -184,21 +190,21 @@ static Gwn_VertBuf *fill_arrows_vbo(const float scale)
v2[axis] = 1.0f;
mul_v3_v3fl(vtmp1, v1, scale);
mul_v3_v3fl(vtmp2, v2, scale);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 1, vtmp2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2);
v1[arrow_axis] = 0.08f;
mul_v3_v3fl(vtmp1, v1, scale);
mul_v3_v3fl(vtmp2, v2, scale);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2);
/* reset v1 & v2 to zero */
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
@@ -207,18 +213,18 @@ static Gwn_VertBuf *fill_arrows_vbo(const float scale)
return vbo;
}
-static Gwn_VertBuf *sphere_wire_vbo(const float rad)
+static GPUVertBuf *sphere_wire_vbo(const float rad)
{
#define NSEGMENTS 32
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2 * 3);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2 * 3);
/* a single ring of vertices */
float p[NSEGMENTS][2];
@@ -236,14 +242,16 @@ static Gwn_VertBuf *sphere_wire_vbo(const float rad)
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];
-
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + j + (NSEGMENTS * 2 * axis), v);
+ if (axis == 0) {
+ ARRAY_SET_ITEMS(v, cv[0], cv[1], 0.0f);
+ }
+ else if (axis == 1) {
+ ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
+ }
+ else {
+ ARRAY_SET_ITEMS(v, 0.0f, cv[0], cv[1]);
+ }
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + j + (NSEGMENTS * 2 * axis), v);
}
}
}
@@ -254,7 +262,7 @@ static Gwn_VertBuf *sphere_wire_vbo(const float rad)
/* Quads */
/* Use this one for rendering fullscreen passes. For 3D objects use DRW_cache_quad_get(). */
-Gwn_Batch *DRW_cache_fullscreen_quad_get(void)
+GPUBatch *DRW_cache_fullscreen_quad_get(void)
{
if (!SHC.drw_fullscreen_quad) {
/* Use a triangle instead of a real quad */
@@ -263,56 +271,57 @@ Gwn_Batch *DRW_cache_fullscreen_quad_get(void)
float uvs[3][2] = {{ 0.0f, 0.0f}, { 2.0f, 0.0f}, { 0.0f, 2.0f}};
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, uvs; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "texCoord");
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 3);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 3);
for (int i = 0; i < 3; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
}
- SHC.drw_fullscreen_quad = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_fullscreen_quad = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_fullscreen_quad;
}
/* Just a regular quad with 4 vertices. */
-Gwn_Batch *DRW_cache_quad_get(void)
+GPUBatch *DRW_cache_quad_get(void)
{
if (!SHC.drw_quad) {
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}, {1.0f, 1.0f}, { 0.0f, 1.0f}};
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, uvs; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4);
for (int i = 0; i < 4; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
}
- SHC.drw_quad = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_quad;
}
/* Sphere */
-Gwn_Batch *DRW_cache_sphere_get(void)
+GPUBatch *DRW_cache_sphere_get(void)
{
if (!SHC.drw_sphere) {
SHC.drw_sphere = gpu_batch_sphere(32, 24);
@@ -327,7 +336,7 @@ Gwn_Batch *DRW_cache_sphere_get(void)
/** \name Common
* \{ */
-Gwn_Batch *DRW_cache_cube_get(void)
+GPUBatch *DRW_cache_cube_get(void)
{
if (!SHC.drw_cube) {
const GLfloat verts[8][3] = {
@@ -341,57 +350,105 @@ Gwn_Batch *DRW_cache_cube_get(void)
{ 1.0f, 1.0f, 1.0f}
};
+ const uint indices[36] = {
+ 0, 1, 2,
+ 1, 3, 2,
+ 0, 4, 1,
+ 4, 5, 1,
+ 6, 5, 4,
+ 6, 7, 5,
+ 2, 7, 6,
+ 2, 3, 7,
+ 3, 1, 7,
+ 1, 5, 7,
+ 0, 2, 4,
+ 2, 6, 4,
+ };
+
+ /* Position Only 3D format */
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 36);
+
+ for (int i = 0; i < 36; ++i) {
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
+ }
+
+ SHC.drw_cube = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_cube;
+}
+
+GPUBatch *DRW_cache_empty_cube_get(void)
+{
+ if (!SHC.drw_empty_cube) {
+ const GLfloat verts[8][3] = {
+ {-1.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, -1.0f, -1.0f},
+ { 1.0f, -1.0f, 1.0f},
+ { 1.0f, 1.0f, -1.0f},
+ { 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};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 24);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 24);
for (int i = 0; i < 24; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
}
- SHC.drw_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_empty_cube = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
- return SHC.drw_cube;
+ return SHC.drw_empty_cube;
}
-Gwn_Batch *DRW_cache_circle_get(void)
+GPUBatch *DRW_cache_circle_get(void)
{
#define CIRCLE_RESOL 64
if (!SHC.drw_circle) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = 0.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
}
- SHC.drw_circle = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_circle = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_circle;
#undef CIRCLE_RESOL
}
-Gwn_Batch *DRW_cache_square_get(void)
+GPUBatch *DRW_cache_square_get(void)
{
if (!SHC.drw_square) {
float p[4][3] = {{ 1.0f, 0.0f, 1.0f},
@@ -400,26 +457,26 @@ Gwn_Batch *DRW_cache_square_get(void)
{-1.0f, 0.0f, 1.0f}};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 8);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 8);
for (int i = 0; i < 4; i++) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2, p[i % 4]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + 1, p[(i + 1) % 4]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2, p[i % 4]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + 1, p[(i + 1) % 4]);
}
- SHC.drw_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_square;
}
-Gwn_Batch *DRW_cache_single_line_get(void)
+GPUBatch *DRW_cache_single_line_get(void)
{
/* Z axis line */
if (!SHC.drw_line) {
@@ -427,24 +484,24 @@ Gwn_Batch *DRW_cache_single_line_get(void)
float v2[3] = {0.0f, 0.0f, 1.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
- SHC.drw_line = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_line = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_line;
}
-Gwn_Batch *DRW_cache_single_line_endpoints_get(void)
+GPUBatch *DRW_cache_single_line_endpoints_get(void)
{
/* Z axis line */
if (!SHC.drw_line_endpoints) {
@@ -452,59 +509,114 @@ Gwn_Batch *DRW_cache_single_line_endpoints_get(void)
float v2[3] = {0.0f, 0.0f, 1.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
- SHC.drw_line_endpoints = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_line_endpoints = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_line_endpoints;
}
-Gwn_Batch *DRW_cache_screenspace_circle_get(void)
+GPUBatch *DRW_cache_screenspace_circle_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_screenspace_circle) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL + 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL + 1);
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));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
}
- SHC.drw_screenspace_circle = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_screenspace_circle = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_screenspace_circle;
#undef CIRCLE_RESOL
}
-/** \} */
+/* Grease Pencil object */
+GPUBatch *DRW_cache_gpencil_axes_get(void)
+{
+ if (!SHC.drw_gpencil_axes) {
+ int axis;
+ float v1[3] = { 0.0f, 0.0f, 0.0f };
+ float v2[3] = { 0.0f, 0.0f, 0.0f };
+
+ /* cube data */
+ const GLfloat verts[8][3] = {
+ { -0.25f, -0.25f, -0.25f },
+ { -0.25f, -0.25f, 0.25f },
+ { -0.25f, 0.25f, -0.25f },
+ { -0.25f, 0.25f, 0.25f },
+ { 0.25f, -0.25f, -0.25f },
+ { 0.25f, -0.25f, 0.25f },
+ { 0.25f, 0.25f, -0.25f },
+ { 0.25f, 0.25f, 0.25f }
+ };
+
+ 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 GPUVertFormat format = { 0 };
+ static uint pos_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+
+ /* alloc 30 elements for cube and 3 axis */
+ GPU_vertbuf_data_alloc(vbo, ARRAY_SIZE(indices) + 6);
+
+ /* draw axis */
+ for (axis = 0; axis < 3; axis++) {
+ v1[axis] = 1.0f;
+ v2[axis] = -1.0f;
+
+ GPU_vertbuf_attr_set(vbo, pos_id, axis * 2, v1);
+ GPU_vertbuf_attr_set(vbo, pos_id, axis * 2 + 1, v2);
+
+ /* reset v1 & v2 to zero for next axis */
+ v1[axis] = v2[axis] = 0.0f;
+ }
+
+ /* draw cube */
+ for (int i = 0; i < 24; ++i) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i + 6, verts[indices[i]]);
+ }
+
+ SHC.drw_gpencil_axes = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_gpencil_axes;
+}
+
/* -------------------------------------------------------------------- */
/** \name Common Object API
- * \{ */
+* \{ */
-Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob)
+GPUBatch *DRW_cache_object_wire_outline_get(Object *ob)
{
switch (ob->type) {
case OB_MESH:
@@ -516,7 +628,7 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob)
}
}
-Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
+GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
{
switch (ob->type) {
case OB_MESH:
@@ -540,7 +652,7 @@ void DRW_cache_object_face_wireframe_get(
}
}
-Gwn_Batch *DRW_cache_object_loose_edges_get(struct Object *ob)
+GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
{
switch (ob->type) {
case OB_MESH:
@@ -552,7 +664,7 @@ Gwn_Batch *DRW_cache_object_loose_edges_get(struct Object *ob)
}
}
-Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
+GPUBatch *DRW_cache_object_surface_get(Object *ob)
{
switch (ob->type) {
case OB_MESH:
@@ -570,7 +682,7 @@ Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
}
}
-Gwn_Batch **DRW_cache_object_surface_material_get(
+GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
@@ -605,7 +717,7 @@ Gwn_Batch **DRW_cache_object_surface_material_get(
/** \name Empties
* \{ */
-Gwn_Batch *DRW_cache_plain_axes_get(void)
+GPUBatch *DRW_cache_plain_axes_get(void)
{
if (!SHC.drw_plain_axes) {
int axis;
@@ -613,46 +725,46 @@ Gwn_Batch *DRW_cache_plain_axes_get(void)
float v2[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 6);
for (axis = 0; axis < 3; axis++) {
v1[axis] = 1.0f;
v2[axis] = -1.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2 + 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 2, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 2 + 1, v2);
/* reset v1 & v2 to zero for next axis */
v1[axis] = v2[axis] = 0.0f;
}
- SHC.drw_plain_axes = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_plain_axes = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_plain_axes;
}
-Gwn_Batch *DRW_cache_single_arrow_get(void)
+GPUBatch *DRW_cache_single_arrow_get(void)
{
if (!SHC.drw_single_arrow) {
float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Square Pyramid */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 12);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 12);
v2[0] = 0.035f; v2[1] = 0.035f;
v3[0] = -0.035f; v3[1] = 0.035f;
@@ -668,26 +780,26 @@ Gwn_Batch *DRW_cache_single_arrow_get(void)
v3[0] = -v3[0];
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 0, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 1, v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 2, v3);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 2, v3);
}
- SHC.drw_single_arrow = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_single_arrow = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_single_arrow;
}
-Gwn_Batch *DRW_cache_empty_sphere_get(void)
+GPUBatch *DRW_cache_empty_sphere_get(void)
{
if (!SHC.drw_empty_sphere) {
- Gwn_VertBuf *vbo = sphere_wire_vbo(1.0f);
- SHC.drw_empty_sphere = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GPUVertBuf *vbo = sphere_wire_vbo(1.0f);
+ SHC.drw_empty_sphere = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_empty_sphere;
}
-Gwn_Batch *DRW_cache_empty_cone_get(void)
+GPUBatch *DRW_cache_empty_cone_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_empty_cone) {
@@ -700,14 +812,14 @@ Gwn_Batch *DRW_cache_empty_cone_get(void)
}
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
@@ -715,153 +827,291 @@ Gwn_Batch *DRW_cache_empty_cone_get(void)
cv[1] = p[(i) % NSEGMENTS][1];
/* cone sides */
- v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
- v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
+ ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
+ ARRAY_SET_ITEMS(v, 0.0f, 2.0f, 0.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
/* end ring */
- v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v);
+ ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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];
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
+ ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
}
- SHC.drw_empty_cone = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_empty_cone = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_empty_cone;
#undef NSEGMENTS
}
-Gwn_Batch *DRW_cache_arrows_get(void)
+GPUBatch *DRW_cache_empty_cylinder_get(void)
+{
+#define NSEGMENTS 12
+ if (!SHC.drw_empty_cylinder) {
+ /* 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 GPUVertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 6);
+
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float cv[2], pv[2], v[3];
+ cv[0] = p[(i) % NSEGMENTS][0];
+ cv[1] = p[(i) % NSEGMENTS][1];
+ pv[0] = p[(i + 1) % NSEGMENTS][0];
+ pv[1] = p[(i + 1) % NSEGMENTS][1];
+
+ /* cylinder sides */
+ copy_v3_fl3(v, cv[0], cv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6, v);
+ copy_v3_fl3(v, cv[0], cv[1], 1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 1, v);
+
+ /* top ring */
+ copy_v3_fl3(v, cv[0], cv[1], 1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 2, v);
+ copy_v3_fl3(v, pv[0], pv[1], 1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 3, v);
+
+ /* bottom ring */
+ copy_v3_fl3(v, cv[0], cv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 4, v);
+ copy_v3_fl3(v, pv[0], pv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 5, v);
+ }
+
+ SHC.drw_empty_cylinder = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_empty_cylinder;
+#undef NSEGMENTS
+}
+
+GPUBatch *DRW_cache_empty_capsule_body_get(void)
+{
+ if (!SHC.drw_empty_capsule_body) {
+ const float pos[8][3] = {
+ { 1.0f, 0.0f, 1.0f},
+ { 1.0f, 0.0f, 0.0f},
+ { 0.0f, 1.0f, 1.0f},
+ { 0.0f, 1.0f, 0.0f},
+ {-1.0f, 0.0f, 1.0f},
+ {-1.0f, 0.0f, 0.0f},
+ { 0.0f, -1.0f, 1.0f},
+ { 0.0f, -1.0f, 0.0f}
+ };
+
+ /* Position Only 3D format */
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 8);
+ GPU_vertbuf_attr_fill(vbo, attr_id.pos, pos);
+
+ SHC.drw_empty_capsule_body = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_empty_capsule_body;
+}
+
+GPUBatch *DRW_cache_empty_capsule_cap_get(void)
+{
+#define NSEGMENTS 24 /* Must be multiple of 2. */
+ if (!SHC.drw_empty_capsule_cap) {
+ /* 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 GPUVertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (NSEGMENTS * 2) * 2);
+
+ /* Base circle */
+ int vidx = 0;
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ copy_v2_v2(v, p[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ copy_v2_v2(v, p[(i + 1) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+ for (int i = 0; i < NSEGMENTS / 2; ++i) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ int ci = i % NSEGMENTS;
+ int pi = (i + 1) % NSEGMENTS;
+ /* Y half circle */
+ copy_v3_fl3(v, p[ci][0], 0.0f, p[ci][1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ copy_v3_fl3(v, p[pi][0], 0.0f, p[pi][1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ /* X half circle */
+ copy_v3_fl3(v, 0.0f, p[ci][0], p[ci][1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ copy_v3_fl3(v, 0.0f, p[pi][0], p[pi][1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+ SHC.drw_empty_capsule_cap = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_empty_capsule_cap;
+#undef NSEGMENTS
+}
+
+GPUBatch *DRW_cache_arrows_get(void)
{
if (!SHC.drw_arrows) {
- Gwn_VertBuf *vbo = fill_arrows_vbo(1.0f);
+ GPUVertBuf *vbo = fill_arrows_vbo(1.0f);
- SHC.drw_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_arrows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_arrows;
}
-Gwn_Batch *DRW_cache_axis_names_get(void)
+GPUBatch *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 Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
/* Using 3rd component as axis indicator */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Line */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 14);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 14);
/* X */
copy_v3_fl3(v1, -size, size, 0.0f);
copy_v3_fl3(v2, size, -size, 0.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
copy_v3_fl3(v1, size, size, 0.0f);
copy_v3_fl3(v2, -size, -size, 0.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 3, v2);
/* Y */
copy_v3_fl3(v1, -size + 0.25f * size, size, 1.0f);
copy_v3_fl3(v2, 0.0f, 0.0f, 1.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 5, v2);
copy_v3_fl3(v1, size - 0.25f * size, size, 1.0f);
copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 7, v2);
/* Z */
copy_v3_fl3(v1, -size, size, 2.0f);
copy_v3_fl3(v2, size, size, 2.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 8, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 9, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 8, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 9, v2);
copy_v3_fl3(v1, size, size, 2.0f);
copy_v3_fl3(v2, -size, -size, 2.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 10, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 11, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 10, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 11, v2);
copy_v3_fl3(v1, -size, -size, 2.0f);
copy_v3_fl3(v2, size, -size, 2.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 12, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 13, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 12, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 13, v2);
- SHC.drw_axis_names = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_axis_names = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_axis_names;
}
-Gwn_Batch *DRW_cache_image_plane_get(void)
+GPUBatch *DRW_cache_image_plane_get(void)
{
if (!SHC.drw_image_plane) {
const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, texCoords; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.texCoords = GWN_vertformat_attr_add(&format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.texCoords = GPU_vertformat_attr_add(&format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4);
for (uint j = 0; j < 4; j++) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
- GWN_vertbuf_attr_set(vbo, attr_id.texCoords, j, quad[j]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
+ GPU_vertbuf_attr_set(vbo, attr_id.texCoords, j, quad[j]);
}
- SHC.drw_image_plane = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_image_plane = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_image_plane;
}
-Gwn_Batch *DRW_cache_image_plane_wire_get(void)
+GPUBatch *DRW_cache_image_plane_wire_get(void)
{
if (!SHC.drw_image_plane_wire) {
const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4);
for (uint j = 0; j < 4; j++) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
}
- SHC.drw_image_plane_wire = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_image_plane_wire = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_image_plane_wire;
}
/* Force Field */
-Gwn_Batch *DRW_cache_field_wind_get(void)
+GPUBatch *DRW_cache_field_wind_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_wind) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 4);
for (int i = 0; i < 4; i++) {
float z = 0.05f * (float)i;
@@ -869,36 +1119,36 @@ Gwn_Batch *DRW_cache_field_wind_get(void)
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + 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] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
}
}
- SHC.drw_field_wind = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_field_wind = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_field_wind;
#undef CIRCLE_RESOL
}
-Gwn_Batch *DRW_cache_field_force_get(void)
+GPUBatch *DRW_cache_field_force_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_force) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 3);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 3);
for (int i = 0; i < 3; i++) {
float radius = 1.0f + 0.5f * (float)i;
@@ -906,22 +1156,22 @@ Gwn_Batch *DRW_cache_field_force_get(void)
v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = 0.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = 0.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
}
}
- SHC.drw_field_force = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_field_force = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_field_force;
#undef CIRCLE_RESOL
}
-Gwn_Batch *DRW_cache_field_vortex_get(void)
+GPUBatch *DRW_cache_field_vortex_get(void)
{
#define SPIRAL_RESOL 32
if (!SHC.drw_field_vortex) {
@@ -929,36 +1179,36 @@ Gwn_Batch *DRW_cache_field_vortex_get(void)
uint v_idx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, SPIRAL_RESOL * 2 + 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, SPIRAL_RESOL * 2 + 1);
for (int a = SPIRAL_RESOL; a > -1; a--) {
v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
for (int a = 1; a <= SPIRAL_RESOL; a++) {
v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
- SHC.drw_field_vortex = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_field_vortex = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_field_vortex;
#undef SPIRAL_RESOL
}
-Gwn_Batch *DRW_cache_field_tube_limit_get(void)
+GPUBatch *DRW_cache_field_tube_limit_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_tube_limit) {
@@ -966,14 +1216,14 @@ Gwn_Batch *DRW_cache_field_tube_limit_get(void)
uint v_idx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
/* Caps */
for (int i = 0; i < 2; i++) {
@@ -982,12 +1232,12 @@ Gwn_Batch *DRW_cache_field_tube_limit_get(void)
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, 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] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
}
/* Side Edges */
@@ -997,17 +1247,17 @@ Gwn_Batch *DRW_cache_field_tube_limit_get(void)
v[0] = sinf((2.0f * M_PI * a) / 4.0f);
v[1] = cosf((2.0f * M_PI * a) / 4.0f);
v[2] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
}
- SHC.drw_field_tube_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_field_tube_limit = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_field_tube_limit;
#undef CIRCLE_RESOL
}
-Gwn_Batch *DRW_cache_field_cone_limit_get(void)
+GPUBatch *DRW_cache_field_cone_limit_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_cone_limit) {
@@ -1015,14 +1265,14 @@ Gwn_Batch *DRW_cache_field_cone_limit_get(void)
uint v_idx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
/* Caps */
for (int i = 0; i < 2; i++) {
@@ -1031,12 +1281,12 @@ Gwn_Batch *DRW_cache_field_cone_limit_get(void)
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, 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] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
}
/* Side Edges */
@@ -1046,11 +1296,11 @@ Gwn_Batch *DRW_cache_field_cone_limit_get(void)
v[0] = z * sinf((2.0f * M_PI * a) / 4.0f);
v[1] = z * cosf((2.0f * M_PI * a) / 4.0f);
v[2] = z;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
}
}
- SHC.drw_field_cone_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_field_cone_limit = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_field_cone_limit;
#undef CIRCLE_RESOL
@@ -1063,84 +1313,84 @@ Gwn_Batch *DRW_cache_field_cone_limit_get(void)
/** \name Lamps
* \{ */
-Gwn_Batch *DRW_cache_lamp_get(void)
+GPUBatch *DRW_cache_lamp_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_lamp) {
float v[2];
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
for (int a = 0; a < NSEGMENTS * 2; a += 2) {
v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
}
- SHC.drw_lamp = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp;
#undef NSEGMENTS
}
-Gwn_Batch *DRW_cache_lamp_shadows_get(void)
+GPUBatch *DRW_cache_lamp_shadows_get(void)
{
#define NSEGMENTS 10
if (!SHC.drw_lamp_shadows) {
float v[2];
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
for (int a = 0; a < NSEGMENTS * 2; a += 2) {
v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
}
- SHC.drw_lamp_shadows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_shadows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_shadows;
#undef NSEGMENTS
}
-Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
+GPUBatch *DRW_cache_lamp_sunrays_get(void)
{
if (!SHC.drw_lamp_sunrays) {
float v[2], v1[2], v2[2];
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 32);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 32);
for (int a = 0; a < 8; a++) {
v[0] = sinf((2.0f * M_PI * a) / 8.0f);
@@ -1148,86 +1398,86 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
mul_v2_v2fl(v1, v, 1.6f);
mul_v2_v2fl(v2, v, 1.9f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2);
mul_v2_v2fl(v1, v, 2.2f);
mul_v2_v2fl(v2, v, 2.5f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2);
}
- SHC.drw_lamp_sunrays = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_sunrays = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_sunrays;
}
-Gwn_Batch *DRW_cache_lamp_area_square_get(void)
+GPUBatch *DRW_cache_lamp_area_square_get(void)
{
if (!SHC.drw_lamp_area_square) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 8);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 8);
v1[0] = v1[1] = 0.5f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
v1[0] = -0.5f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
v1[1] = -0.5f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 3, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
v1[0] = 0.5f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 5, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
v1[1] = 0.5f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 7, v1);
- SHC.drw_lamp_area_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_area_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_area_square;
}
-Gwn_Batch *DRW_cache_lamp_area_disk_get(void)
+GPUBatch *DRW_cache_lamp_area_disk_get(void)
{
#define NSEGMENTS 32
if (!SHC.drw_lamp_area_disk) {
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 2 * NSEGMENTS);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 2 * NSEGMENTS);
float v[3] = {0.0f, 0.5f, 0.0f};
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v);
for (int a = 1; a < NSEGMENTS; a++) {
v[0] = 0.5f * sinf(2.0f * (float)M_PI * a / NSEGMENTS);
v[1] = 0.5f * cosf(2.0f * (float)M_PI * a / NSEGMENTS);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v);
}
copy_v3_fl3(v, 0.0f, 0.5f, 0.0f);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v);
- SHC.drw_lamp_area_disk = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_area_disk = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_area_disk;
#undef NSEGMENTS
}
-Gwn_Batch *DRW_cache_lamp_hemi_get(void)
+GPUBatch *DRW_cache_lamp_hemi_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_lamp_hemi) {
@@ -1235,26 +1485,26 @@ Gwn_Batch *DRW_cache_lamp_hemi_get(void)
int vidx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(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;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
/* XY plane */
@@ -1262,12 +1512,12 @@ Gwn_Batch *DRW_cache_lamp_hemi_get(void)
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;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
/* YZ plane full circle */
@@ -1276,22 +1526,22 @@ Gwn_Batch *DRW_cache_lamp_hemi_get(void)
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));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
- SHC.drw_lamp_hemi = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_hemi = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_hemi;
#undef CIRCLE_RESOL
}
-Gwn_Batch *DRW_cache_lamp_spot_get(void)
+GPUBatch *DRW_cache_lamp_spot_get(void)
{
#define NSEGMENTS 32
if (!SHC.drw_lamp_spot) {
@@ -1313,16 +1563,16 @@ Gwn_Batch *DRW_cache_lamp_spot_get(void)
}
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, n1, n2; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.n1 = GPU_vertformat_attr_add(&format, "N1", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.n2 = GPU_vertformat_attr_add(&format, "N2", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
@@ -1330,37 +1580,37 @@ Gwn_Batch *DRW_cache_lamp_spot_get(void)
cv[1] = p[i % NSEGMENTS][1];
/* cone sides */
- v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
- v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
+ ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
+ ARRAY_SET_ITEMS(v, 0.0f, 0.0f, 0.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4, n[(i) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 1, n[(i) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4, n[(i + 1) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 1, n[(i + 1) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4, n[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 1, n[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4, n[(i + 1) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 1, n[(i + 1) % NSEGMENTS]);
/* end ring */
- v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v);
+ ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
+ ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 2, n[(i) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 3, n[(i) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 2, neg[(i) % NSEGMENTS]);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 3, neg[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 2, n[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 3, n[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 2, neg[(i) % NSEGMENTS]);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 3, neg[(i) % NSEGMENTS]);
}
- SHC.drw_lamp_spot = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_spot = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_spot;
#undef NSEGMENTS
}
-Gwn_Batch *DRW_cache_lamp_spot_square_get(void)
+GPUBatch *DRW_cache_lamp_spot_square_get(void)
{
if (!SHC.drw_lamp_spot_square) {
float p[5][3] = {{ 0.0f, 0.0f, 0.0f},
@@ -1372,25 +1622,25 @@ Gwn_Batch *DRW_cache_lamp_spot_square_get(void)
uint v_idx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 16);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 16);
/* piramid sides */
for (int i = 1; i <= 4; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]);
}
- SHC.drw_lamp_spot_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lamp_spot_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lamp_spot_square;
}
@@ -1402,7 +1652,7 @@ Gwn_Batch *DRW_cache_lamp_spot_square_get(void)
/** \name Speaker
* \{ */
-Gwn_Batch *DRW_cache_speaker_get(void)
+GPUBatch *DRW_cache_speaker_get(void)
{
if (!SHC.drw_speaker) {
float v[3];
@@ -1410,30 +1660,30 @@ Gwn_Batch *DRW_cache_speaker_get(void)
int vidx = 0;
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 3 * segments * 2 + 4 * 4);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(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);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 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);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
copy_v3_fl3(v, r, 0.0f, z);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
for (int j = 0; j < 4; j++) {
@@ -1447,14 +1697,14 @@ Gwn_Batch *DRW_cache_speaker_get(void)
float z = 0.25f * i - 0.125f;
copy_v3_fl3(v, x, y, z);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
if (i == 1) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
}
}
}
- SHC.drw_speaker = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_speaker = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_speaker;
}
@@ -1466,7 +1716,7 @@ Gwn_Batch *DRW_cache_speaker_get(void)
/** \name Probe
* \{ */
-Gwn_Batch *DRW_cache_lightprobe_cube_get(void)
+GPUBatch *DRW_cache_lightprobe_cube_get(void)
{
if (!SHC.drw_lightprobe_cube) {
int v_idx = 0;
@@ -1483,35 +1733,35 @@ Gwn_Batch *DRW_cache_lightprobe_cube_get(void)
};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (6 + 3) * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (6 + 3) * 2);
for (int i = 0; i < 6; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 6]);
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- SHC.drw_lightprobe_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lightprobe_cube = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lightprobe_cube;
}
-Gwn_Batch *DRW_cache_lightprobe_grid_get(void)
+GPUBatch *DRW_cache_lightprobe_grid_get(void)
{
if (!SHC.drw_lightprobe_grid) {
int v_idx = 0;
@@ -1528,47 +1778,47 @@ Gwn_Batch *DRW_cache_lightprobe_grid_get(void)
};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (6 * 2 + 3) * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (6 * 2 + 3) * 2);
for (int i = 0; i < 6; ++i) {
float tmp_v1[3], tmp_v2[3], tmp_tr[3];
copy_v3_v3(tmp_v1, v[i]);
copy_v3_v3(tmp_v2, v[(i + 1) % 6]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
/* Internal wires. */
for (int j = 1; j < 2; ++j) {
mul_v3_v3fl(tmp_tr, v[(i / 2) * 2 + 1], -0.5f * j);
add_v3_v3v3(tmp_v1, v[i], tmp_tr);
add_v3_v3v3(tmp_v2, v[(i + 1) % 6], tmp_tr);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
}
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
- SHC.drw_lightprobe_grid = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lightprobe_grid = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lightprobe_grid;
}
-Gwn_Batch *DRW_cache_lightprobe_planar_get(void)
+GPUBatch *DRW_cache_lightprobe_planar_get(void)
{
if (!SHC.drw_lightprobe_planar) {
int v_idx = 0;
@@ -1581,21 +1831,21 @@ Gwn_Batch *DRW_cache_lightprobe_planar_get(void)
};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4 * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4 * 2);
for (int i = 0; i < 4; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 4]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 4]);
}
- SHC.drw_lightprobe_planar = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_lightprobe_planar = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_lightprobe_planar;
}
@@ -1704,45 +1954,45 @@ static const float bone_octahedral_solid_normals[8][3] = {
{ 0.00000000f, 0.11043154f, 0.99388373f}
};
-Gwn_Batch *DRW_cache_bone_octahedral_get(void)
+GPUBatch *DRW_cache_bone_octahedral_get(void)
{
if (!SHC.drw_bone_octahedral) {
uint v_idx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor, snor; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.snor = GWN_vertformat_attr_add(&format, "snor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 24);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 24);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 3; ++j) {
- GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]);
}
}
- SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL,
- GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_octahedral = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL,
+ GPU_BATCH_OWNS_VBO);
}
return SHC.drw_bone_octahedral;
}
-Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void)
+GPUBatch *DRW_cache_bone_octahedral_wire_get(void)
{
if (!SHC.drw_bone_octahedral_wire) {
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 24);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 24);
for (int i = 0; i < 12; i++) {
- GWN_indexbuf_add_line_adj_verts(&elb,
+ GPU_indexbuf_add_line_adj_verts(&elb,
bone_octahedral_wire_lines_adjacency[i][0],
bone_octahedral_wire_lines_adjacency[i][1],
bone_octahedral_wire_lines_adjacency[i][2],
@@ -1750,10 +2000,10 @@ Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void)
}
/* HACK Reuse vertex buffer. */
- Gwn_Batch *pos_nor_batch = DRW_cache_bone_octahedral_get();
+ GPUBatch *pos_nor_batch = DRW_cache_bone_octahedral_get();
- SHC.drw_bone_octahedral_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_INDEX);
+ SHC.drw_bone_octahedral_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GPU_indexbuf_build(&elb),
+ GPU_BATCH_OWNS_INDEX);
}
return SHC.drw_bone_octahedral_wire;
}
@@ -1870,45 +2120,45 @@ static const float bone_box_solid_normals[12][3] = {
{ 0.0f, 1.0f, 0.0f},
};
-Gwn_Batch *DRW_cache_bone_box_get(void)
+GPUBatch *DRW_cache_bone_box_get(void)
{
if (!SHC.drw_bone_box) {
uint v_idx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor, snor; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.snor = GWN_vertformat_attr_add(&format, "snor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 36);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 36);
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 3; j++) {
- GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
- GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
}
}
- SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL,
- GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_box = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL,
+ GPU_BATCH_OWNS_VBO);
}
return SHC.drw_bone_box;
}
-Gwn_Batch *DRW_cache_bone_box_wire_get(void)
+GPUBatch *DRW_cache_bone_box_wire_get(void)
{
if (!SHC.drw_bone_box_wire) {
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 36);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 36);
for (int i = 0; i < 12; i++) {
- GWN_indexbuf_add_line_adj_verts(&elb,
+ GPU_indexbuf_add_line_adj_verts(&elb,
bone_box_wire_lines_adjacency[i][0],
bone_box_wire_lines_adjacency[i][1],
bone_box_wire_lines_adjacency[i][2],
@@ -1916,10 +2166,10 @@ Gwn_Batch *DRW_cache_bone_box_wire_get(void)
}
/* HACK Reuse vertex buffer. */
- Gwn_Batch *pos_nor_batch = DRW_cache_bone_box_get();
+ GPUBatch *pos_nor_batch = DRW_cache_bone_box_get();
- SHC.drw_bone_box_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_INDEX);
+ SHC.drw_bone_box_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GPU_indexbuf_build(&elb),
+ GPU_BATCH_OWNS_INDEX);
}
return SHC.drw_bone_box_wire;
}
@@ -1933,7 +2183,7 @@ static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3])
r_nor[2] = cosf(lat);
}
-Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
+GPUBatch *DRW_cache_bone_envelope_solid_get(void)
{
if (!SHC.drw_bone_envelope) {
const int lon_res = 24;
@@ -1942,15 +2192,15 @@ Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
const float lat_inc = M_PI / lat_res;
uint v_idx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 1);
float lon = 0.0f;
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
@@ -1964,24 +2214,24 @@ Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
benv_lat_lon_to_co(lat, lon, co1);
benv_lat_lon_to_co(lat, lon + lon_inc, co2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
}
/* Closing the loop */
benv_lat_lon_to_co(M_PI, lon, co1);
benv_lat_lon_to_co(M_PI, lon + lon_inc, co2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
}
- SHC.drw_bone_envelope = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_envelope = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_bone_envelope;
}
-Gwn_Batch *DRW_cache_bone_envelope_outline_get(void)
+GPUBatch *DRW_cache_bone_envelope_outline_get(void)
{
if (!SHC.drw_bone_envelope_outline) {
# define CIRCLE_RESOL 64
@@ -1989,16 +2239,16 @@ Gwn_Batch *DRW_cache_bone_envelope_outline_get(void)
const float radius = 1.0f;
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos0, pos1, pos2; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.pos2 = GWN_vertformat_attr_add(&format, "pos2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos0 = GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.pos1 = GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.pos2 = GPU_vertformat_attr_add(&format, "pos2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
v0[0] = radius * sinf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL));
v0[1] = radius * cosf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL));
@@ -2010,31 +2260,31 @@ Gwn_Batch *DRW_cache_bone_envelope_outline_get(void)
for (int a = 0; a < CIRCLE_RESOL; a++) {
v2[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v2[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
copy_v2_v2(v0, v1);
copy_v2_v2(v1, v2);
}
v2[0] = 0.0f;
v2[1] = radius;
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
-
- SHC.drw_bone_envelope_outline = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
+
+ SHC.drw_bone_envelope_outline = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
# undef CIRCLE_RESOL
}
return SHC.drw_bone_envelope_outline;
}
-Gwn_Batch *DRW_cache_bone_point_get(void)
+GPUBatch *DRW_cache_bone_point_get(void)
{
if (!SHC.drw_bone_point) {
#if 0 /* old style geometry sphere */
@@ -2045,16 +2295,16 @@ Gwn_Batch *DRW_cache_bone_point_get(void)
const float lat_inc = M_PI / lat_res;
uint v_idx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6);
float lon = 0.0f;
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
@@ -2074,56 +2324,56 @@ Gwn_Batch *DRW_cache_bone_point_get(void)
}
}
- SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
#else
# define CIRCLE_RESOL 64
float v[2];
const float radius = 0.05f;
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
}
- SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
# undef CIRCLE_RESOL
#endif
}
return SHC.drw_bone_point;
}
-Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
+GPUBatch *DRW_cache_bone_point_wire_outline_get(void)
{
if (!SHC.drw_bone_point_wire) {
#if 0 /* old style geometry sphere */
- Gwn_VertBuf *vbo = sphere_wire_vbo(0.05f);
- SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GPUVertBuf *vbo = sphere_wire_vbo(0.05f);
+ SHC.drw_bone_point_wire = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
#else
# define CIRCLE_RESOL 64
float v0[2], v1[2];
const float radius = 0.05f;
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos0, pos1; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos0 = GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.pos1 = GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
v0[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
v0[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
@@ -2132,20 +2382,20 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
for (int a = 0; a < CIRCLE_RESOL; a++) {
v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
copy_v2_v2(v0, v1);
}
v1[0] = 0.0f;
v1[1] = radius;
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
- SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_point_wire = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
# undef CIRCLE_RESOL
#endif
}
@@ -2162,7 +2412,7 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
#define POS_TAIL (1 << 5)
#define POS_BONE (1 << 6)
-Gwn_Batch *DRW_cache_bone_stick_get(void)
+GPUBatch *DRW_cache_bone_stick_get(void)
{
if (!SHC.drw_bone_stick) {
#define CIRCLE_RESOL 12
@@ -2172,20 +2422,20 @@ Gwn_Batch *DRW_cache_bone_stick_get(void)
float pos[2];
/* Position Only 2D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, flag; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.flag = GWN_vertformat_attr_add(&format, "flag", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.flag = GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U32, 1, GPU_FETCH_INT);
}
const uint vcount = (CIRCLE_RESOL + 1) * 2 + 6;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vcount);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vcount);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, GPU_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true);
/* head/tail points */
for (int i = 0; i < 2; ++i) {
@@ -2193,22 +2443,22 @@ Gwn_Batch *DRW_cache_bone_stick_get(void)
copy_v2_fl(pos, 0.0f);
flag = (i == 0) ? POS_HEAD : POS_TAIL;
flag |= (i == 0) ? COL_HEAD : COL_TAIL;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
- GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
+ GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
/* circle vertices */
flag |= COL_WIRE;
for (int a = 0; a < CIRCLE_RESOL; a++) {
pos[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
pos[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
- GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
+ GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
}
/* Close the circle */
- GWN_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL);
+ GPU_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL);
- GWN_indexbuf_add_primitive_restart(&elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
}
/* Bone rectangle */
@@ -2217,25 +2467,25 @@ Gwn_Batch *DRW_cache_bone_stick_get(void)
pos[1] = (i == 0 || i == 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f);
flag = ((i < 2 || i > 4) ? POS_HEAD : POS_TAIL) |
((i == 0 || i == 3) ? 0 : COL_WIRE) | COL_BONE | POS_BONE;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
- GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
+ GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
}
- SHC.drw_bone_stick = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ SHC.drw_bone_stick = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, GPU_indexbuf_build(&elb),
+ GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
#undef CIRCLE_RESOL
}
return SHC.drw_bone_stick;
}
static void set_bone_axis_vert(
- Gwn_VertBuf *vbo, uint axis, uint pos, uint col,
+ GPUVertBuf *vbo, uint axis, uint pos, uint col,
uint *v, const float *a, const float *p, const float *c)
{
- GWN_vertbuf_attr_set(vbo, axis, *v, a);
- GWN_vertbuf_attr_set(vbo, pos, *v, p);
- GWN_vertbuf_attr_set(vbo, col, *v, c);
+ GPU_vertbuf_attr_set(vbo, axis, *v, a);
+ GPU_vertbuf_attr_set(vbo, pos, *v, p);
+ GPU_vertbuf_attr_set(vbo, col, *v, c);
*v += 1;
}
@@ -2310,21 +2560,21 @@ static float axis_name_shadow[8][2] = {
#undef S_X
#undef S_Y
-Gwn_Batch *DRW_cache_bone_arrows_get(void)
+GPUBatch *DRW_cache_bone_arrows_get(void)
{
if (!SHC.drw_bone_arrows) {
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint axis, pos, col; } attr_id;
if (format.attr_len == 0) {
- attr_id.axis = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- attr_id.pos = GWN_vertformat_attr_add(&format, "screenPos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.col = GWN_vertformat_attr_add(&format, "colorAxis", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.axis = GPU_vertformat_attr_add(&format, "axis", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "screenPos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "colorAxis", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
/* Line */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 +
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 +
(X_LEN + Y_LEN + Z_LEN) * (1 + SHADOW_RES));
uint v = 0;
@@ -2387,7 +2637,7 @@ Gwn_Batch *DRW_cache_bone_arrows_get(void)
}
}
- SHC.drw_bone_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_bone_arrows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_bone_arrows;
}
@@ -2422,52 +2672,52 @@ static const float camera_coords_frame_tri[3] = {
/** Draw a loop of lines. */
static void camera_fill_lines_loop_fl_v1(
- Gwn_VertBufRaw *pos_step,
+ GPUVertBufRaw *pos_step,
const float *coords, const uint coords_len)
{
for (uint i = 0, i_prev = coords_len - 1; i < coords_len; i_prev = i++) {
- *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i_prev];
- *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i_prev];
+ *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
}
}
/** Fan lines out from the first vertex. */
static void camera_fill_lines_fan_fl_v1(
- Gwn_VertBufRaw *pos_step,
+ GPUVertBufRaw *pos_step,
const float *coords, const uint coords_len)
{
for (uint i = 1; i < coords_len; i++) {
- *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[0];
- *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[0];
+ *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
}
}
/** Simply fill the array. */
static void camera_fill_array_fl_v1(
- Gwn_VertBufRaw *pos_step,
+ GPUVertBufRaw *pos_step,
const float *coords, const uint coords_len)
{
for (uint i = 0; i < coords_len; i++) {
- *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
}
}
-Gwn_Batch *DRW_cache_camera_get(void)
+GPUBatch *DRW_cache_camera_get(void)
{
if (!SHC.drw_camera) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = 22;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
/* camera cone (from center to frame) */
camera_fill_lines_fan_fl_v1(&pos_step, camera_coords_frame_bounds, ARRAY_SIZE(camera_coords_frame_bounds));
@@ -2478,62 +2728,62 @@ Gwn_Batch *DRW_cache_camera_get(void)
/* camera triangle (above the frame) */
camera_fill_lines_loop_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
- SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_camera = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_camera;
}
-Gwn_Batch *DRW_cache_camera_frame_get(void)
+GPUBatch *DRW_cache_camera_frame_get(void)
{
if (!SHC.drw_camera_frame) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = 8;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
/* camera frame (skip center) */
camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
- BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
- SHC.drw_camera_frame = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_camera_frame = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_camera_frame;
}
-Gwn_Batch *DRW_cache_camera_tria_get(void)
+GPUBatch *DRW_cache_camera_tria_get(void)
{
if (!SHC.drw_camera_tria) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
/* Vertices */
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = 3;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
/* camera triangle (above the frame) */
camera_fill_array_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
- SHC.drw_camera_tria = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_camera_tria = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_camera_tria;
}
@@ -2546,24 +2796,24 @@ Gwn_Batch *DRW_cache_camera_tria_get(void)
* \{ */
/* Object Center */
-Gwn_Batch *DRW_cache_single_vert_get(void)
+GPUBatch *DRW_cache_single_vert_get(void)
{
if (!SHC.drw_single_vertice) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
- SHC.drw_single_vertice = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_single_vertice = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_single_vertice;
}
@@ -2575,7 +2825,7 @@ Gwn_Batch *DRW_cache_single_vert_get(void)
/** \name Meshes
* \{ */
-Gwn_Batch *DRW_cache_mesh_surface_overlay_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
@@ -2584,7 +2834,7 @@ Gwn_Batch *DRW_cache_mesh_surface_overlay_get(Object *ob)
void DRW_cache_mesh_wire_overlay_get(
Object *ob,
- Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts)
+ GPUBatch **r_tris, GPUBatch **r_ledges, GPUBatch **r_lverts)
{
BLI_assert(ob->type == OB_MESH);
@@ -2597,7 +2847,7 @@ void DRW_cache_mesh_wire_overlay_get(
void DRW_cache_mesh_normals_overlay_get(
Object *ob,
- Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts)
+ GPUBatch **r_tris, GPUBatch **r_ledges, GPUBatch **r_lverts)
{
BLI_assert(ob->type == OB_MESH);
@@ -2608,7 +2858,7 @@ void DRW_cache_mesh_normals_overlay_get(
*r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
}
-Gwn_Batch *DRW_cache_face_centers_get(Object *ob)
+GPUBatch *DRW_cache_face_centers_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2617,7 +2867,7 @@ Gwn_Batch *DRW_cache_face_centers_get(Object *ob)
return DRW_mesh_batch_cache_get_overlay_facedots(me);
}
-Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob)
+GPUBatch *DRW_cache_mesh_wire_outline_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2625,7 +2875,7 @@ Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob)
return DRW_mesh_batch_cache_get_fancy_edges(me);
}
-Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
+GPUBatch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
{
BLI_assert(ob->type == OB_MESH);
@@ -2633,7 +2883,7 @@ Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
return DRW_mesh_batch_cache_get_edge_detection(me, r_is_manifold);
}
-Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2641,7 +2891,7 @@ Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob)
return DRW_mesh_batch_cache_get_triangles_with_normals(me);
}
-Gwn_Batch *DRW_cache_mesh_loose_edges_get(Object *ob)
+GPUBatch *DRW_cache_mesh_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2649,7 +2899,7 @@ Gwn_Batch *DRW_cache_mesh_loose_edges_get(Object *ob)
return DRW_mesh_batch_cache_get_loose_edges_with_normals(me);
}
-Gwn_Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2657,7 +2907,7 @@ Gwn_Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
return DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me, ob->actdef - 1);
}
-Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2666,7 +2916,7 @@ Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
}
/* Return list of batches */
-Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+GPUBatch **DRW_cache_mesh_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
@@ -2678,7 +2928,7 @@ Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
}
/* Return list of batches */
-Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
+GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2686,7 +2936,7 @@ Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
return DRW_mesh_batch_cache_get_surface_texpaint(me);
}
-Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2694,7 +2944,7 @@ Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
return DRW_mesh_batch_cache_get_surface_texpaint_single(me);
}
-Gwn_Batch *DRW_cache_mesh_surface_verts_get(Object *ob)
+GPUBatch *DRW_cache_mesh_surface_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2702,7 +2952,7 @@ Gwn_Batch *DRW_cache_mesh_surface_verts_get(Object *ob)
return DRW_mesh_batch_cache_get_points_with_normals(me);
}
-Gwn_Batch *DRW_cache_mesh_edges_get(Object *ob)
+GPUBatch *DRW_cache_mesh_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2710,7 +2960,7 @@ Gwn_Batch *DRW_cache_mesh_edges_get(Object *ob)
return DRW_mesh_batch_cache_get_all_edges(me);
}
-Gwn_Batch *DRW_cache_mesh_verts_get(Object *ob)
+GPUBatch *DRW_cache_mesh_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2718,7 +2968,7 @@ Gwn_Batch *DRW_cache_mesh_verts_get(Object *ob)
return DRW_mesh_batch_cache_get_all_verts(me);
}
-Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, bool use_sel)
+GPUBatch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, bool use_sel)
{
BLI_assert(ob->type == OB_MESH);
@@ -2726,7 +2976,7 @@ Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, boo
return DRW_mesh_batch_cache_get_weight_overlay_edges(me, use_wire, use_sel);
}
-Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
+GPUBatch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2734,7 +2984,7 @@ Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
return DRW_mesh_batch_cache_get_weight_overlay_faces(me);
}
-Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob)
+GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -2757,23 +3007,23 @@ void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
/** \name Curve
* \{ */
-Gwn_Batch *DRW_cache_curve_edge_wire_get(Object *ob)
+GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
+ return DRW_curve_batch_cache_get_wire_edge(cu, ob->runtime.curve_cache);
}
-Gwn_Batch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size)
+GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_normal_edge(cu, ob->curve_cache, normal_size);
+ return DRW_curve_batch_cache_get_normal_edge(cu, ob->runtime.curve_cache, normal_size);
}
-Gwn_Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
+GPUBatch *DRW_cache_curve_edge_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
@@ -2781,7 +3031,7 @@ Gwn_Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
return DRW_curve_batch_cache_get_overlay_edges(cu);
}
-Gwn_Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
+GPUBatch *DRW_cache_curve_vert_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
@@ -2789,22 +3039,22 @@ Gwn_Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
return DRW_curve_batch_cache_get_overlay_verts(cu);
}
-Gwn_Batch *DRW_cache_curve_surface_get(Object *ob)
+GPUBatch *DRW_cache_curve_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
}
/* Return list of batches */
-Gwn_Batch **DRW_cache_curve_surface_shaded_get(
+GPUBatch **DRW_cache_curve_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
}
/** \} */
@@ -2814,13 +3064,13 @@ Gwn_Batch **DRW_cache_curve_surface_shaded_get(
/** \name MetaBall
* \{ */
-Gwn_Batch *DRW_cache_mball_surface_get(Object *ob)
+GPUBatch *DRW_cache_mball_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_MBALL);
return DRW_metaball_batch_cache_get_triangles_with_normals(ob);
}
-Gwn_Batch **DRW_cache_mball_surface_shaded_get(
+GPUBatch **DRW_cache_mball_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_MBALL);
@@ -2835,25 +3085,25 @@ Gwn_Batch **DRW_cache_mball_surface_shaded_get(
/** \name Font
* \{ */
-Gwn_Batch *DRW_cache_text_edge_wire_get(Object *ob)
+GPUBatch *DRW_cache_text_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
+ return DRW_curve_batch_cache_get_wire_edge(cu, ob->runtime.curve_cache);
}
-Gwn_Batch *DRW_cache_text_surface_get(Object *ob)
+GPUBatch *DRW_cache_text_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
}
-Gwn_Batch **DRW_cache_text_surface_shaded_get(
+GPUBatch **DRW_cache_text_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_FONT);
@@ -2861,17 +3111,17 @@ Gwn_Batch **DRW_cache_text_surface_shaded_get(
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
}
-Gwn_Batch *DRW_cache_text_cursor_overlay_get(Object *ob)
+GPUBatch *DRW_cache_text_cursor_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_overlay_cursor(cu);
}
-Gwn_Batch *DRW_cache_text_select_overlay_get(Object *ob)
+GPUBatch *DRW_cache_text_select_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
@@ -2885,22 +3135,22 @@ Gwn_Batch *DRW_cache_text_select_overlay_get(Object *ob)
/** \name Surface
* \{ */
-Gwn_Batch *DRW_cache_surf_surface_get(Object *ob)
+GPUBatch *DRW_cache_surf_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
}
/* Return list of batches */
-Gwn_Batch **DRW_cache_surf_surface_shaded_get(
+GPUBatch **DRW_cache_surf_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
}
/** \} */
@@ -2910,7 +3160,7 @@ Gwn_Batch **DRW_cache_surf_surface_shaded_get(
/** \name Lattice
* \{ */
-Gwn_Batch *DRW_cache_lattice_verts_get(Object *ob)
+GPUBatch *DRW_cache_lattice_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_LATTICE);
@@ -2918,7 +3168,7 @@ Gwn_Batch *DRW_cache_lattice_verts_get(Object *ob)
return DRW_lattice_batch_cache_get_all_verts(lt);
}
-Gwn_Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
+GPUBatch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
{
BLI_assert(ob->type == OB_LATTICE);
@@ -2932,7 +3182,7 @@ Gwn_Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef);
}
-Gwn_Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
+GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_LATTICE);
@@ -2947,17 +3197,17 @@ Gwn_Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
/** \name Particles
* \{ */
-Gwn_Batch *DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
+GPUBatch *DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
{
return DRW_particles_batch_cache_get_hair(object, psys, md);
}
-Gwn_Batch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
+GPUBatch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
{
return DRW_particles_batch_cache_get_dots(object, psys);
}
-Gwn_Batch *DRW_cache_particles_get_edit_strands(
+GPUBatch *DRW_cache_particles_get_edit_strands(
Object *object,
ParticleSystem *psys,
struct PTCacheEdit *edit)
@@ -2965,7 +3215,7 @@ Gwn_Batch *DRW_cache_particles_get_edit_strands(
return DRW_particles_batch_cache_get_edit_strands(object, psys, edit);
}
-Gwn_Batch *DRW_cache_particles_get_edit_inner_points(
+GPUBatch *DRW_cache_particles_get_edit_inner_points(
Object *object,
ParticleSystem *psys,
struct PTCacheEdit *edit)
@@ -2973,7 +3223,7 @@ Gwn_Batch *DRW_cache_particles_get_edit_inner_points(
return DRW_particles_batch_cache_get_edit_inner_points(object, psys, edit);
}
-Gwn_Batch *DRW_cache_particles_get_edit_tip_points(
+GPUBatch *DRW_cache_particles_get_edit_tip_points(
Object *object,
ParticleSystem *psys,
struct PTCacheEdit *edit)
@@ -2981,100 +3231,100 @@ Gwn_Batch *DRW_cache_particles_get_edit_tip_points(
return DRW_particles_batch_cache_get_edit_tip_points(object, psys, edit);
}
-Gwn_Batch *DRW_cache_particles_get_prim(int type)
+GPUBatch *DRW_cache_particles_get_prim(int type)
{
switch (type) {
case PART_DRAW_CROSS:
if (!SHC.drw_particle_cross) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, axis_id;
if (format.attr_len == 0) {
- pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ pos_id = GPU_vertformat_attr_add(&format, "inst_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ axis_id = GPU_vertformat_attr_add(&format, "axis", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 6);
/* X axis */
float co[3] = {-1.0f, 0.0f, 0.0f};
int axis = -1;
- GWN_vertbuf_attr_set(vbo, pos_id, 0, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 0, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 0, &axis);
co[0] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 1, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 1, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 1, &axis);
/* Y axis */
co[0] = 0.0f;
co[1] = -1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 2, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 2, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 2, &axis);
co[1] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 3, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 3, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 3, &axis);
/* Z axis */
co[1] = 0.0f;
co[2] = -1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 4, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 4, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 4, &axis);
co[2] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 5, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 5, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 5, &axis);
- SHC.drw_particle_cross = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_particle_cross = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_particle_cross;
case PART_DRAW_AXIS:
if (!SHC.drw_particle_axis) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, axis_id;
if (format.attr_len == 0) {
- pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ pos_id = GPU_vertformat_attr_add(&format, "inst_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ axis_id = GPU_vertformat_attr_add(&format, "axis", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 6);
/* X axis */
float co[3] = {0.0f, 0.0f, 0.0f};
int axis = 0;
- GWN_vertbuf_attr_set(vbo, pos_id, 0, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 0, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 0, &axis);
co[0] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 1, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 1, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 1, &axis);
/* Y axis */
co[0] = 0.0f;
axis = 1;
- GWN_vertbuf_attr_set(vbo, pos_id, 2, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 2, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 2, &axis);
co[1] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 3, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 3, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 3, &axis);
/* Z axis */
co[1] = 0.0f;
axis = 2;
- GWN_vertbuf_attr_set(vbo, pos_id, 4, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 4, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 4, &axis);
co[2] = 1.0f;
- GWN_vertbuf_attr_set(vbo, pos_id, 5, co);
- GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, 5, co);
+ GPU_vertbuf_attr_set(vbo, axis_id, 5, &axis);
- SHC.drw_particle_axis = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_particle_axis = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_particle_axis;
@@ -3084,26 +3334,26 @@ Gwn_Batch *DRW_cache_particles_get_prim(int type)
float v[3] = {0.0f, 0.0f, 0.0f};
int axis = -1;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, axis_id;
if (format.attr_len == 0) {
- pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ pos_id = GPU_vertformat_attr_add(&format, "inst_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ axis_id = GPU_vertformat_attr_add(&format, "axis", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
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;
- GWN_vertbuf_attr_set(vbo, pos_id, a, v);
- GWN_vertbuf_attr_set(vbo, axis_id, a, &axis);
+ GPU_vertbuf_attr_set(vbo, pos_id, a, v);
+ GPU_vertbuf_attr_set(vbo, axis_id, a, &axis);
}
- SHC.drw_particle_circle = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_particle_circle = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_particle_circle;
@@ -3120,20 +3370,20 @@ Gwn_Batch *DRW_cache_particles_get_prim(int type)
/** \name Hair */
-Gwn_Batch *DRW_cache_hair_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export)
+GPUBatch *DRW_cache_hair_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export)
{
return DRW_hair_batch_cache_get_fibers(hsys, hair_export);
}
-Gwn_Batch *DRW_cache_hair_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export)
+GPUBatch *DRW_cache_hair_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export)
{
return DRW_hair_batch_cache_get_follicle_points(hsys, hair_export);
}
/* 3D cursor */
-Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines)
+GPUBatch *DRW_cache_cursor_get(bool crosshair_lines)
{
- Gwn_Batch **drw_cursor = crosshair_lines ? &SHC.drw_cursor : &SHC.drw_cursor_only_circle;
+ GPUBatch **drw_cursor = crosshair_lines ? &SHC.drw_cursor : &SHC.drw_cursor_only_circle;
if (*drw_cursor == NULL) {
const float f5 = 0.25f;
@@ -3147,18 +3397,18 @@ Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines)
uchar red[3] = {255, 0, 0};
uchar white[3] = {255, 255, 255};
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, color; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- attr_id.color = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.color = GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init_ex(&elb, GWN_PRIM_LINE_STRIP, index_len, vert_len, true);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len, true);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vert_len);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
int v = 0;
for (int i = 0; i < segments; ++i) {
@@ -3167,59 +3417,59 @@ Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines)
float y = f10 * sinf(angle);
if (i % 2 == 0)
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, red);
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, red);
else
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, white);
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, white);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){x, y});
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){x, y});
+ GPU_indexbuf_add_generic_vert(&elb, v++);
}
- GWN_indexbuf_add_generic_vert(&elb, 0);
+ GPU_indexbuf_add_generic_vert(&elb, 0);
if (crosshair_lines) {
uchar crosshair_color[3];
UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
- GWN_indexbuf_add_primitive_restart(&elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f20, 0});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f5, 0});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f20, 0});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f5, 0});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
- GWN_indexbuf_add_primitive_restart(&elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f5, 0});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f20, 0});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f5, 0});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f20, 0});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
- GWN_indexbuf_add_primitive_restart(&elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f20});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f5});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f20});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f5});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
- GWN_indexbuf_add_primitive_restart(&elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f5});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f20});
- GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
- GWN_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f5});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f20});
+ GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
+ GPU_indexbuf_add_generic_vert(&elb, v++);
}
- Gwn_IndexBuf *ibo = GWN_indexbuf_build(&elb);
+ GPUIndexBuf *ibo = GPU_indexbuf_build(&elb);
- *drw_cursor = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, ibo, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ *drw_cursor = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, ibo, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
return *drw_cursor;
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index aef32291215..06789e892d3 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -26,7 +26,7 @@
#ifndef __DRAW_CACHE_H__
#define __DRAW_CACHE_H__
-struct Gwn_Batch;
+struct GPUBatch;
struct GPUMaterial;
struct ModifierData;
struct Object;
@@ -38,162 +38,169 @@ void DRW_shape_cache_free(void);
void DRW_shape_cache_reset(void);
/* 3D cursor */
-struct Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines);
+struct GPUBatch *DRW_cache_cursor_get(bool crosshair_lines);
/* Common Shapes */
-struct Gwn_Batch *DRW_cache_fullscreen_quad_get(void);
-struct Gwn_Batch *DRW_cache_quad_get(void);
-struct Gwn_Batch *DRW_cache_sphere_get(void);
-struct Gwn_Batch *DRW_cache_single_vert_get(void);
-struct Gwn_Batch *DRW_cache_single_line_get(void);
-struct Gwn_Batch *DRW_cache_single_line_endpoints_get(void);
-struct Gwn_Batch *DRW_cache_screenspace_circle_get(void);
+struct GPUBatch *DRW_cache_fullscreen_quad_get(void);
+struct GPUBatch *DRW_cache_quad_get(void);
+struct GPUBatch *DRW_cache_cube_get(void);
+struct GPUBatch *DRW_cache_sphere_get(void);
+struct GPUBatch *DRW_cache_single_vert_get(void);
+struct GPUBatch *DRW_cache_single_line_get(void);
+struct GPUBatch *DRW_cache_single_line_endpoints_get(void);
+struct GPUBatch *DRW_cache_screenspace_circle_get(void);
/* Common Object */
-struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold);
-struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_object_loose_edges_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_object_surface_material_get(
+struct GPUBatch *DRW_cache_object_wire_outline_get(struct Object *ob);
+struct GPUBatch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+struct GPUBatch *DRW_cache_object_surface_get(struct Object *ob);
+struct GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob);
+struct GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
void DRW_cache_object_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
/* Empties */
-struct Gwn_Batch *DRW_cache_plain_axes_get(void);
-struct Gwn_Batch *DRW_cache_single_arrow_get(void);
-struct Gwn_Batch *DRW_cache_cube_get(void);
-struct Gwn_Batch *DRW_cache_circle_get(void);
-struct Gwn_Batch *DRW_cache_square_get(void);
-struct Gwn_Batch *DRW_cache_empty_sphere_get(void);
-struct Gwn_Batch *DRW_cache_empty_cone_get(void);
-struct Gwn_Batch *DRW_cache_arrows_get(void);
-struct Gwn_Batch *DRW_cache_axis_names_get(void);
-struct Gwn_Batch *DRW_cache_image_plane_get(void);
-struct Gwn_Batch *DRW_cache_image_plane_wire_get(void);
+struct GPUBatch *DRW_cache_plain_axes_get(void);
+struct GPUBatch *DRW_cache_single_arrow_get(void);
+struct GPUBatch *DRW_cache_empty_cube_get(void);
+struct GPUBatch *DRW_cache_circle_get(void);
+struct GPUBatch *DRW_cache_square_get(void);
+struct GPUBatch *DRW_cache_empty_sphere_get(void);
+struct GPUBatch *DRW_cache_empty_cylinder_get(void);
+struct GPUBatch *DRW_cache_empty_cone_get(void);
+struct GPUBatch *DRW_cache_empty_capsule_cap_get(void);
+struct GPUBatch *DRW_cache_empty_capsule_body_get(void);
+struct GPUBatch *DRW_cache_arrows_get(void);
+struct GPUBatch *DRW_cache_axis_names_get(void);
+struct GPUBatch *DRW_cache_image_plane_get(void);
+struct GPUBatch *DRW_cache_image_plane_wire_get(void);
/* Force Field */
-struct Gwn_Batch *DRW_cache_field_wind_get(void);
-struct Gwn_Batch *DRW_cache_field_force_get(void);
-struct Gwn_Batch *DRW_cache_field_vortex_get(void);
-struct Gwn_Batch *DRW_cache_field_tube_limit_get(void);
-struct Gwn_Batch *DRW_cache_field_cone_limit_get(void);
+struct GPUBatch *DRW_cache_field_wind_get(void);
+struct GPUBatch *DRW_cache_field_force_get(void);
+struct GPUBatch *DRW_cache_field_vortex_get(void);
+struct GPUBatch *DRW_cache_field_tube_limit_get(void);
+struct GPUBatch *DRW_cache_field_cone_limit_get(void);
+
+/* Grease Pencil */
+struct GPUBatch *DRW_cache_gpencil_axes_get(void);
/* Lamps */
-struct Gwn_Batch *DRW_cache_lamp_get(void);
-struct Gwn_Batch *DRW_cache_lamp_shadows_get(void);
-struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void);
-struct Gwn_Batch *DRW_cache_lamp_area_square_get(void);
-struct Gwn_Batch *DRW_cache_lamp_area_disk_get(void);
-struct Gwn_Batch *DRW_cache_lamp_hemi_get(void);
-struct Gwn_Batch *DRW_cache_lamp_spot_get(void);
-struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void);
+struct GPUBatch *DRW_cache_lamp_get(void);
+struct GPUBatch *DRW_cache_lamp_shadows_get(void);
+struct GPUBatch *DRW_cache_lamp_sunrays_get(void);
+struct GPUBatch *DRW_cache_lamp_area_square_get(void);
+struct GPUBatch *DRW_cache_lamp_area_disk_get(void);
+struct GPUBatch *DRW_cache_lamp_hemi_get(void);
+struct GPUBatch *DRW_cache_lamp_spot_get(void);
+struct GPUBatch *DRW_cache_lamp_spot_square_get(void);
/* Camera */
-struct Gwn_Batch *DRW_cache_camera_get(void);
-struct Gwn_Batch *DRW_cache_camera_frame_get(void);
-struct Gwn_Batch *DRW_cache_camera_tria_get(void);
+struct GPUBatch *DRW_cache_camera_get(void);
+struct GPUBatch *DRW_cache_camera_frame_get(void);
+struct GPUBatch *DRW_cache_camera_tria_get(void);
/* Speaker */
-struct Gwn_Batch *DRW_cache_speaker_get(void);
+struct GPUBatch *DRW_cache_speaker_get(void);
/* Probe */
-struct Gwn_Batch *DRW_cache_lightprobe_cube_get(void);
-struct Gwn_Batch *DRW_cache_lightprobe_grid_get(void);
-struct Gwn_Batch *DRW_cache_lightprobe_planar_get(void);
+struct GPUBatch *DRW_cache_lightprobe_cube_get(void);
+struct GPUBatch *DRW_cache_lightprobe_grid_get(void);
+struct GPUBatch *DRW_cache_lightprobe_planar_get(void);
/* Bones */
-struct Gwn_Batch *DRW_cache_bone_octahedral_get(void);
-struct Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void);
-struct Gwn_Batch *DRW_cache_bone_box_get(void);
-struct Gwn_Batch *DRW_cache_bone_box_wire_get(void);
-struct Gwn_Batch *DRW_cache_bone_envelope_solid_get(void);
-struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void);
-struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void);
-struct Gwn_Batch *DRW_cache_bone_point_get(void);
-struct Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void);
-struct Gwn_Batch *DRW_cache_bone_stick_get(void);
-struct Gwn_Batch *DRW_cache_bone_arrows_get(void);
+struct GPUBatch *DRW_cache_bone_octahedral_get(void);
+struct GPUBatch *DRW_cache_bone_octahedral_wire_get(void);
+struct GPUBatch *DRW_cache_bone_box_get(void);
+struct GPUBatch *DRW_cache_bone_box_wire_get(void);
+struct GPUBatch *DRW_cache_bone_envelope_solid_get(void);
+struct GPUBatch *DRW_cache_bone_envelope_outline_get(void);
+struct GPUBatch *DRW_cache_bone_envelope_head_wire_outline_get(void);
+struct GPUBatch *DRW_cache_bone_point_get(void);
+struct GPUBatch *DRW_cache_bone_point_wire_outline_get(void);
+struct GPUBatch *DRW_cache_bone_stick_get(void);
+struct GPUBatch *DRW_cache_bone_arrows_get(void);
/* Meshes */
-struct Gwn_Batch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
void DRW_cache_mesh_wire_overlay_get(
struct Object *ob,
- struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts);
+ struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts);
void DRW_cache_mesh_normals_overlay_get(
struct Object *ob,
- struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts);
-struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold);
-struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_loose_edges_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_edges_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_verts_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel);
-struct Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+ struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts);
+struct GPUBatch *DRW_cache_face_centers_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+struct GPUBatch *DRW_cache_mesh_surface_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_loose_edges_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_edges_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_verts_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel);
+struct GPUBatch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
+struct GPUBatch **DRW_cache_mesh_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
-struct Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
+struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
/* Curve */
-struct Gwn_Batch *DRW_cache_curve_surface_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_curve_surface_shaded_get(
+struct GPUBatch *DRW_cache_curve_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_curve_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-struct Gwn_Batch *DRW_cache_curve_surface_verts_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
+struct GPUBatch *DRW_cache_curve_surface_verts_get(struct Object *ob);
+struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob);
/* edit-mode */
-struct Gwn_Batch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
-struct Gwn_Batch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
+struct GPUBatch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
/* Font */
-struct Gwn_Batch *DRW_cache_text_edge_wire_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_text_surface_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_text_surface_shaded_get(
+struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
+struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_text_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* edit-mode */
-struct Gwn_Batch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_text_select_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_text_select_overlay_get(struct Object *ob);
/* Surface */
-struct Gwn_Batch *DRW_cache_surf_surface_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_surf_surface_shaded_get(
+struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_surf_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Lattice */
-struct Gwn_Batch *DRW_cache_lattice_verts_get(struct Object *ob);
-struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight);
-struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob);
+struct GPUBatch *DRW_cache_lattice_verts_get(struct Object *ob);
+struct GPUBatch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight);
+struct GPUBatch *DRW_cache_lattice_vert_overlay_get(struct Object *ob);
/* Particles */
-struct Gwn_Batch *DRW_cache_particles_get_hair(
+struct GPUBatch *DRW_cache_particles_get_hair(
struct Object *object, struct ParticleSystem *psys, struct ModifierData *md);
-struct Gwn_Batch *DRW_cache_particles_get_dots(
+struct GPUBatch *DRW_cache_particles_get_dots(
struct Object *object, struct ParticleSystem *psys);
-struct Gwn_Batch *DRW_cache_particles_get_edit_strands(
+struct GPUBatch *DRW_cache_particles_get_edit_strands(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points(
+struct GPUBatch *DRW_cache_particles_get_edit_inner_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points(
+struct GPUBatch *DRW_cache_particles_get_edit_tip_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_cache_particles_get_prim(int type);
+struct GPUBatch *DRW_cache_particles_get_prim(int type);
/* Hair */
-struct Gwn_Batch *DRW_cache_hair_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export);
-struct Gwn_Batch *DRW_cache_hair_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export);
+struct GPUBatch *DRW_cache_hair_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export);
+struct GPUBatch *DRW_cache_hair_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export);
/* Metaball */
-struct Gwn_Batch *DRW_cache_mball_surface_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
#endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index caef4979ee3..0068e84055b 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -29,9 +29,9 @@
struct CurveCache;
struct GPUMaterial;
struct GPUTexture;
-struct Gwn_Batch;
-struct Gwn_IndexBuf;
-struct Gwn_VertBuf;
+struct GPUBatch;
+struct GPUIndexBuf;
+struct GPUVertBuf;
struct ListBase;
struct ModifierData;
struct ParticleSystem;
@@ -43,6 +43,7 @@ struct Curve;
struct Lattice;
struct Mesh;
struct MetaBall;
+struct bGPdata;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
@@ -60,75 +61,78 @@ void DRW_lattice_batch_cache_free(struct Lattice *lt);
void DRW_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
+void DRW_gpencil_batch_cache_dirty(struct bGPdata *gpd);
+void DRW_gpencil_batch_cache_free(struct bGPdata *gpd);
+
void DRW_hair_batch_cache_dirty(struct HairSystem *hsys, int mode);
void DRW_hair_batch_cache_free(struct HairSystem *hsys);
/* Curve */
-struct Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
-struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(
+struct GPUBatch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
+struct GPUBatch *DRW_curve_batch_cache_get_normal_edge(
struct Curve *cu, struct CurveCache *ob_curve_cache, float normal_size);
-struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
-struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
-struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
+struct GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(
struct Curve *cu, struct CurveCache *ob_curve_cache);
-struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
+struct GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
struct Curve *cu, struct CurveCache *ob_curve_cache,
struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Metaball */
-struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
-struct Gwn_Batch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+struct GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
+struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Curve (Font) */
-struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
-struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
/* DispList */
-struct Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb);
-struct Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb);
-struct Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
+struct GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb);
+struct GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb);
+struct GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
struct ListBase *lb, uint gpumat_array_len);
-struct Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
+struct GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
struct ListBase *lb, uint gpumat_array_len);
/* Lattice */
-struct Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
-struct Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
-struct Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
+struct GPUBatch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
+struct GPUBatch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
+struct GPUBatch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
/* Mesh */
-struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
-struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, int defgroup);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_loose_edges_with_normals(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
+struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
+struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, int defgroup);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide);
+struct GPUBatch *DRW_mesh_batch_cache_get_loose_edges_with_normals(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
/* edit-mesh selection (use generic function for faces) */
-struct Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset);
-struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset);
+struct GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset);
+struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset);
+struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset);
/* Object mode Wireframe overlays */
void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
@@ -136,19 +140,19 @@ void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
/* Particles */
-struct Gwn_Batch *DRW_particles_batch_cache_get_hair(
+struct GPUBatch *DRW_particles_batch_cache_get_hair(
struct Object *object, struct ParticleSystem *psys, struct ModifierData *md);
-struct Gwn_Batch *DRW_particles_batch_cache_get_dots(
+struct GPUBatch *DRW_particles_batch_cache_get_dots(
struct Object *object, struct ParticleSystem *psys);
-struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(
+struct GPUBatch *DRW_particles_batch_cache_get_edit_strands(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(
+struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(
+struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
/* Hair */
-struct Gwn_Batch *DRW_hair_batch_cache_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export);
-struct Gwn_Batch *DRW_hair_batch_cache_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export);
+struct GPUBatch *DRW_hair_batch_cache_get_fibers(struct HairSystem *hsys, const struct HairExportCache *hair_export);
+struct GPUBatch *DRW_hair_batch_cache_get_follicle_points(struct HairSystem *hsys, const struct HairExportCache *hair_export);
#endif /* __DRAW_CACHE_IMPL_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 4de1dfd24f5..cfaa3c6914f 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -298,43 +298,43 @@ enum {
};
/* ---------------------------------------------------------------------- */
-/* Curve Gwn_Batch Cache */
+/* Curve GPUBatch Cache */
typedef struct CurveBatchCache {
/* center-line */
struct {
- Gwn_VertBuf *verts;
- Gwn_VertBuf *edges;
- Gwn_Batch *batch;
- Gwn_IndexBuf *elem;
+ GPUVertBuf *verts;
+ GPUVertBuf *edges;
+ GPUBatch *batch;
+ GPUIndexBuf *elem;
} wire;
/* normals */
struct {
- Gwn_VertBuf *verts;
- Gwn_VertBuf *edges;
- Gwn_Batch *batch;
- Gwn_IndexBuf *elem;
+ GPUVertBuf *verts;
+ GPUVertBuf *edges;
+ GPUBatch *batch;
+ GPUIndexBuf *elem;
} normal;
/* control handles and vertices */
struct {
- Gwn_Batch *edges;
- Gwn_Batch *verts;
+ GPUBatch *edges;
+ GPUBatch *verts;
} overlay;
struct {
- Gwn_VertBuf *verts;
- Gwn_IndexBuf *triangles_in_order;
- Gwn_Batch **shaded_triangles;
- Gwn_Batch *batch;
+ GPUVertBuf *verts;
+ GPUIndexBuf *triangles_in_order;
+ GPUBatch **shaded_triangles;
+ GPUBatch *batch;
int mat_len;
} surface;
/* 3d text */
struct {
- Gwn_Batch *select;
- Gwn_Batch *cursor;
+ GPUBatch *select;
+ GPUBatch *cursor;
} text;
/* settings to determine if cache is invalid */
@@ -348,7 +348,7 @@ typedef struct CurveBatchCache {
bool is_editmode;
} CurveBatchCache;
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
static bool curve_batch_cache_valid(Curve *cu)
{
@@ -434,12 +434,12 @@ void DRW_curve_batch_cache_dirty(Curve *cu, int mode)
break;
case BKE_CURVE_BATCH_DIRTY_SELECT:
/* editnurb */
- GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
- GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay.verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay.edges);
/* editfont */
- GWN_BATCH_DISCARD_SAFE(cache->text.select);
- GWN_BATCH_DISCARD_SAFE(cache->text.cursor);
+ GPU_BATCH_DISCARD_SAFE(cache->text.select);
+ GPU_BATCH_DISCARD_SAFE(cache->text.cursor);
break;
default:
BLI_assert(0);
@@ -453,34 +453,34 @@ static void curve_batch_cache_clear(Curve *cu)
return;
}
- GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
- GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay.verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay.edges);
- GWN_VERTBUF_DISCARD_SAFE(cache->surface.verts);
- GWN_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
+ GPU_VERTBUF_DISCARD_SAFE(cache->surface.verts);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
if (cache->surface.shaded_triangles) {
for (int i = 0; i < cache->surface.mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
}
}
MEM_SAFE_FREE(cache->surface.shaded_triangles);
- GWN_BATCH_DISCARD_SAFE(cache->surface.batch);
+ GPU_BATCH_DISCARD_SAFE(cache->surface.batch);
/* don't own vbo & elems */
- GWN_BATCH_DISCARD_SAFE(cache->wire.batch);
- GWN_VERTBUF_DISCARD_SAFE(cache->wire.verts);
- GWN_VERTBUF_DISCARD_SAFE(cache->wire.edges);
- GWN_INDEXBUF_DISCARD_SAFE(cache->wire.elem);
+ GPU_BATCH_DISCARD_SAFE(cache->wire.batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->wire.verts);
+ GPU_VERTBUF_DISCARD_SAFE(cache->wire.edges);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->wire.elem);
/* don't own vbo & elems */
- GWN_BATCH_DISCARD_SAFE(cache->normal.batch);
- GWN_VERTBUF_DISCARD_SAFE(cache->normal.verts);
- GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges);
- GWN_INDEXBUF_DISCARD_SAFE(cache->normal.elem);
+ GPU_BATCH_DISCARD_SAFE(cache->normal.batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->normal.verts);
+ GPU_VERTBUF_DISCARD_SAFE(cache->normal.edges);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->normal.elem);
/* 3d text */
- GWN_BATCH_DISCARD_SAFE(cache->text.cursor);
- GWN_BATCH_DISCARD_SAFE(cache->text.select);
+ GPU_BATCH_DISCARD_SAFE(cache->text.cursor);
+ GPU_BATCH_DISCARD_SAFE(cache->text.select);
}
void DRW_curve_batch_cache_free(Curve *cu)
@@ -494,30 +494,30 @@ void DRW_curve_batch_cache_free(Curve *cu)
/** \name Private Curve Cache API
* \{ */
-/* Gwn_Batch cache usage. */
-static Gwn_VertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+/* GPUBatch cache usage. */
+static GPUVertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
BLI_assert(rdata->ob_curve_cache != NULL);
if (cache->wire.verts == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
- Gwn_VertBuf *vbo = cache->wire.verts = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vert_len);
+ GPUVertBuf *vbo = cache->wire.verts = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
int vbo_len_used = 0;
for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
if (bl->nr > 0) {
const int i_end = vbo_len_used + bl->nr;
for (const BevPoint *bevp = bl->bevpoints; vbo_len_used < i_end; vbo_len_used++, bevp++) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec);
}
}
}
@@ -527,7 +527,7 @@ static Gwn_VertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, Cur
return cache->wire.verts;
}
-static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUIndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_WIRE);
BLI_assert(rdata->ob_curve_cache != NULL);
@@ -537,8 +537,8 @@ static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, Cu
const int edge_len = curve_render_data_wire_edges_len_get(rdata);
int edge_len_used = 0;
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
int i = 0;
for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
@@ -554,7 +554,7 @@ static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, Cu
i += 1;
}
for (; i < i_end; i_prev = i++) {
- GWN_indexbuf_add_line_verts(&elb, i_prev, i);
+ GPU_indexbuf_add_line_verts(&elb, i_prev, i);
edge_len_used += 1;
}
}
@@ -567,30 +567,30 @@ static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, Cu
BLI_assert(edge_len_used == edge_len);
}
- cache->wire.elem = GWN_indexbuf_build(&elb);
+ cache->wire.elem = GPU_indexbuf_build(&elb);
}
return cache->wire.elem;
}
-static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUVertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
BLI_assert(rdata->ob_curve_cache != NULL);
if (cache->normal.verts == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
const int normal_len = curve_render_data_normal_len_get(rdata);
const int vert_len = normal_len * 3;
- Gwn_VertBuf *vbo = cache->normal.verts = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vert_len);
+ GPUVertBuf *vbo = cache->normal.verts = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
int vbo_len_used = 0;
const BevList *bl;
@@ -622,9 +622,9 @@ static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, C
add_v3_v3(vec_a, bevp->vec);
add_v3_v3(vec_b, bevp->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b);
bevp += skip + 1;
nr -= skip;
@@ -636,7 +636,7 @@ static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, C
return cache->normal.verts;
}
-static Gwn_IndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUIndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
BLI_assert(rdata->ob_curve_cache != NULL);
@@ -646,19 +646,19 @@ static Gwn_IndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata,
const int vert_len = normal_len * 3;
const int edge_len = normal_len * 2;
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
int vbo_len_used = 0;
for (int i = 0; i < normal_len; i++) {
- GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1);
- GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2);
+ GPU_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1);
+ GPU_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2);
vbo_len_used += 3;
}
BLI_assert(vbo_len_used == vert_len);
- cache->normal.elem = GWN_indexbuf_build(&elb);
+ cache->normal.elem = GPU_indexbuf_build(&elb);
}
return cache->normal.elem;
@@ -673,18 +673,18 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
CurveRenderData *rdata = curve_render_data_create(cu, NULL, options);
if (cache->overlay.verts == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
int i = 0;
for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
if (nu->bezt) {
@@ -697,16 +697,16 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
if (rdata->hide_handles) {
vflag = (bezt->f2 & SELECT) ?
(is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
vbo_len_used += 1;
}
else {
for (int j = 0; j < 3; j++) {
vflag = ((&bezt->f1)[j] & SELECT) ?
(is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
vbo_len_used += 1;
}
}
@@ -721,8 +721,8 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
const bool is_active = (i == rdata->actvert);
char vflag;
vflag = (bp->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
vbo_len_used += 1;
}
i += 1;
@@ -731,29 +731,29 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
i += nu->pntsu;
}
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
- cache->overlay.verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->overlay.verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
if ((cache->overlay.edges == NULL) && (rdata->hide_handles == false)) {
/* Note: we could reference indices to vertices (above) */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int edge_len = curve_render_data_overlay_edges_len_get(rdata);
const int vbo_len_capacity = edge_len * 2;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
int i = 0;
for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, i++) {
const bool is_active_nurb = (i == cu->actnu);
@@ -766,7 +766,7 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
for (int j = 0; j < 2; j += 1) {
/* same vertex twice, only check different selection */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
vbo_len_used += 1;
col_id = (&bezt->h1)[j];
@@ -777,8 +777,8 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
col_id |= ACTIVE_NURB;
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j * 2]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j * 2]);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
vbo_len_used += 1;
}
}
@@ -794,11 +794,11 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
col_id |= ACTIVE_NURB;
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec);
vbo_len_used += 1;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
vbo_len_used += 1;
}
@@ -806,16 +806,16 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
}
}
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
- cache->overlay.edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->overlay.edges = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
curve_render_data_free(rdata);
}
-static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUBatch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
if (cache->surface.batch == NULL) {
@@ -827,8 +827,8 @@ static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata,
if (cache->surface.triangles_in_order == NULL) {
cache->surface.triangles_in_order = DRW_displist_indexbuf_calc_triangles_in_order(lb);
}
- cache->surface.batch = GWN_batch_create(
- GWN_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order);
+ cache->surface.batch = GPU_batch_create(
+ GPU_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order);
}
return cache->surface.batch;
@@ -843,21 +843,21 @@ static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata,
* \{ */
-static Gwn_Batch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUBatch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
if (cache->text.select == NULL) {
EditFont *ef = rdata->text.edit_font;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = ef->selboxes_len * 6;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
float box[4][3];
@@ -904,37 +904,37 @@ static Gwn_Batch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, C
add_v2_v2(box[3], &sb->x);
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]);
}
BLI_assert(vbo_len_used == vbo_len_capacity);
- cache->text.select = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->text.select = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return cache->text.select;
}
-static Gwn_Batch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache)
+static GPUBatch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
if (cache->text.cursor == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = 4;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
for (int i = 0; i < 4; i++) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]);
}
- cache->text.cursor = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->text.cursor = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return cache->text.cursor;
}
@@ -946,7 +946,7 @@ static Gwn_Batch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, C
/** \name Public Object/Curve API
* \{ */
-Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
+GPUBatch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -954,8 +954,8 @@ Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_c
/* create batch from Curve */
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE);
- cache->wire.batch = GWN_batch_create(
- GWN_PRIM_LINES,
+ cache->wire.batch = GPU_batch_create(
+ GPU_PRIM_LINES,
curve_batch_cache_get_wire_verts(rdata, cache),
curve_batch_cache_get_wire_edges(rdata, cache));
@@ -964,15 +964,15 @@ Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_c
return cache->wire.batch;
}
-Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
+GPUBatch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
if (cache->normal.batch != NULL) {
cache->normal_size = normal_size;
if (cache->normal_size != normal_size) {
- GWN_BATCH_DISCARD_SAFE(cache->normal.batch);
- GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges);
+ GPU_BATCH_DISCARD_SAFE(cache->normal.batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->normal.edges);
}
}
cache->normal_size = normal_size;
@@ -981,8 +981,8 @@ Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve
/* create batch from Curve */
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL);
- cache->normal.batch = GWN_batch_create(
- GWN_PRIM_LINES,
+ cache->normal.batch = GPU_batch_create(
+ GPU_PRIM_LINES,
curve_batch_cache_get_normal_verts(rdata, cache),
curve_batch_cache_get_normal_edges(rdata, cache));
@@ -992,7 +992,7 @@ Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve
return cache->normal.batch;
}
-Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
+GPUBatch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -1003,7 +1003,7 @@ Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
return cache->overlay.edges;
}
-Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu)
+GPUBatch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -1014,7 +1014,7 @@ Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu)
return cache->overlay.verts;
}
-Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
+GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(
struct Curve *cu, struct CurveCache *ob_curve_cache)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -1030,7 +1030,7 @@ Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
return cache->surface.batch;
}
-Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
+GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
struct Curve *cu, struct CurveCache *ob_curve_cache,
struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
{
@@ -1040,7 +1040,7 @@ Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
/* TODO: deduplicate code */
if (cache->surface.shaded_triangles) {
for (int i = 0; i < cache->surface.mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
}
}
MEM_SAFE_FREE(cache->surface.shaded_triangles);
@@ -1058,7 +1058,7 @@ Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
else {
cache->surface.shaded_triangles = MEM_mallocN(
sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__);
- Gwn_IndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
+ GPUIndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
lb, gpumat_array_len);
if (cache->surface.verts == NULL) {
@@ -1066,8 +1066,8 @@ Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
}
for (int i = 0; i < gpumat_array_len; ++i) {
- cache->surface.shaded_triangles[i] = GWN_batch_create_ex(
- GWN_PRIM_TRIS, cache->surface.verts, el[i], GWN_BATCH_OWNS_INDEX);
+ cache->surface.shaded_triangles[i] = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, cache->surface.verts, el[i], GPU_BATCH_OWNS_INDEX);
}
MEM_freeN(el); /* Save `el` in cache? */
@@ -1085,7 +1085,7 @@ Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
/** \name Public Object/Font API
* \{ */
-Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
+GPUBatch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -1100,7 +1100,7 @@ Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
return cache->text.select;
}
-Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
+GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 8d187af0501..5ea0f6fb05d 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -87,49 +87,49 @@ static int curve_render_surface_tri_len_get(const ListBase *lb)
return tri_len;
}
-static void displist_indexbufbuilder_set(Gwn_IndexBufBuilder *elb, const DispList *dl, const int ofs)
+static void displist_indexbufbuilder_set(GPUIndexBufBuilder *elb, const DispList *dl, const int ofs)
{
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
const int *idx = dl->index;
if (dl->type == DL_INDEX3) {
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 3) {
- GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
+ GPU_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
}
}
else if (dl->type == DL_SURF) {
const int i_end = dl->totindex;
for (int i = 0; i < i_end; i++, idx += 4) {
- GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
- GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[3] + ofs, idx[2] + ofs);
+ GPU_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
+ GPU_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[3] + ofs, idx[2] + ofs);
}
}
else {
BLI_assert(dl->type == DL_INDEX4);
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 4) {
- GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+ GPU_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
if (idx[2] != idx[3]) {
- GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+ GPU_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
}
}
}
}
}
-Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
+GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
{
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb));
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb));
BKE_displist_normals_add(lb);
@@ -141,9 +141,9 @@ Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
const float *fp_no = dl->nors;
const int vbo_end = vbo_len_used + dl_vert_len(dl);
while (vbo_len_used < vbo_end) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
if (fp_no) {
- GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
if (ndata_is_single == false) {
fp_no += 3;
}
@@ -157,13 +157,13 @@ Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
return vbo;
}
-Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
+GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
const int vert_len = curve_render_surface_vert_len_get(lb);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
int ofs = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
@@ -171,14 +171,14 @@ Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
ofs += dl_vert_len(dl);
}
- return GWN_indexbuf_build(&elb);
+ return GPU_indexbuf_build(&elb);
}
-Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
+GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
{
- Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(
+ GPUIndexBuf **shaded_triangles_in_order = MEM_callocN(
sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__);
- Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
+ GPUIndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
const int tri_len = curve_render_surface_tri_len_get(lb);
const int vert_len = curve_render_surface_vert_len_get(lb);
@@ -186,7 +186,7 @@ Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(L
/* Init each index buffer builder */
for (i = 0; i < gpumat_array_len; i++) {
- GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len);
+ GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, tri_len, vert_len);
}
/* calc each index buffer builder */
@@ -198,56 +198,56 @@ Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(L
/* build each indexbuf */
for (i = 0; i < gpumat_array_len; i++) {
- shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
+ shaded_triangles_in_order[i] = GPU_indexbuf_build(&elb[i]);
}
return shaded_triangles_in_order;
}
static void displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step, Gwn_VertBufRaw *uv_step,
+ GPUVertBufRaw *pos_step, GPUVertBufRaw *nor_step, GPUVertBufRaw *uv_step,
const float v1[3], const float v2[3], const float v3[3],
const float n1[3], const float n2[3], const float n3[3],
const float uv1[2], const float uv2[2], const float uv3[2])
{
- copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v1);
- copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n1);
- copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv1);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v1);
+ copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n1);
+ copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv1);
- copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v2);
- copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n2);
- copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv2);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v2);
+ copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n2);
+ copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv2);
- copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v3);
- copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n3);
- copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv3);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v3);
+ copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n3);
+ copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv3);
}
-Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(ListBase *lb, uint gpumat_array_len)
+GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(ListBase *lb, uint gpumat_array_len)
{
- static Gwn_VertFormat shaded_triangles_format = { 0 };
+ static GPUVertFormat shaded_triangles_format = { 0 };
static struct { uint pos, nor, uv; } attr_id;
if (shaded_triangles_format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&shaded_triangles_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&shaded_triangles_format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.uv = GWN_vertformat_attr_add(&shaded_triangles_format, "u", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&shaded_triangles_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&shaded_triangles_format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.uv = GPU_vertformat_attr_add(&shaded_triangles_format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_Batch **shaded_triangles = MEM_mallocN(sizeof(*shaded_triangles) * gpumat_array_len, __func__);
+ GPUBatch **shaded_triangles = MEM_mallocN(sizeof(*shaded_triangles) * gpumat_array_len, __func__);
- Gwn_VertBuf **vbo = BLI_array_alloca(vbo, gpumat_array_len);
+ GPUVertBuf **vbo = BLI_array_alloca(vbo, gpumat_array_len);
uint *vbo_len_capacity = BLI_array_alloca(vbo_len_capacity, gpumat_array_len);
- Gwn_VertBufRaw *pos_step, *nor_step, *uv_step;
+ GPUVertBufRaw *pos_step, *nor_step, *uv_step;
pos_step = BLI_array_alloca(pos_step, gpumat_array_len);
nor_step = BLI_array_alloca(nor_step, gpumat_array_len);
uv_step = BLI_array_alloca(uv_step, gpumat_array_len);
/* Create each vertex buffer */
for (int i = 0; i < gpumat_array_len; i++) {
- vbo[i] = GWN_vertbuf_create_with_format(&shaded_triangles_format);
+ vbo[i] = GPU_vertbuf_create_with_format(&shaded_triangles_format);
vbo_len_capacity[i] = 0;
}
@@ -258,10 +258,10 @@ Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(Lis
/* Alloc each vertex buffer and get each raw data */
for (int i = 0; i < gpumat_array_len; i++) {
- GWN_vertbuf_data_alloc(vbo[i], vbo_len_capacity[i]);
- GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.pos, &pos_step[i]);
- GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.nor, &nor_step[i]);
- GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.uv, &uv_step[i]);
+ GPU_vertbuf_data_alloc(vbo[i], vbo_len_capacity[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.pos, &pos_step[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.nor, &nor_step[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.uv, &uv_step[i]);
}
BKE_displist_normals_add(lb);
@@ -388,11 +388,11 @@ Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(Lis
}
for (int i = 0; i < gpumat_array_len; i++) {
- uint vbo_len_used = GWN_vertbuf_raw_used(&pos_step[i]);
+ uint vbo_len_used = GPU_vertbuf_raw_used(&pos_step[i]);
if (vbo_len_capacity[i] != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo[i], vbo_len_used);
+ GPU_vertbuf_data_resize(vbo[i], vbo_len_used);
}
- shaded_triangles[i] = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo[i], NULL, GWN_BATCH_OWNS_VBO);
+ shaded_triangles[i] = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo[i], NULL, GPU_BATCH_OWNS_VBO);
}
return shaded_triangles;
diff --git a/source/blender/draw/intern/draw_cache_impl_hair.c b/source/blender/draw/intern/draw_cache_impl_hair.c
index e945e2bb52e..9f5afed49f1 100644
--- a/source/blender/draw/intern/draw_cache_impl_hair.c
+++ b/source/blender/draw/intern/draw_cache_impl_hair.c
@@ -54,9 +54,9 @@
#include "DRW_render.h"
/* ---------------------------------------------------------------------- */
-/* Hair Gwn_Batch Cache */
+/* Hair GPUBatch Cache */
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
typedef struct HairBatchCache {
ParticleHairCache hair;
@@ -147,7 +147,7 @@ static void hair_batch_cache_ensure_count(
static void hair_batch_cache_fill_segments_proc_pos(
const HairExportCache *hair_export,
- Gwn_VertBufRaw *attr_step)
+ GPUVertBufRaw *attr_step)
{
for (int i = 0; i < hair_export->totcurves; i++) {
const HairFiberCurve *curve = &hair_export->fiber_curves[i];
@@ -159,7 +159,7 @@ static void hair_batch_cache_fill_segments_proc_pos(
const float *co_prev = NULL;
float *seg_data_first;
for (int j = 0; j < curve->numverts; j++) {
- float *seg_data = (float *)GWN_vertbuf_raw_step(attr_step);
+ float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
copy_v3_v3(seg_data, verts[j].co);
if (co_prev) {
total_len += len_v3v3(co_prev, verts[j].co);
@@ -188,19 +188,19 @@ static void hair_batch_cache_ensure_procedural_pos(
}
/* initialize vertex format */
- Gwn_VertFormat format = {0};
- uint pos_id = GWN_vertformat_attr_add(&format, "posTime", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->proc_point_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
+ cache->proc_point_buf = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
hair_batch_cache_fill_segments_proc_pos(hair_export, &pos_step);
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->proc_point_buf);
+ GPU_vertbuf_use(cache->proc_point_buf);
cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
}
@@ -215,9 +215,9 @@ static void hair_pack_mcol(MCol *mcol, unsigned short r_scol[3])
static int hair_batch_cache_fill_strands_data(
const HairExportCache *hair_export,
- Gwn_VertBufRaw *data_step,
- Gwn_VertBufRaw *uv_step, int num_uv_layers,
- Gwn_VertBufRaw *col_step, int num_col_layers)
+ GPUVertBufRaw *data_step,
+ GPUVertBufRaw *uv_step, int num_uv_layers,
+ GPUVertBufRaw *col_step, int num_col_layers)
{
int curr_point = 0;
for (int i = 0; i < hair_export->totcurves; i++) {
@@ -226,7 +226,7 @@ static int hair_batch_cache_fill_strands_data(
continue;
}
- uint *seg_data = (uint *)GWN_vertbuf_raw_step(data_step);
+ uint *seg_data = (uint *)GPU_vertbuf_raw_step(data_step);
const uint numseg = curve->numverts - 1;
*seg_data = (curr_point & 0xFFFFFF) | (numseg << 24);
curr_point += curve->numverts;
@@ -266,11 +266,11 @@ static int hair_batch_cache_fill_strands_data(
#endif
for (int k = 0; k < num_uv_layers; k++) {
- float *t_uv = (float *)GWN_vertbuf_raw_step(uv_step + k);
+ float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k);
copy_v2_v2(t_uv, uv[k]);
}
for (int k = 0; k < num_col_layers; k++) {
- unsigned short *scol = (unsigned short *)GWN_vertbuf_raw_step(col_step + k);
+ unsigned short *scol = (unsigned short *)GPU_vertbuf_raw_step(col_step + k);
hair_pack_mcol(&mcol[k], scol);
}
@@ -306,36 +306,36 @@ static void hair_batch_cache_ensure_procedural_strand_data(
}
#endif
- Gwn_VertBufRaw data_step;
- Gwn_VertBufRaw uv_step[MAX_MTFACE];
- Gwn_VertBufRaw col_step[MAX_MCOL];
+ GPUVertBufRaw data_step;
+ GPUVertBufRaw uv_step[MAX_MTFACE];
+ GPUVertBufRaw col_step[MAX_MCOL];
MTFace *mtfaces[MAX_MTFACE] = {NULL};
MCol *mcols[MAX_MCOL] = {NULL};
- Gwn_VertFormat format_data = {0};
- uint data_id = GWN_vertformat_attr_add(&format_data, "data", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat format_data = {0};
+ uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
- Gwn_VertFormat format_uv = {0};
- uint uv_id = GWN_vertformat_attr_add(&format_uv, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat format_uv = {0};
+ uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- Gwn_VertFormat format_col = {0};
- uint col_id = GWN_vertformat_attr_add(&format_col, "col", GWN_COMP_U16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat format_col = {0};
+ uint col_id = GPU_vertformat_attr_add(&format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names));
memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names));
/* Strand Data */
- cache->proc_strand_buf = GWN_vertbuf_create_with_format(&format_data);
- GWN_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
+ cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
+ GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
#if 0 // TODO
/* UV layers */
for (int i = 0; i < cache->num_uv_layers; i++) {
- cache->proc_uv_buf[i] = GWN_vertbuf_create_with_format(&format_uv);
- GWN_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
+ cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv);
+ GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
uint hash = BLI_ghashutil_strhash_p(name);
@@ -349,9 +349,9 @@ static void hair_batch_cache_ensure_procedural_strand_data(
}
/* Vertex colors */
for (int i = 0; i < cache->num_col_layers; i++) {
- cache->proc_col_buf[i] = GWN_vertbuf_create_with_format(&format_col);
- GWN_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
+ cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col);
+ GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
uint hash = BLI_ghashutil_strhash_p(name);
@@ -390,15 +390,15 @@ static void hair_batch_cache_ensure_procedural_strand_data(
col_step, cache->num_col_layers);
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->proc_strand_buf);
+ GPU_vertbuf_use(cache->proc_strand_buf);
cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
for (int i = 0; i < cache->num_uv_layers; i++) {
- GWN_vertbuf_use(cache->proc_uv_buf[i]);
+ GPU_vertbuf_use(cache->proc_uv_buf[i]);
cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]);
}
for (int i = 0; i < cache->num_col_layers; i++) {
- GWN_vertbuf_use(cache->proc_col_buf[i]);
+ GPU_vertbuf_use(cache->proc_col_buf[i]);
cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]);
}
}
@@ -422,17 +422,17 @@ static void hair_batch_cache_ensure_procedural_final_points(
int subdiv)
{
/* Same format as point_tex. */
- Gwn_VertFormat format = { 0 };
- GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat format = { 0 };
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->final[subdiv].proc_point_buf = GWN_vertbuf_create_with_format(&format);
+ cache->final[subdiv].proc_point_buf = GPU_vertbuf_create_with_format(&format);
/* Create a destination buffer for the tranform feedback. Sized appropriately */
/* Thoses are points! not line segments. */
- GWN_vertbuf_data_alloc(cache->final[subdiv].proc_point_buf, cache->final[subdiv].point_len);
+ GPU_vertbuf_data_alloc(cache->final[subdiv].proc_point_buf, cache->final[subdiv].point_len);
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->final[subdiv].proc_point_buf);
+ GPU_vertbuf_use(cache->final[subdiv].proc_point_buf);
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_point_buf);
}
@@ -441,7 +441,7 @@ static int hair_batch_cache_fill_segments_indices(
const HairExportCache *hair_export,
const int subdiv,
const int thickness_res,
- Gwn_IndexBufBuilder *elb)
+ GPUIndexBufBuilder *elb)
{
int curr_point = 0;
for (int i = 0; i < hair_export->totcurves; i++) {
@@ -452,9 +452,9 @@ static int hair_batch_cache_fill_segments_indices(
const int res = (((curve->numverts - 1) << subdiv) + 1) * thickness_res;
for (int k = 0; k < res; k++) {
- GWN_indexbuf_add_generic_vert(elb, curr_point++);
+ GPU_indexbuf_add_generic_vert(elb, curr_point++);
}
- GWN_indexbuf_add_primitive_restart(elb);
+ GPU_indexbuf_add_primitive_restart(elb);
}
return curr_point;
}
@@ -472,27 +472,27 @@ static void hair_batch_cache_ensure_procedural_indices(
}
int element_count = cache->final[subdiv].elems_len;
- Gwn_PrimType prim_type = (thickness_res == 1) ? GWN_PRIM_LINE_STRIP : GWN_PRIM_TRI_STRIP;
+ GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
- static Gwn_VertFormat format = { 0 };
- GWN_vertformat_clear(&format);
+ static GPUVertFormat format = { 0 };
+ GPU_vertformat_clear(&format);
/* initialize vertex format */
- GWN_vertformat_attr_add(&format, "dummy", GWN_COMP_U8, 1, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true);
hair_batch_cache_fill_segments_indices(hair_export, subdiv, thickness_res, &elb);
- cache->final[subdiv].proc_hairs[thickness_res - 1] = GWN_batch_create_ex(
+ cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
prim_type,
vbo,
- GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GPU_indexbuf_build(&elb),
+ GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
/* Ensure all textures and buffers needed for GPU accelerated drawing. */
@@ -541,14 +541,14 @@ bool hair_ensure_procedural_data(
return need_ft_update;
}
-Gwn_Batch *DRW_hair_batch_cache_get_fibers(HairSystem *hsys, const HairExportCache *hair_export)
+GPUBatch *DRW_hair_batch_cache_get_fibers(HairSystem *hsys, const HairExportCache *hair_export)
{
// TODO
UNUSED_VARS(hsys, hair_export);
return NULL;
}
-Gwn_Batch *DRW_hair_batch_cache_get_follicle_points(HairSystem *hsys, const HairExportCache *hair_export)
+GPUBatch *DRW_hair_batch_cache_get_follicle_points(HairSystem *hsys, const HairExportCache *hair_export)
{
// TODO
UNUSED_VARS(hsys, hair_export);
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index 99dce2d7343..d6acc4112d6 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -279,16 +279,16 @@ enum {
};
/* ---------------------------------------------------------------------- */
-/* Lattice Gwn_Batch Cache */
+/* Lattice GPUBatch Cache */
typedef struct LatticeBatchCache {
- Gwn_VertBuf *pos;
- Gwn_IndexBuf *edges;
+ GPUVertBuf *pos;
+ GPUIndexBuf *edges;
- Gwn_Batch *all_verts;
- Gwn_Batch *all_edges;
+ GPUBatch *all_verts;
+ GPUBatch *all_edges;
- Gwn_Batch *overlay_verts;
+ GPUBatch *overlay_verts;
/* settings to determine if cache is invalid */
bool is_dirty;
@@ -301,7 +301,7 @@ typedef struct LatticeBatchCache {
bool is_editmode;
} LatticeBatchCache;
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
static bool lattice_batch_cache_valid(Lattice *lt)
{
@@ -373,7 +373,7 @@ void DRW_lattice_batch_cache_dirty(Lattice *lt, int mode)
break;
case BKE_LATTICE_BATCH_DIRTY_SELECT:
/* TODO Separate Flag vbo */
- GWN_BATCH_DISCARD_SAFE(cache->overlay_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_verts);
break;
default:
BLI_assert(0);
@@ -387,12 +387,12 @@ static void lattice_batch_cache_clear(Lattice *lt)
return;
}
- GWN_BATCH_DISCARD_SAFE(cache->all_verts);
- GWN_BATCH_DISCARD_SAFE(cache->all_edges);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->all_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->all_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_verts);
- GWN_VERTBUF_DISCARD_SAFE(cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(cache->edges);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->edges);
}
void DRW_lattice_batch_cache_free(Lattice *lt)
@@ -401,38 +401,38 @@ void DRW_lattice_batch_cache_free(Lattice *lt)
MEM_SAFE_FREE(lt->batch_cache);
}
-/* Gwn_Batch cache usage. */
-static Gwn_VertBuf *lattice_batch_cache_get_pos(LatticeRenderData *rdata, LatticeBatchCache *cache,
+/* GPUBatch cache usage. */
+static GPUVertBuf *lattice_batch_cache_get_pos(LatticeRenderData *rdata, LatticeBatchCache *cache,
bool use_weight, const int actdef)
{
BLI_assert(rdata->types & LR_DATATYPE_VERT);
if (cache->pos == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, col; } attr_id;
- GWN_vertformat_clear(&format);
+ GPU_vertformat_clear(&format);
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
if (use_weight) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
const int vert_len = lattice_render_data_verts_len_get(rdata);
- cache->pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->pos, vert_len);
+ cache->pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache->pos, vert_len);
for (int i = 0; i < vert_len; ++i) {
const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i);
- GWN_vertbuf_attr_set(cache->pos, attr_id.pos, i, bp->vec);
+ GPU_vertbuf_attr_set(cache->pos, attr_id.pos, i, bp->vec);
if (use_weight) {
float w_col[4];
lattice_render_data_weight_col_get(rdata, i, actdef, w_col);
- GWN_vertbuf_attr_set(cache->pos, attr_id.col, i, w_col);
+ GPU_vertbuf_attr_set(cache->pos, attr_id.col, i, w_col);
}
}
}
@@ -440,7 +440,7 @@ static Gwn_VertBuf *lattice_batch_cache_get_pos(LatticeRenderData *rdata, Lattic
return cache->pos;
}
-static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, LatticeBatchCache *cache)
+static GPUIndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, LatticeBatchCache *cache)
{
BLI_assert(rdata->types & (LR_DATATYPE_VERT | LR_DATATYPE_EDGE));
@@ -449,8 +449,8 @@ static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, Lat
const int edge_len = lattice_render_data_edges_len_get(rdata);
int edge_len_real = 0;
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
#define LATT_INDEX(u, v, w) \
((((w) * rdata->dims.v_len + (v)) * rdata->dims.u_len) + (u))
@@ -463,17 +463,17 @@ static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, Lat
int uxt = (u == 0 || u == rdata->dims.u_len - 1);
if (w && ((uxt || vxt) || !rdata->show_only_outside)) {
- GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v, w - 1), LATT_INDEX(u, v, w));
+ GPU_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v, w - 1), LATT_INDEX(u, v, w));
BLI_assert(edge_len_real <= edge_len);
edge_len_real++;
}
if (v && ((uxt || wxt) || !rdata->show_only_outside)) {
- GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v - 1, w), LATT_INDEX(u, v, w));
+ GPU_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v - 1, w), LATT_INDEX(u, v, w));
BLI_assert(edge_len_real <= edge_len);
edge_len_real++;
}
if (u && ((vxt || wxt) || !rdata->show_only_outside)) {
- GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u - 1, v, w), LATT_INDEX(u, v, w));
+ GPU_indexbuf_add_line_verts(&elb, LATT_INDEX(u - 1, v, w), LATT_INDEX(u, v, w));
BLI_assert(edge_len_real <= edge_len);
edge_len_real++;
}
@@ -490,7 +490,7 @@ static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, Lat
BLI_assert(edge_len_real == edge_len);
}
- cache->edges = GWN_indexbuf_build(&elb);
+ cache->edges = GPU_indexbuf_build(&elb);
}
return cache->edges;
@@ -505,18 +505,18 @@ static void lattice_batch_cache_create_overlay_batches(Lattice *lt)
LatticeRenderData *rdata = lattice_render_data_create(lt, options);
if (cache->overlay_verts == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
const int vert_len = lattice_render_data_verts_len_get(rdata);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vert_len);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
for (int i = 0; i < vert_len; ++i) {
const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i);
@@ -530,17 +530,17 @@ static void lattice_batch_cache_create_overlay_batches(Lattice *lt)
}
}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, bp->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.data, i, &vflag);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, bp->vec);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, i, &vflag);
}
- cache->overlay_verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->overlay_verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
lattice_render_data_free(rdata);
}
-Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, const int actdef)
+GPUBatch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, const int actdef)
{
LatticeBatchCache *cache = lattice_batch_cache_get(lt);
@@ -548,7 +548,7 @@ Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, c
/* create batch from Lattice */
LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT | LR_DATATYPE_EDGE);
- cache->all_edges = GWN_batch_create(GWN_PRIM_LINES, lattice_batch_cache_get_pos(rdata, cache, use_weight, actdef),
+ cache->all_edges = GPU_batch_create(GPU_PRIM_LINES, lattice_batch_cache_get_pos(rdata, cache, use_weight, actdef),
lattice_batch_cache_get_edges(rdata, cache));
lattice_render_data_free(rdata);
@@ -557,14 +557,14 @@ Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, c
return cache->all_edges;
}
-Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt)
+GPUBatch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt)
{
LatticeBatchCache *cache = lattice_batch_cache_get(lt);
if (cache->all_verts == NULL) {
LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT);
- cache->all_verts = GWN_batch_create(GWN_PRIM_POINTS, lattice_batch_cache_get_pos(rdata, cache, false, -1), NULL);
+ cache->all_verts = GPU_batch_create(GPU_PRIM_POINTS, lattice_batch_cache_get_pos(rdata, cache, false, -1), NULL);
lattice_render_data_free(rdata);
}
@@ -572,7 +572,7 @@ Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt)
return cache->all_verts;
}
-Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(Lattice *lt)
+GPUBatch *DRW_lattice_batch_cache_get_overlay_verts(Lattice *lt)
{
LatticeBatchCache *cache = lattice_batch_cache_get(lt);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 7a72622cb9e..1cf270048e1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -202,8 +202,8 @@ typedef struct MeshRenderData {
float (*poly_normals)[3];
float (*vert_weight_color)[3];
char (*vert_color)[3];
- Gwn_PackedNormal *poly_normals_pack;
- Gwn_PackedNormal *vert_normals_pack;
+ GPUPackedNormal *poly_normals_pack;
+ GPUPackedNormal *vert_normals_pack;
bool *edge_select_bool;
} MeshRenderData;
@@ -427,7 +427,10 @@ static MeshRenderData *mesh_render_data_create_ex(
int totloop = bm->totloop;
if (is_auto_smooth) {
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__);
- BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
+ int cd_loop_clnors_offset = CustomData_get_layer_index(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ BM_loops_calc_normal_vcos(
+ bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL,
+ cd_loop_clnors_offset, false);
}
rdata->loop_len = totloop;
bm_ensure_types |= BM_LOOP;
@@ -726,7 +729,7 @@ static MeshRenderData *mesh_render_data_create_ex(
/* Should we store the previous array of `loop_normals` in somewhere? */
rdata->loop_len = bm->totloop;
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__);
- BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
+ BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1, false);
}
bool calc_active_tangent = false;
@@ -952,7 +955,7 @@ static int mesh_render_data_polys_len_get(const MeshRenderData *rdata)
/** Ensure #MeshRenderData.poly_normals_pack */
static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
{
- Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack;
+ GPUPackedNormal *pnors_pack = rdata->poly_normals_pack;
if (pnors_pack == NULL) {
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
@@ -962,7 +965,7 @@ static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
BM_ITER_MESH_INDEX(efa, &fiter, bm, BM_FACES_OF_MESH, i) {
- pnors_pack[i] = GWN_normal_convert_i10_v3(efa->no);
+ pnors_pack[i] = GPU_normal_convert_i10_v3(efa->no);
}
}
else {
@@ -977,7 +980,7 @@ static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
for (int i = 0; i < rdata->poly_len; i++) {
- pnors_pack[i] = GWN_normal_convert_i10_v3(pnors[i]);
+ pnors_pack[i] = GPU_normal_convert_i10_v3(pnors[i]);
}
}
}
@@ -986,7 +989,7 @@ static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
/** Ensure #MeshRenderData.vert_normals_pack */
static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata)
{
- Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack;
+ GPUPackedNormal *vnors_pack = rdata->vert_normals_pack;
if (vnors_pack == NULL) {
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
@@ -996,7 +999,7 @@ static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata)
vnors_pack = rdata->vert_normals_pack = MEM_mallocN(sizeof(*vnors_pack) * rdata->vert_len, __func__);
BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) {
- vnors_pack[i] = GWN_normal_convert_i10_v3(eve->no);
+ vnors_pack[i] = GPU_normal_convert_i10_v3(eve->no);
}
}
else {
@@ -1413,7 +1416,7 @@ static uchar mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *e
}
static void add_overlay_tri(
- MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id,
const BMLoop **bm_looptri, const int base_vert_idx)
{
@@ -1426,24 +1429,24 @@ static void add_overlay_tri(
for (uint i = 0; i < 3; i++) {
int vidx = BM_elem_index_get(bm_looptri[i]->v);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
else {
for (uint i = 0; i < 3; i++) {
const float *pos = bm_looptri[i]->v->co;
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
}
if (vbo_nor) {
/* TODO real loop normal */
- Gwn_PackedNormal lnor = GWN_normal_convert_i10_v3(bm_looptri[0]->f->no);
+ GPUPackedNormal lnor = GPU_normal_convert_i10_v3(bm_looptri[0]->f->no);
for (uint i = 0; i < 3; i++) {
- Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(bm_looptri[i]->v->no);
- GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
- GWN_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
+ GPUPackedNormal vnor = GPU_normal_convert_i10_v3(bm_looptri[i]->v->no);
+ GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPU_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
}
}
@@ -1457,7 +1460,7 @@ static void add_overlay_tri(
mesh_render_data_edge_flag(rdata, bm_looptri[i_next]->e, &eattr);
}
eattr.v_flag = fflag | vflag;
- GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
+ GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
i_prev = i;
i = i_next;
@@ -1466,7 +1469,7 @@ static void add_overlay_tri(
}
static void add_overlay_loose_edge(
- MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
const BMEdge *eed, const int base_vert_idx)
{
@@ -1476,21 +1479,21 @@ static void add_overlay_loose_edge(
for (uint i = 0; i < 2; i++) {
int vidx = BM_elem_index_get((&eed->v1)[i]);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
else {
for (int i = 0; i < 2; ++i) {
const float *pos = (&eed->v1)[i]->co;
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
}
if (vbo_nor) {
for (int i = 0; i < 2; ++i) {
- Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3((&eed->v1)[i]->no);
- GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPUPackedNormal vnor = GPU_normal_convert_i10_v3((&eed->v1)[i]->no);
+ GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
}
}
@@ -1499,13 +1502,13 @@ static void add_overlay_loose_edge(
mesh_render_data_edge_flag(rdata, eed, &eattr);
for (int i = 0; i < 2; ++i) {
eattr.v_flag = mesh_render_data_vertex_flag(rdata, (&eed->v1)[i]);
- GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
+ GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
}
}
}
static void add_overlay_loose_vert(
- MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
const BMVert *eve, const int base_vert_idx)
{
@@ -1514,23 +1517,23 @@ static void add_overlay_loose_vert(
if (rdata->edit_data && rdata->edit_data->vertexCos) {
int vidx = BM_elem_index_get(eve);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
}
else {
const float *pos = eve->co;
- GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
+ GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
}
}
if (vbo_nor) {
- Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(eve->no);
- GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
+ GPUPackedNormal vnor = GPU_normal_convert_i10_v3(eve->no);
+ GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
}
if (vbo_data) {
uchar vflag[4] = {0, 0, 0, 0};
vflag[0] = mesh_render_data_vertex_flag(rdata, eve);
- GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag);
+ GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag);
}
}
@@ -1539,96 +1542,96 @@ static void add_overlay_loose_vert(
/* ---------------------------------------------------------------------- */
-/** \name Mesh Gwn_Batch Cache
+/** \name Mesh GPUBatch Cache
* \{ */
typedef struct MeshBatchCache {
- Gwn_VertBuf *pos_in_order;
- Gwn_IndexBuf *edges_in_order;
- Gwn_IndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */
- Gwn_IndexBuf *triangles_in_order;
- Gwn_IndexBuf *ledges_in_order;
+ GPUVertBuf *pos_in_order;
+ GPUIndexBuf *edges_in_order;
+ GPUIndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */
+ GPUIndexBuf *triangles_in_order;
+ GPUIndexBuf *ledges_in_order;
GPUTexture *pos_in_order_tx; /* Depending on pos_in_order */
- Gwn_Batch *all_verts;
- Gwn_Batch *all_edges;
- Gwn_Batch *all_triangles;
+ GPUBatch *all_verts;
+ GPUBatch *all_edges;
+ GPUBatch *all_triangles;
- Gwn_VertBuf *pos_with_normals;
- Gwn_VertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
+ GPUVertBuf *pos_with_normals;
+ GPUVertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
/**
* Other uses are all positions or loose elements.
* This stores all visible elements, needed for selection.
*/
- Gwn_VertBuf *ed_fcenter_pos_with_nor_and_sel;
- Gwn_VertBuf *ed_edge_pos;
- Gwn_VertBuf *ed_vert_pos;
+ GPUVertBuf *ed_fcenter_pos_with_nor_and_sel;
+ GPUVertBuf *ed_edge_pos;
+ GPUVertBuf *ed_vert_pos;
- Gwn_Batch *triangles_with_normals;
- Gwn_Batch *ledges_with_normals;
+ GPUBatch *triangles_with_normals;
+ GPUBatch *ledges_with_normals;
/* Skip hidden (depending on paint select mode) */
- Gwn_Batch *triangles_with_weights;
- Gwn_Batch *triangles_with_vert_colors;
+ GPUBatch *triangles_with_weights;
+ GPUBatch *triangles_with_vert_colors;
/* Always skip hidden */
- Gwn_Batch *triangles_with_select_mask;
- Gwn_Batch *triangles_with_select_id;
+ GPUBatch *triangles_with_select_mask;
+ GPUBatch *triangles_with_select_id;
uint triangles_with_select_id_offset;
- Gwn_Batch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */
- Gwn_Batch *edges_with_select_id;
- Gwn_Batch *verts_with_select_id;
+ GPUBatch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */
+ GPUBatch *edges_with_select_id;
+ GPUBatch *verts_with_select_id;
uint facedot_with_select_id_offset;
uint edges_with_select_id_offset;
uint verts_with_select_id_offset;
- Gwn_Batch *points_with_normals;
- Gwn_Batch *fancy_edges; /* owns its vertex buffer (not shared) */
+ GPUBatch *points_with_normals;
+ GPUBatch *fancy_edges; /* owns its vertex buffer (not shared) */
- Gwn_Batch *edge_detection;
+ GPUBatch *edge_detection;
- Gwn_VertBuf *edges_face_overlay;
+ GPUVertBuf *edges_face_overlay;
GPUTexture *edges_face_overlay_tx;
int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay(_adj)_tx */
/* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
* to minimize data transfer for skinned mesh. */
- Gwn_VertFormat shaded_triangles_format;
- Gwn_VertBuf *shaded_triangles_data;
- Gwn_IndexBuf **shaded_triangles_in_order;
- Gwn_Batch **shaded_triangles;
+ GPUVertFormat shaded_triangles_format;
+ GPUVertBuf *shaded_triangles_data;
+ GPUIndexBuf **shaded_triangles_in_order;
+ GPUBatch **shaded_triangles;
/* Texture Paint.*/
/* per-texture batch */
- Gwn_Batch **texpaint_triangles;
- Gwn_Batch *texpaint_triangles_single;
+ GPUBatch **texpaint_triangles;
+ GPUBatch *texpaint_triangles_single;
/* Edit Cage Mesh buffers */
- Gwn_VertBuf *ed_tri_pos;
- Gwn_VertBuf *ed_tri_nor; /* LoopNor, VertNor */
- Gwn_VertBuf *ed_tri_data;
+ GPUVertBuf *ed_tri_pos;
+ GPUVertBuf *ed_tri_nor; /* LoopNor, VertNor */
+ GPUVertBuf *ed_tri_data;
- Gwn_VertBuf *ed_ledge_pos;
- Gwn_VertBuf *ed_ledge_nor; /* VertNor */
- Gwn_VertBuf *ed_ledge_data;
+ GPUVertBuf *ed_ledge_pos;
+ GPUVertBuf *ed_ledge_nor; /* VertNor */
+ GPUVertBuf *ed_ledge_data;
- Gwn_VertBuf *ed_lvert_pos;
- Gwn_VertBuf *ed_lvert_nor; /* VertNor */
- Gwn_VertBuf *ed_lvert_data;
+ GPUVertBuf *ed_lvert_pos;
+ GPUVertBuf *ed_lvert_nor; /* VertNor */
+ GPUVertBuf *ed_lvert_data;
- Gwn_Batch *overlay_triangles;
- Gwn_Batch *overlay_triangles_nor; /* GWN_PRIM_POINTS */
- Gwn_Batch *overlay_loose_edges;
- Gwn_Batch *overlay_loose_edges_nor; /* GWN_PRIM_POINTS */
- Gwn_Batch *overlay_loose_verts;
- Gwn_Batch *overlay_facedots;
+ GPUBatch *overlay_triangles;
+ GPUBatch *overlay_triangles_nor; /* GPU_PRIM_POINTS */
+ GPUBatch *overlay_loose_edges;
+ GPUBatch *overlay_loose_edges_nor; /* GPU_PRIM_POINTS */
+ GPUBatch *overlay_loose_verts;
+ GPUBatch *overlay_facedots;
- Gwn_Batch *overlay_weight_faces;
- Gwn_Batch *overlay_weight_verts;
- Gwn_Batch *overlay_paint_edges;
+ GPUBatch *overlay_weight_faces;
+ GPUBatch *overlay_weight_verts;
+ GPUBatch *overlay_paint_edges;
/* arrays of bool uniform names (and value) that will be use to
* set srgb conversion for auto attribs.*/
@@ -1653,7 +1656,7 @@ typedef struct MeshBatchCache {
bool is_manifold;
} MeshBatchCache;
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
static bool mesh_batch_cache_valid(Mesh *me)
{
@@ -1742,21 +1745,21 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
cache->is_maybe_dirty = true;
break;
case BKE_MESH_BATCH_DIRTY_SELECT:
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
-
- GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
+
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_facedots);
/* Edit mode selection. */
- GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
cache->is_dirty = true;
@@ -1777,7 +1780,7 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
/**
* This only clear the batches associated to the given vertex buffer.
**/
-static void mesh_batch_cache_clear_selective(Mesh *me, Gwn_VertBuf *vert)
+static void mesh_batch_cache_clear_selective(Mesh *me, GPUVertBuf *vert)
{
MeshBatchCache *cache = me->runtime.batch_cache;
if (!cache) {
@@ -1787,26 +1790,26 @@ static void mesh_batch_cache_clear_selective(Mesh *me, Gwn_VertBuf *vert)
BLI_assert(vert != NULL);
if (cache->pos_with_normals == vert) {
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
- GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
- GWN_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
+ GPU_BATCH_DISCARD_SAFE(cache->points_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
if (cache->shaded_triangles) {
for (int i = 0; i < cache->mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
}
}
MEM_SAFE_FREE(cache->shaded_triangles);
if (cache->texpaint_triangles) {
for (int i = 0; i < cache->mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
}
}
MEM_SAFE_FREE(cache->texpaint_triangles);
- GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
+ GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
}
/* TODO: add the other ones if needed. */
else {
@@ -1822,69 +1825,69 @@ static void mesh_batch_cache_clear(Mesh *me)
return;
}
- GWN_BATCH_DISCARD_SAFE(cache->all_verts);
- GWN_BATCH_DISCARD_SAFE(cache->all_edges);
- GWN_BATCH_DISCARD_SAFE(cache->all_triangles);
+ GPU_BATCH_DISCARD_SAFE(cache->all_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->all_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->all_triangles);
- GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
DRW_TEXTURE_FREE_SAFE(cache->pos_in_order_tx);
- GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
- GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
- GWN_INDEXBUF_DISCARD_SAFE(cache->ledges_in_order);
-
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
-
- GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
- GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
-
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
- GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
- GWN_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
- GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
- GWN_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
- GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
- GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
-
- GWN_BATCH_DISCARD_SAFE(cache->fancy_edges);
-
- GWN_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency);
- GWN_BATCH_DISCARD_SAFE(cache->edge_detection);
-
- GWN_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ledges_in_order);
+
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
+
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_facedots);
+
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->points_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
+ GPU_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+
+ GPU_BATCH_DISCARD_SAFE(cache->fancy_edges);
+
+ GPU_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency);
+ GPU_BATCH_DISCARD_SAFE(cache->edge_detection);
+
+ GPU_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay);
DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx);
- GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
if (cache->shaded_triangles_in_order) {
for (int i = 0; i < cache->mat_len; ++i) {
- GWN_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
}
}
if (cache->shaded_triangles) {
for (int i = 0; i < cache->mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
}
}
@@ -1896,12 +1899,12 @@ static void mesh_batch_cache_clear(Mesh *me)
if (cache->texpaint_triangles) {
for (int i = 0; i < cache->mat_len; ++i) {
- GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
}
}
MEM_SAFE_FREE(cache->texpaint_triangles);
- GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
+ GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
}
@@ -1911,9 +1914,9 @@ void DRW_mesh_batch_cache_free(Mesh *me)
MEM_SAFE_FREE(me->runtime.batch_cache);
}
-/* Gwn_Batch cache usage. */
+/* GPUBatch cache usage. */
-static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUVertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
#define USE_COMP_MESH_DATA
@@ -1928,9 +1931,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
return NULL;
}
- Gwn_VertFormat *format = &cache->shaded_triangles_format;
+ GPUVertFormat *format = &cache->shaded_triangles_format;
- GWN_vertformat_clear(format);
+ GPU_vertformat_clear(format);
/* initialize vertex format */
uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len);
@@ -1968,14 +1971,14 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
/* UV */
const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i);
#if defined(USE_COMP_MESH_DATA) && 0 /* these are clamped. Maybe use them as an option in the future */
- uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ uv_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
#else
- uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uv_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
#endif
/* Auto Name */
attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
- GWN_vertformat_alias_add(format, attrib_name);
+ GPU_vertformat_alias_add(format, attrib_name);
/* +1 include null terminator. */
auto_ofs += 1 + BLI_snprintf_rlen(
@@ -1983,7 +1986,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */
if (i == rdata->cd.layers.uv_active) {
- GWN_vertformat_alias_add(format, "u");
+ GPU_vertformat_alias_add(format, "u");
}
}
@@ -1993,25 +1996,25 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
* That may cause some problem but I could not make it to fail (fclem) */
#ifdef USE_COMP_MESH_DATA
/* Tangents need more precision than 10_10_10 */
- tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ tangent_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
#else
- tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ tangent_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
#endif
if (i == rdata->cd.layers.tangent_active) {
- GWN_vertformat_alias_add(format, "t");
+ GPU_vertformat_alias_add(format, "t");
}
}
for (uint i = 0; i < vcol_len; i++) {
const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i);
- vcol_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ vcol_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
/* Auto layer */
if (rdata->cd.layers.auto_vcol[i]) {
attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
- GWN_vertformat_alias_add(format, attrib_name);
+ GPU_vertformat_alias_add(format, attrib_name);
/* +1 include null terminator. */
auto_ofs += 1 + BLI_snprintf_rlen(
@@ -2020,23 +2023,23 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
}
if (i == rdata->cd.layers.vcol_active) {
- GWN_vertformat_alias_add(format, "c");
+ GPU_vertformat_alias_add(format, "c");
}
}
const uint tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_VertBuf *vbo = cache->shaded_triangles_data = GWN_vertbuf_create_with_format(format);
+ GPUVertBuf *vbo = cache->shaded_triangles_data = GPU_vertbuf_create_with_format(format);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
+ GPUVertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
- Gwn_VertBufRaw *uv_step = layers_combined_step;
- Gwn_VertBufRaw *tangent_step = uv_step + uv_len;
- Gwn_VertBufRaw *vcol_step = tangent_step + tangent_len;
+ GPUVertBufRaw *uv_step = layers_combined_step;
+ GPUVertBufRaw *tangent_step = uv_step + uv_len;
+ GPUVertBufRaw *vcol_step = tangent_step + tangent_len;
/* Not needed, just for sanity. */
if (uv_len == 0) { uv_step = NULL; }
@@ -2044,16 +2047,16 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
if (vcol_len == 0) { vcol_step = NULL; }
for (uint i = 0; i < uv_len; i++) {
- GWN_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
}
for (uint i = 0; i < tangent_len; i++) {
- GWN_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
}
for (uint i = 0; i < vcol_len; i++) {
- GWN_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
+ GPU_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
}
- /* TODO deduplicate all verts and make use of Gwn_IndexBuf in
+ /* TODO deduplicate all verts and make use of GPUIndexBuf in
* mesh_batch_cache_get_triangles_in_order_split_by_material. */
if (rdata->edit_bmesh) {
for (uint i = 0; i < tri_len; i++) {
@@ -2066,7 +2069,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
const uint layer_offset = rdata->cd.offset.uv[j];
for (uint t = 0; t < 3; t++) {
const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->uv;
- copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
+ copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
}
}
/* TANGENTs */
@@ -2074,7 +2077,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
float (*layer_data)[4] = rdata->cd.layers.tangent[j];
for (uint t = 0; t < 3; t++) {
const float *elem = layer_data[BM_elem_index_get(bm_looptri[t])];
- normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+ normal_float_to_short_v3(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
}
}
/* VCOLs */
@@ -2082,7 +2085,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
const uint layer_offset = rdata->cd.offset.vcol[j];
for (uint t = 0; t < 3; t++) {
const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->r;
- copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
+ copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
}
}
}
@@ -2096,7 +2099,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
const MLoopUV *layer_data = rdata->cd.layers.uv[j];
for (uint t = 0; t < 3; t++) {
const float *elem = layer_data[mlt->tri[t]].uv;
- copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
+ copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
}
}
/* TANGENTs */
@@ -2105,9 +2108,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
for (uint t = 0; t < 3; t++) {
const float *elem = layer_data[mlt->tri[t]];
#ifdef USE_COMP_MESH_DATA
- normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+ normal_float_to_short_v3(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
#else
- copy_v3_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+ copy_v3_v3(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
#endif
}
}
@@ -2116,25 +2119,25 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
const MLoopCol *layer_data = rdata->cd.layers.vcol[j];
for (uint t = 0; t < 3; t++) {
const uchar *elem = &layer_data[mlt->tri[t]].r;
- copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
+ copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
}
}
}
}
- vbo_len_used = GWN_vertbuf_raw_used(&layers_combined_step[0]);
+ vbo_len_used = GPU_vertbuf_raw_used(&layers_combined_step[0]);
#ifndef NDEBUG
/* Check all layers are write aligned. */
if (layers_combined_len > 1) {
for (uint i = 1; i < layers_combined_len; i++) {
- BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&layers_combined_step[i]));
+ BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&layers_combined_step[i]));
}
}
#endif
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
@@ -2143,7 +2146,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
return cache->shaded_triangles_data;
}
-static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
+static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV));
@@ -2157,19 +2160,19 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
uint vidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint uv; } attr_id;
if (format.attr_len == 0) {
- attr_id.uv = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.uv = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_VertBuf *vbo = cache->tri_aligned_uv = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = cache->tri_aligned_uv = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
BMEditMesh *embm = rdata->edit_bmesh;
@@ -2189,7 +2192,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
const int index = BM_elem_index_get(loop);
if (index != -1) {
const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
- GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem);
+ GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem);
}
}
}
@@ -2198,9 +2201,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
/* object mode */
for (int i = 0; i < tri_len; i++) {
const MLoopTri *mlt = &rdata->mlooptri[i];
- GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
- GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
- GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
+ GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
+ GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
+ GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
}
}
@@ -2213,36 +2216,36 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
return cache->tri_aligned_uv;
}
-static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
+static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
MeshRenderData *rdata, const bool use_hide,
- Gwn_VertBuf **r_vbo)
+ GPUVertBuf **r_vbo)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
if (*r_vbo == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_VertBuf *vbo = *r_vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = *r_vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw pos_step, nor_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
+ GPUVertBufRaw pos_step, nor_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
float (*lnors)[3] = rdata->loop_normals;
if (rdata->edit_bmesh) {
- Gwn_PackedNormal *pnors_pack, *vnors_pack;
+ GPUPackedNormal *pnors_pack, *vnors_pack;
if (lnors == NULL) {
mesh_render_data_ensure_poly_normals_pack(rdata);
@@ -2264,18 +2267,18 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
if (lnors) {
for (uint t = 0; t < 3; t++) {
const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
}
}
else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
for (uint t = 0; t < 3; t++) {
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
}
}
else {
- const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
+ const GPUPackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
for (uint t = 0; t < 3; t++) {
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack;
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *snor_pack;
}
}
@@ -2284,12 +2287,12 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
for (uint t = 0; t < 3; t++) {
int vidx = BM_elem_index_get(bm_looptri[t]->v);
const float *pos = rdata->edit_data->vertexCos[vidx];
- copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), pos);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), pos);
}
}
else {
for (uint t = 0; t < 3; t++) {
- copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
}
}
}
@@ -2317,85 +2320,85 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
if (lnors) {
for (uint t = 0; t < 3; t++) {
const float *nor = lnors[mlt->tri[t]];
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
}
}
else if (mp->flag & ME_SMOOTH) {
for (uint t = 0; t < 3; t++) {
const MVert *mv = &rdata->mvert[vtri[t]];
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_s3(mv->no);
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_s3(mv->no);
}
}
else {
- const Gwn_PackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
+ const GPUPackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
for (uint t = 0; t < 3; t++) {
- *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *pnors_pack;
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *pnors_pack;
}
}
for (uint t = 0; t < 3; t++) {
const MVert *mv = &rdata->mvert[vtri[t]];
- copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), mv->co);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mv->co);
}
}
}
- vbo_len_used = GWN_vertbuf_raw_used(&pos_step);
- BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&nor_step));
+ vbo_len_used = GPU_vertbuf_raw_used(&pos_step);
+ BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&nor_step));
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return *r_vbo;
}
-static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals(
+static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals(
MeshRenderData *rdata, MeshBatchCache *cache)
{
return mesh_batch_cache_get_tri_pos_and_normals_ex(
rdata, false,
&cache->pos_with_normals);
}
-static Gwn_VertBuf *mesh_create_tri_pos_and_normals_visible_only(
+static GPUVertBuf *mesh_create_tri_pos_and_normals_visible_only(
MeshRenderData *rdata)
{
- Gwn_VertBuf *vbo_dummy = NULL;
+ GPUVertBuf *vbo_dummy = NULL;
return mesh_batch_cache_get_tri_pos_and_normals_ex(
rdata, true,
&vbo_dummy);
}
-static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
+static GPUVertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.data = GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
int vidx = 0;
- Gwn_VertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
for (int i = 0; i < vbo_len_capacity; ++i) {
float pcenter[3], pnor[3];
bool selected = false;
if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) {
- Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 };
- nor = GWN_normal_convert_i10_v3(pnor);
+ GPUPackedNormal nor = { .x = 0, .y = 0, .z = -511 };
+ nor = GPU_normal_convert_i10_v3(pnor);
nor.w = selected ? 1 : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
vidx += 1;
}
@@ -2403,30 +2406,30 @@ static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
const int vbo_len_used = vidx;
BLI_assert(vbo_len_used <= vbo_len_capacity);
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return cache->ed_fcenter_pos_with_nor_and_sel;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
+static GPUVertBuf *mesh_batch_cache_get_edges_visible(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
if (cache->ed_edge_pos == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
int vidx = 0;
- Gwn_VertBuf *vbo = cache->ed_edge_pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBuf *vbo = cache->ed_edge_pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter;
@@ -2434,9 +2437,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co);
vidx += 1;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co);
vidx += 1;
}
}
@@ -2447,7 +2450,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
}
const int vbo_len_used = vidx;
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
UNUSED_VARS_NDEBUG(vbo_len_used);
}
@@ -2455,23 +2458,23 @@ static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
return cache->ed_edge_pos;
}
-static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
+static GPUVertBuf *mesh_batch_cache_get_verts_visible(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_vert_pos == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, data; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
uint vidx = 0;
- Gwn_VertBuf *vbo = cache->ed_vert_pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPUVertBuf *vbo = cache->ed_vert_pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter;
@@ -2479,7 +2482,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co);
vidx += 1;
}
}
@@ -2488,14 +2491,14 @@ static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
for (int i = 0; i < vbo_len_capacity; i++) {
const MVert *mv = &rdata->mvert[i];
if (!(mv->flag & ME_HIDE)) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co);
vidx += 1;
}
}
}
const uint vbo_len_used = vidx;
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
UNUSED_VARS_NDEBUG(vbo_len_used);
@@ -2504,24 +2507,24 @@ static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
return cache->ed_vert_pos;
}
-static Gwn_VertBuf *mesh_create_facedot_select_id(
+static GPUVertBuf *mesh_create_facedot_select_id(
MeshRenderData *rdata, uint select_id_offset)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
int vidx = 0;
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
uint select_index = select_id_offset;
if (rdata->edit_bmesh) {
@@ -2533,7 +2536,7 @@ static Gwn_VertBuf *mesh_create_facedot_select_id(
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
int select_id;
GPU_select_index_get(select_index, &select_id);
- GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
vidx += 1;
}
select_index += 1;
@@ -2545,31 +2548,31 @@ static Gwn_VertBuf *mesh_create_facedot_select_id(
}
const int vbo_len_used = vidx;
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_create_edges_select_id(
+static GPUVertBuf *mesh_create_edges_select_id(
MeshRenderData *rdata, uint select_id_offset)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
int vidx = 0;
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
uint select_index = select_id_offset;
if (rdata->edit_bmesh) {
@@ -2581,9 +2584,9 @@ static Gwn_VertBuf *mesh_create_edges_select_id(
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
int select_id;
GPU_select_index_get(select_index, &select_id);
- GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
vidx += 1;
- GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
vidx += 1;
}
select_index += 1;
@@ -2595,31 +2598,31 @@ static Gwn_VertBuf *mesh_create_edges_select_id(
}
const int vbo_len_used = vidx;
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_create_verts_select_id(
+static GPUVertBuf *mesh_create_verts_select_id(
MeshRenderData *rdata, uint select_id_offset)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
int vidx = 0;
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
uint select_index = select_id_offset;
if (rdata->edit_bmesh) {
@@ -2631,7 +2634,7 @@ static Gwn_VertBuf *mesh_create_verts_select_id(
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
int select_id;
GPU_select_index_get(select_index, &select_id);
- GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
vidx += 1;
}
select_index += 1;
@@ -2643,7 +2646,7 @@ static Gwn_VertBuf *mesh_create_verts_select_id(
if (!(mv->flag & ME_HIDE)) {
int select_id;
GPU_select_index_get(select_index, &select_id);
- GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
vidx += 1;
}
select_index += 1;
@@ -2651,36 +2654,36 @@ static Gwn_VertBuf *mesh_create_verts_select_id(
}
const int vbo_len_used = vidx;
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_create_tri_weights(
+static GPUVertBuf *mesh_create_tri_weights(
MeshRenderData *rdata, bool use_hide, int defgroup)
{
BLI_assert(
rdata->types &
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
uint cidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
- vbo = GWN_vertbuf_create_with_format(&format);
+ vbo = GPU_vertbuf_create_with_format(&format);
const int tri_len = mesh_render_data_looptri_len_get(rdata);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
mesh_render_data_ensure_vert_weight_color(rdata, defgroup);
const float (*vert_weight_color)[3] = rdata->vert_weight_color;
@@ -2692,7 +2695,7 @@ static Gwn_VertBuf *mesh_create_tri_weights(
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
const int v_index = BM_elem_index_get(ltri[tri_corner]->v);
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
}
}
}
@@ -2703,7 +2706,7 @@ static Gwn_VertBuf *mesh_create_tri_weights(
if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
const uint v_index = rdata->mloop[mlt->tri[tri_corner]].v;
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
}
}
}
@@ -2711,36 +2714,36 @@ static Gwn_VertBuf *mesh_create_tri_weights(
vbo_len_used = cidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_create_tri_vert_colors(
+static GPUVertBuf *mesh_create_tri_vert_colors(
MeshRenderData *rdata, bool use_hide)
{
BLI_assert(
rdata->types &
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
uint cidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- vbo = GWN_vertbuf_create_with_format(&format);
+ vbo = GPU_vertbuf_create_with_format(&format);
const uint vbo_len_capacity = tri_len * 3;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
mesh_render_data_ensure_vert_color(rdata);
const char (*vert_color)[3] = rdata->vert_color;
@@ -2752,7 +2755,7 @@ static Gwn_VertBuf *mesh_create_tri_vert_colors(
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
const int l_index = BM_elem_index_get(ltri[tri_corner]);
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
}
}
}
@@ -2763,7 +2766,7 @@ static Gwn_VertBuf *mesh_create_tri_vert_colors(
if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
const uint l_index = mlt->tri[tri_corner];
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
}
}
}
@@ -2771,37 +2774,37 @@ static Gwn_VertBuf *mesh_create_tri_vert_colors(
const uint vbo_len_used = cidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_create_tri_select_id(
+static GPUVertBuf *mesh_create_tri_select_id(
MeshRenderData *rdata, bool use_hide, uint select_id_offset)
{
BLI_assert(
rdata->types &
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
uint cidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint col; } attr_id;
if (format.attr_len == 0) {
- attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- vbo = GWN_vertbuf_create_with_format(&format);
+ vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
if (rdata->edit_bmesh) {
for (int i = 0; i < tri_len; i++) {
@@ -2812,7 +2815,7 @@ static Gwn_VertBuf *mesh_create_tri_select_id(
int select_id;
GPU_select_index_get(poly_index + select_id_offset, &select_id);
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
}
}
}
@@ -2825,7 +2828,7 @@ static Gwn_VertBuf *mesh_create_tri_select_id(
int select_id;
GPU_select_index_get(poly_index + select_id_offset, &select_id);
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
}
}
}
@@ -2833,29 +2836,29 @@ static Gwn_VertBuf *mesh_create_tri_select_id(
vbo_len_used = cidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
+static GPUVertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->pos_in_order == NULL) {
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
if (format.attr_len == 0) {
/* Normal is padded so that the vbo can be used as a buffer texture */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = cache->pos_in_order = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
@@ -2867,15 +2870,15 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
static short no_short[4];
normal_float_to_short_v3(no_short, eve->no);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
- GWN_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
}
BLI_assert(i == vbo_len_capacity);
}
else {
for (int i = 0; i < vbo_len_capacity; ++i) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
- GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); /* XXX actually reading 4 shorts */
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); /* XXX actually reading 4 shorts */
}
}
}
@@ -2883,26 +2886,26 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
return cache->pos_in_order;
}
-static Gwn_VertFormat *edit_mesh_overlay_pos_format(uint *r_pos_id)
+static GPUVertFormat *edit_mesh_overlay_pos_format(uint *r_pos_id)
{
- static Gwn_VertFormat format_pos = { 0 };
+ static GPUVertFormat format_pos = { 0 };
static uint pos_id;
if (format_pos.attr_len == 0) {
- pos_id = GWN_vertformat_attr_add(&format_pos, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
*r_pos_id = pos_id;
return &format_pos;
}
-static Gwn_VertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lnor_id)
+static GPUVertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lnor_id)
{
- static Gwn_VertFormat format_nor = { 0 };
- static Gwn_VertFormat format_nor_loop = { 0 };
+ static GPUVertFormat format_nor = { 0 };
+ static GPUVertFormat format_nor_loop = { 0 };
static uint vnor_id, vnor_loop_id, lnor_id;
if (format_nor.attr_len == 0) {
- vnor_id = GWN_vertformat_attr_add(&format_nor, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- vnor_loop_id = GWN_vertformat_attr_add(&format_nor_loop, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- lnor_id = GWN_vertformat_attr_add(&format_nor_loop, "lnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ vnor_id = GPU_vertformat_attr_add(&format_nor, "vnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ vnor_loop_id = GPU_vertformat_attr_add(&format_nor_loop, "vnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ lnor_id = GPU_vertformat_attr_add(&format_nor_loop, "lnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
if (r_lnor_id) {
*r_vnor_id = vnor_loop_id;
@@ -2915,12 +2918,12 @@ static Gwn_VertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lno
}
}
-static Gwn_VertFormat *edit_mesh_overlay_data_format(uint *r_data_id)
+static GPUVertFormat *edit_mesh_overlay_data_format(uint *r_data_id)
{
- static Gwn_VertFormat format_flag = { 0 };
+ static GPUVertFormat format_flag = { 0 };
static uint data_id;
if (format_flag.attr_len == 0) {
- data_id = GWN_vertformat_attr_add(&format_flag, "data", GWN_COMP_U8, 4, GWN_FETCH_INT);
+ data_id = GPU_vertformat_attr_add(&format_flag, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
}
*r_data_id = data_id;
return &format_flag;
@@ -2937,28 +2940,28 @@ static void mesh_batch_cache_create_overlay_tri_buffers(
int vbo_len_used = 0;
/* Positions */
- Gwn_VertBuf *vbo_pos = NULL;
+ GPUVertBuf *vbo_pos = NULL;
static struct { uint pos, vnor, lnor, data; } attr_id;
if (cache->ed_tri_pos == NULL) {
vbo_pos = cache->ed_tri_pos =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
}
/* Normals */
- Gwn_VertBuf *vbo_nor = NULL;
+ GPUVertBuf *vbo_nor = NULL;
if (cache->ed_tri_nor == NULL) {
vbo_nor = cache->ed_tri_nor =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor));
- GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor));
+ GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
}
/* Data */
- Gwn_VertBuf *vbo_data = NULL;
+ GPUVertBuf *vbo_data = NULL;
if (cache->ed_tri_data == NULL) {
vbo_data = cache->ed_tri_data =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
}
for (int i = 0; i < tri_len; i++) {
@@ -2976,13 +2979,13 @@ static void mesh_batch_cache_create_overlay_tri_buffers(
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
- GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
- GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
- GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
}
}
}
@@ -2998,28 +3001,28 @@ static void mesh_batch_cache_create_overlay_ledge_buffers(
int vbo_len_used = 0;
/* Positions */
- Gwn_VertBuf *vbo_pos = NULL;
+ GPUVertBuf *vbo_pos = NULL;
static struct { uint pos, vnor, data; } attr_id;
if (cache->ed_ledge_pos == NULL) {
vbo_pos = cache->ed_ledge_pos =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
}
/* Normals */
- Gwn_VertBuf *vbo_nor = NULL;
+ GPUVertBuf *vbo_nor = NULL;
if (cache->ed_ledge_nor == NULL) {
vbo_nor = cache->ed_ledge_nor =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
- GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
+ GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
}
/* Data */
- Gwn_VertBuf *vbo_data = NULL;
+ GPUVertBuf *vbo_data = NULL;
if (cache->ed_ledge_data == NULL) {
vbo_data = cache->ed_ledge_data =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
}
if (rdata->edit_bmesh) {
@@ -3039,13 +3042,13 @@ static void mesh_batch_cache_create_overlay_ledge_buffers(
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
- GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
- GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
- GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
}
}
}
@@ -3064,27 +3067,27 @@ static void mesh_batch_cache_create_overlay_lvert_buffers(
static struct { uint pos, vnor, data; } attr_id;
/* Positions */
- Gwn_VertBuf *vbo_pos = NULL;
+ GPUVertBuf *vbo_pos = NULL;
if (cache->ed_lvert_pos == NULL) {
vbo_pos = cache->ed_lvert_pos =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
}
/* Normals */
- Gwn_VertBuf *vbo_nor = NULL;
+ GPUVertBuf *vbo_nor = NULL;
if (cache->ed_lvert_nor == NULL) {
vbo_nor = cache->ed_lvert_nor =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
- GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
+ GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
}
/* Data */
- Gwn_VertBuf *vbo_data = NULL;
+ GPUVertBuf *vbo_data = NULL;
if (cache->ed_lvert_data == NULL) {
vbo_data = cache->ed_lvert_data =
- GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
}
for (uint i = 0; i < lvert_len; i++) {
@@ -3099,19 +3102,19 @@ static void mesh_batch_cache_create_overlay_lvert_buffers(
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
- GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
- GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
- GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
}
}
}
/* Position */
-static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_pos(
+static GPUVertBuf *mesh_batch_cache_get_edit_tri_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3123,7 +3126,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_pos(
return cache->ed_tri_pos;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_pos(
+static GPUVertBuf *mesh_batch_cache_get_edit_ledge_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3135,7 +3138,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_pos(
return cache->ed_ledge_pos;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_pos(
+static GPUVertBuf *mesh_batch_cache_get_edit_lvert_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3148,7 +3151,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_pos(
}
/* Normal */
-static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_nor(
+static GPUVertBuf *mesh_batch_cache_get_edit_tri_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3160,7 +3163,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_nor(
return cache->ed_tri_nor;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_nor(
+static GPUVertBuf *mesh_batch_cache_get_edit_ledge_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3172,7 +3175,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_nor(
return cache->ed_ledge_nor;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_nor(
+static GPUVertBuf *mesh_batch_cache_get_edit_lvert_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3185,7 +3188,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_nor(
}
/* Data */
-static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_data(
+static GPUVertBuf *mesh_batch_cache_get_edit_tri_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3197,7 +3200,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_data(
return cache->ed_tri_data;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_data(
+static GPUVertBuf *mesh_batch_cache_get_edit_ledge_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3209,7 +3212,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_data(
return cache->ed_ledge_data;
}
-static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_data(
+static GPUVertBuf *mesh_batch_cache_get_edit_lvert_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -3221,7 +3224,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_data(
return cache->ed_lvert_data;
}
-static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUIndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
@@ -3229,8 +3232,8 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata,
const int vert_len = mesh_render_data_verts_len_get(rdata);
const int edge_len = mesh_render_data_edges_len_get(rdata);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
BLI_assert(rdata->types & MR_DATATYPE_EDGE);
@@ -3240,24 +3243,24 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata,
BMEdge *eed;
BM_ITER_MESH(eed, &eiter, bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
+ GPU_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
}
}
}
else {
const MEdge *ed = rdata->medge;
for (int i = 0; i < edge_len; i++, ed++) {
- GWN_indexbuf_add_line_verts(&elb, ed->v1, ed->v2);
+ GPU_indexbuf_add_line_verts(&elb, ed->v1, ed->v2);
}
}
- cache->edges_in_order = GWN_indexbuf_build(&elb);
+ cache->edges_in_order = GPU_indexbuf_build(&elb);
}
return cache->edges_in_order;
}
#define NO_EDGE INT_MAX
-static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUIndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
@@ -3268,8 +3271,8 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
cache->is_manifold = true;
/* Allocate max but only used indices are sent to GPU. */
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, tri_len * 3, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, tri_len * 3, vert_len);
EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3);
/* Create edges for each pair of triangles sharing an edge. */
@@ -3310,12 +3313,12 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
if (inv_opposite == inv_indices) {
/* Don't share edge if triangles have non matching winding. */
- GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
- GWN_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite);
+ GPU_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
+ GPU_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite);
cache->is_manifold = false;
}
else {
- GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite);
+ GPU_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite);
}
}
}
@@ -3336,13 +3339,13 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
if (v_data < 0) { /* inv_opposite */
SWAP(uint, v1, v2);
}
- GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
+ GPU_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
cache->is_manifold = false;
}
BLI_edgehashIterator_free(ehi);
BLI_edgehash_free(eh, NULL);
- cache->edges_adjacency = GWN_indexbuf_build(&elb);
+ cache->edges_adjacency = GPU_indexbuf_build(&elb);
}
return cache->edges_adjacency;
@@ -3395,16 +3398,16 @@ static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
return eh;
}
-static Gwn_VertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderData *rdata)
+static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderData *rdata)
{
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_VertFormat format = {0};
- uint index_id = GWN_vertformat_attr_add(&format, "index", GWN_COMP_U32, 1, GWN_FETCH_INT);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertFormat format = {0};
+ uint index_id = GPU_vertformat_attr_add(&format, "index", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
int vbo_len_capacity = tri_len * 3;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
int vidx = 0;
EdgeHash *eh = NULL;
@@ -3442,7 +3445,7 @@ static Gwn_VertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRender
if (eav->vert_index[1] == -1) {
value |= (1 << 31);
}
- GWN_vertbuf_attr_set(vbo, index_id, vidx++, &value);
+ GPU_vertbuf_attr_set(vbo, index_id, vidx++, &value);
}
}
@@ -3451,7 +3454,7 @@ static Gwn_VertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRender
int vbo_len_used = vidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
return vbo;
@@ -3467,10 +3470,10 @@ static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData
return cache->edges_face_overlay_tx;
}
- Gwn_VertBuf *vbo = cache->edges_face_overlay = mesh_batch_cache_create_edges_overlay_texture_buf(rdata);
+ GPUVertBuf *vbo = cache->edges_face_overlay = mesh_batch_cache_create_edges_overlay_texture_buf(rdata);
/* Upload data early because we need to create the texture for it. */
- GWN_vertbuf_use(vbo);
+ GPU_vertbuf_use(vbo);
cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo);
cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 3;
@@ -3482,15 +3485,15 @@ static GPUTexture *mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(MeshRender
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
if (cache->pos_in_order_tx == NULL) {
- Gwn_VertBuf *pos_in_order = mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache);
- GWN_vertbuf_use(pos_in_order); /* Upload early for buffer texture creation. */
+ GPUVertBuf *pos_in_order = mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache);
+ GPU_vertbuf_use(pos_in_order); /* Upload early for buffer texture creation. */
cache->pos_in_order_tx = GPU_texture_create_buffer(GPU_R32F, pos_in_order->vbo_id);
}
return cache->pos_in_order_tx;
}
-static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUIndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
@@ -3498,15 +3501,15 @@ static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rda
const int vert_len = mesh_render_data_verts_len_get(rdata);
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
if (rdata->edit_bmesh) {
for (int i = 0; i < tri_len; ++i) {
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
+ GPU_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
}
}
}
@@ -3515,18 +3518,18 @@ static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rda
for (int i = 0; i < tri_len; ++i) {
const MLoopTri *mlt = &rdata->mlooptri[i];
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GWN_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
+ GPU_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
}
}
}
- cache->triangles_in_order = GWN_indexbuf_build(&elb);
+ cache->triangles_in_order = GPU_indexbuf_build(&elb);
}
return cache->triangles_in_order;
}
-static Gwn_IndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUIndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
@@ -3535,8 +3538,8 @@ static Gwn_IndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, Mes
const int edge_len = mesh_render_data_edges_len_get(rdata);
/* Alloc max (edge_len) and upload only needed range. */
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
if (rdata->edit_bmesh) {
/* No need to support since edit mesh already draw them.
@@ -3546,7 +3549,7 @@ static Gwn_IndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, Mes
BMEdge *eed;
BM_ITER_MESH(eed, &eiter, bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_edge_is_wire(eed)) {
- GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
+ GPU_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
}
}
}
@@ -3554,17 +3557,17 @@ static Gwn_IndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, Mes
for (int i = 0; i < edge_len; ++i) {
const MEdge *medge = &rdata->medge[i];
if (medge->flag & ME_LOOSEEDGE) {
- GWN_indexbuf_add_line_verts(&elb, medge->v1, medge->v2);
+ GPU_indexbuf_add_line_verts(&elb, medge->v1, medge->v2);
}
}
}
- cache->ledges_in_order = GWN_indexbuf_build(&elb);
+ cache->ledges_in_order = GPU_indexbuf_build(&elb);
}
return cache->ledges_in_order;
}
-static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
+static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY));
@@ -3576,7 +3579,7 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__);
cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
- Gwn_IndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
+ GPUIndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
/* Note that polygons (not triangles) are used here.
* This OK because result is _guaranteed_ to be the same. */
@@ -3602,7 +3605,7 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
/* Init ELBs. */
for (int i = 0; i < mat_len; ++i) {
- GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
+ GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
}
/* Populate ELBs. */
@@ -3616,7 +3619,7 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
for (int j = 2; j < efa->len; j++) {
- GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
+ GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
nidx += 3;
}
}
@@ -3627,7 +3630,7 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
const MPoly *mp = &rdata->mpoly[i]; ;
const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
for (int j = 2; j < mp->totloop; j++) {
- GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
+ GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
nidx += 3;
}
}
@@ -3635,7 +3638,7 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
/* Build ELBs. */
for (int i = 0; i < mat_len; ++i) {
- cache->shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
+ cache->shaded_triangles_in_order[i] = GPU_indexbuf_build(&elb[i]);
}
MEM_freeN(mat_tri_len);
@@ -3645,30 +3648,30 @@ static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
return cache->shaded_triangles_in_order;
}
-static Gwn_VertBuf *mesh_create_edge_pos_with_sel(
+static GPUVertBuf *mesh_create_edge_pos_with_sel(
MeshRenderData *rdata, bool use_wire, bool use_select_bool)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP));
BLI_assert(rdata->edit_bmesh == NULL);
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
uint vidx = 0, cidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, sel; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.sel = GWN_vertformat_attr_add(&format, "select", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.sel = GPU_vertformat_attr_add(&format, "select", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
const int edge_len = mesh_render_data_edges_len_get(rdata);
- vbo = GWN_vertbuf_create_with_format(&format);
+ vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = edge_len * 2;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
if (use_select_bool) {
mesh_render_data_ensure_edge_select_bool(rdata, use_wire);
@@ -3689,23 +3692,23 @@ static Gwn_VertBuf *mesh_create_edge_pos_with_sel(
continue;
}
- GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
- GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
+ GPU_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
+ GPU_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co);
}
vbo_len_used = vidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
}
-static Gwn_IndexBuf *mesh_create_tri_overlay_weight_faces(
+static GPUIndexBuf *mesh_create_tri_overlay_weight_faces(
MeshRenderData *rdata)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
@@ -3714,57 +3717,57 @@ static Gwn_IndexBuf *mesh_create_tri_overlay_weight_faces(
const int vert_len = mesh_render_data_verts_len_get(rdata);
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
for (int i = 0; i < tri_len; ++i) {
const MLoopTri *mlt = &rdata->mlooptri[i];
if (!(rdata->mpoly[mlt->poly].flag & (ME_FACE_SEL | ME_HIDE))) {
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GWN_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v);
+ GPU_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v);
}
}
}
- return GWN_indexbuf_build(&elb);
+ return GPU_indexbuf_build(&elb);
}
}
/**
* Non-edit mode vertices (only used for weight-paint mode).
*/
-static Gwn_VertBuf *mesh_create_vert_pos_with_overlay_data(
+static GPUVertBuf *mesh_create_vert_pos_with_overlay_data(
MeshRenderData *rdata)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT));
BLI_assert(rdata->edit_bmesh == NULL);
- Gwn_VertBuf *vbo;
+ GPUVertBuf *vbo;
{
uint cidx = 0;
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint data; } attr_id;
if (format.attr_len == 0) {
- attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_I8, 1, GWN_FETCH_INT);
+ attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_I8, 1, GPU_FETCH_INT);
}
const int vert_len = mesh_render_data_verts_len_get(rdata);
- vbo = GWN_vertbuf_create_with_format(&format);
+ vbo = GPU_vertbuf_create_with_format(&format);
const int vbo_len_capacity = vert_len;
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
for (int i = 0; i < vert_len; i++) {
const MVert *mv = &rdata->mvert[i];
const char data = mv->flag & (SELECT | ME_HIDE);
- GWN_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data);
+ GPU_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data);
}
vbo_len_used = cidx;
if (vbo_len_capacity != vbo_len_used) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
}
return vbo;
@@ -3778,7 +3781,7 @@ static Gwn_VertBuf *mesh_create_vert_pos_with_overlay_data(
/** \name Public API
* \{ */
-Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3787,8 +3790,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->all_edges = GWN_batch_create(
- GWN_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ cache->all_edges = GPU_batch_create(
+ GPU_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
mesh_batch_cache_get_edges_in_order(rdata, cache));
mesh_render_data_free(rdata);
@@ -3797,7 +3800,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
return cache->all_edges;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3806,8 +3809,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->all_triangles = GWN_batch_create(
- GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ cache->all_triangles = GPU_batch_create(
+ GPU_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
mesh_batch_cache_get_triangles_in_order(rdata, cache));
mesh_render_data_free(rdata);
@@ -3816,7 +3819,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
return cache->all_triangles;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3824,8 +3827,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->triangles_with_normals = GWN_batch_create(
- GWN_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
+ cache->triangles_with_normals = GPU_batch_create(
+ GPU_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
mesh_render_data_free(rdata);
}
@@ -3833,7 +3836,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
return cache->triangles_with_normals;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3841,8 +3844,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->ledges_with_normals = GWN_batch_create(
- GWN_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ cache->ledges_with_normals = GPU_batch_create(
+ GPU_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
mesh_batch_cache_get_loose_edges(rdata, cache));
mesh_render_data_free(rdata);
@@ -3851,7 +3854,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
return cache->ledges_with_normals;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int defgroup)
+GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int defgroup)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3861,14 +3864,14 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me,
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->triangles_with_weights = GWN_batch_create_ex(
- GWN_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, defgroup), NULL, GWN_BATCH_OWNS_VBO);
+ cache->triangles_with_weights = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, defgroup), NULL, GPU_BATCH_OWNS_VBO);
- Gwn_VertBuf *vbo_tris = use_hide ?
+ GPUVertBuf *vbo_tris = use_hide ?
mesh_create_tri_pos_and_normals_visible_only(rdata) :
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GWN_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide);
+ GPU_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide);
mesh_render_data_free(rdata);
}
@@ -3876,7 +3879,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me,
return cache->triangles_with_weights;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3886,13 +3889,13 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->triangles_with_vert_colors = GWN_batch_create_ex(
- GWN_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GWN_BATCH_OWNS_VBO);
+ cache->triangles_with_vert_colors = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GPU_BATCH_OWNS_VBO);
- Gwn_VertBuf *vbo_tris = use_hide ?
+ GPUVertBuf *vbo_tris = use_hide ?
mesh_create_tri_pos_and_normals_visible_only(rdata) :
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GWN_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide);
+ GPU_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide);
mesh_render_data_free(rdata);
}
@@ -3901,14 +3904,14 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh
}
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(
struct Mesh *me, bool use_hide, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->triangles_with_select_id_offset != select_id_offset) {
cache->triangles_with_select_id_offset = select_id_offset;
- GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
}
if (cache->triangles_with_select_id == NULL) {
@@ -3916,13 +3919,13 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->triangles_with_select_id = GWN_batch_create_ex(
- GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GWN_BATCH_OWNS_VBO);
+ cache->triangles_with_select_id = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GPU_BATCH_OWNS_VBO);
- Gwn_VertBuf *vbo_tris = use_hide ?
+ GPUVertBuf *vbo_tris = use_hide ?
mesh_create_tri_pos_and_normals_visible_only(rdata) :
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GWN_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide);
+ GPU_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide);
mesh_render_data_free(rdata);
}
@@ -3934,7 +3937,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(
* Same as #DRW_mesh_batch_cache_get_triangles_with_select_id
* without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces.
*/
-struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide)
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->triangles_with_select_mask == NULL) {
@@ -3942,12 +3945,12 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mes
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- Gwn_VertBuf *vbo_tris = use_hide ?
+ GPUVertBuf *vbo_tris = use_hide ?
mesh_create_tri_pos_and_normals_visible_only(rdata) :
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- cache->triangles_with_select_mask = GWN_batch_create_ex(
- GWN_PRIM_TRIS, vbo_tris, NULL, use_hide ? GWN_BATCH_OWNS_VBO : 0);
+ cache->triangles_with_select_mask = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, vbo_tris, NULL, use_hide ? GPU_BATCH_OWNS_VBO : 0);
mesh_render_data_free(rdata);
}
@@ -3955,7 +3958,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mes
return cache->triangles_with_select_mask;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3963,8 +3966,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->points_with_normals = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
+ cache->points_with_normals = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
mesh_render_data_free(rdata);
}
@@ -3972,7 +3975,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
return cache->points_with_normals;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3980,8 +3983,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
/* create batch from DM */
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
- cache->all_verts = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
+ cache->all_verts = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
mesh_render_data_free(rdata);
}
@@ -3989,21 +3992,21 @@ Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
return cache->all_verts;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->fancy_edges == NULL) {
/* create batch from DM */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static struct { uint pos, n1, n2; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.n1 = GPU_vertformat_attr_add(&format, "N1", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.n2 = GPU_vertformat_attr_add(&format, "N2", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
MeshRenderData *rdata = mesh_render_data_create(
me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
@@ -4012,7 +4015,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
const int vbo_len_capacity = edge_len * 2; /* these are PRIM_LINE verts, not mesh verts */
int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
for (int i = 0; i < edge_len; ++i) {
float *vcos1, *vcos2;
float *pnor1 = NULL, *pnor2 = NULL;
@@ -4020,33 +4023,33 @@ Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
if (mesh_render_data_edge_vcos_manifold_pnors(rdata, i, &vcos1, &vcos2, &pnor1, &pnor2, &is_manifold)) {
- Gwn_PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
- Gwn_PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
+ GPUPackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
+ GPUPackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
if (is_manifold) {
- n1value = GWN_normal_convert_i10_v3(pnor1);
- n2value = GWN_normal_convert_i10_v3(pnor2);
+ n1value = GPU_normal_convert_i10_v3(pnor1);
+ n2value = GPU_normal_convert_i10_v3(pnor2);
}
- const Gwn_PackedNormal *n1 = &n1value;
- const Gwn_PackedNormal *n2 = &n2value;
+ const GPUPackedNormal *n1 = &n1value;
+ const GPUPackedNormal *n2 = &n2value;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i, vcos1);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i, n1);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i, n2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * i, vcos1);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, 2 * i, n1);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, 2 * i, n2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i + 1, vcos2);
- GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i + 1, n1);
- GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i + 1, n2);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * i + 1, vcos2);
+ GPU_vertbuf_attr_set(vbo, attr_id.n1, 2 * i + 1, n1);
+ GPU_vertbuf_attr_set(vbo, attr_id.n2, 2 * i + 1, n2);
vbo_len_used += 2;
}
}
if (vbo_len_used != vbo_len_capacity) {
- GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
- cache->fancy_edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ cache->fancy_edges = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
mesh_render_data_free(rdata);
}
@@ -4054,7 +4057,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
return cache->fancy_edges;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
+GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4063,8 +4066,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold
MeshRenderData *rdata = mesh_render_data_create(me, options);
- cache->edge_detection = GWN_batch_create_ex(
- GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ cache->edge_detection = GPU_batch_create_ex(
+ GPU_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
mesh_batch_cache_get_edges_adjacency(rdata, cache), 0);
mesh_render_data_free(rdata);
@@ -4111,42 +4114,42 @@ static void mesh_batch_cache_create_overlay_batches(Mesh *me)
MeshRenderData *rdata = mesh_render_data_create(me, options);
if (cache->overlay_triangles == NULL) {
- cache->overlay_triangles = GWN_batch_create(
- GWN_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
- GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
- GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
+ cache->overlay_triangles = GPU_batch_create(
+ GPU_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
+ GPU_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
+ GPU_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
}
if (cache->overlay_loose_edges == NULL) {
- cache->overlay_loose_edges = GWN_batch_create(
- GWN_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
- GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
- GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
+ cache->overlay_loose_edges = GPU_batch_create(
+ GPU_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
+ GPU_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
+ GPU_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
}
if (cache->overlay_loose_verts == NULL) {
- cache->overlay_loose_verts = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
- GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
- GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
+ cache->overlay_loose_verts = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
+ GPU_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
+ GPU_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
}
if (cache->overlay_triangles_nor == NULL) {
- cache->overlay_triangles_nor = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
- GWN_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
+ cache->overlay_triangles_nor = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
+ GPU_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
}
if (cache->overlay_loose_edges_nor == NULL) {
- cache->overlay_loose_edges_nor = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
- GWN_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
+ cache->overlay_loose_edges_nor = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
+ GPU_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
}
mesh_render_data_free(rdata);
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4157,7 +4160,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
return cache->overlay_triangles;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4168,7 +4171,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
return cache->overlay_loose_edges;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4179,7 +4182,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
return cache->overlay_loose_verts;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4190,7 +4193,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
return cache->overlay_triangles_nor;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4201,15 +4204,15 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
return cache->overlay_loose_edges_nor;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->overlay_facedots == NULL) {
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
- cache->overlay_facedots = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
+ cache->overlay_facedots = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
mesh_render_data_free(rdata);
}
@@ -4217,13 +4220,13 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
return cache->overlay_facedots;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
+GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->facedot_with_select_id_offset != select_id_offset) {
cache->facedot_with_select_id_offset = select_id_offset;
- GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
}
if (cache->facedot_with_select_id == NULL) {
@@ -4231,10 +4234,10 @@ Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint selec
/* We only want the 'pos', not the normals or flag.
* Use since this is almost certainly already created. */
- cache->facedot_with_select_id = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
+ cache->facedot_with_select_id = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
- GWN_batch_vertbuf_add_ex(
+ GPU_batch_vertbuf_add_ex(
cache->facedot_with_select_id,
mesh_create_facedot_select_id(rdata, select_id_offset), true);
@@ -4244,22 +4247,22 @@ Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint selec
return cache->facedot_with_select_id;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset)
+GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->edges_with_select_id_offset != select_id_offset) {
cache->edges_with_select_id_offset = select_id_offset;
- GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
}
if (cache->edges_with_select_id == NULL) {
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
- cache->edges_with_select_id = GWN_batch_create(
- GWN_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL);
+ cache->edges_with_select_id = GPU_batch_create(
+ GPU_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL);
- GWN_batch_vertbuf_add_ex(
+ GPU_batch_vertbuf_add_ex(
cache->edges_with_select_id,
mesh_create_edges_select_id(rdata, select_id_offset), true);
@@ -4269,22 +4272,22 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_i
return cache->edges_with_select_id;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset)
+GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->verts_with_select_id_offset != select_id_offset) {
cache->verts_with_select_id_offset = select_id_offset;
- GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
}
if (cache->verts_with_select_id == NULL) {
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
- cache->verts_with_select_id = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL);
+ cache->verts_with_select_id = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL);
- GWN_batch_vertbuf_add_ex(
+ GPU_batch_vertbuf_add_ex(
cache->verts_with_select_id,
mesh_create_verts_select_id(rdata, select_id_offset), true);
@@ -4294,7 +4297,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_i
return cache->verts_with_select_id;
}
-Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
@@ -4311,16 +4314,16 @@ Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
- Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
+ GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
- Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- Gwn_VertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
+ GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GPUVertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
for (int i = 0; i < mat_len; ++i) {
- cache->shaded_triangles[i] = GWN_batch_create(
- GWN_PRIM_TRIS, vbo, el[i]);
+ cache->shaded_triangles[i] = GPU_batch_create(
+ GPU_PRIM_TRIS, vbo, el[i]);
if (vbo_shading) {
- GWN_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
+ GPU_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
}
}
@@ -4336,7 +4339,7 @@ Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
return cache->shaded_triangles;
}
-Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
+GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4350,15 +4353,15 @@ Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__);
- Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
+ GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
- Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
for (int i = 0; i < mat_len; ++i) {
- cache->texpaint_triangles[i] = GWN_batch_create(
- GWN_PRIM_TRIS, vbo, el[i]);
- Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
+ cache->texpaint_triangles[i] = GPU_batch_create(
+ GPU_PRIM_TRIS, vbo, el[i]);
+ GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
if (vbo_uv) {
- GWN_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
+ GPU_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
}
}
mesh_render_data_free(rdata);
@@ -4367,7 +4370,7 @@ Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
return cache->texpaint_triangles;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4377,20 +4380,20 @@ Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- cache->texpaint_triangles_single = GWN_batch_create(
- GWN_PRIM_TRIS, vbo, NULL);
- Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
+ cache->texpaint_triangles_single = GPU_batch_create(
+ GPU_PRIM_TRIS, vbo, NULL);
+ GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
if (vbo_uv) {
- GWN_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
+ GPU_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
}
mesh_render_data_free(rdata);
}
return cache->texpaint_triangles_single;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel)
+GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4399,8 +4402,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->overlay_paint_edges = GWN_batch_create_ex(
- GWN_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GWN_BATCH_OWNS_VBO);
+ cache->overlay_paint_edges = GPU_batch_create_ex(
+ GPU_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GPU_BATCH_OWNS_VBO);
mesh_render_data_free(rdata);
}
@@ -4408,7 +4411,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire
return cache->overlay_paint_edges;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4417,9 +4420,9 @@ Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
- cache->overlay_weight_faces = GWN_batch_create_ex(
- GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
- mesh_create_tri_overlay_weight_faces(rdata), GWN_BATCH_OWNS_INDEX);
+ cache->overlay_weight_faces = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ mesh_create_tri_overlay_weight_faces(rdata), GPU_BATCH_OWNS_INDEX);
mesh_render_data_free(rdata);
}
@@ -4427,7 +4430,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
return cache->overlay_weight_faces;
}
-Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4435,10 +4438,10 @@ Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
/* create batch from Mesh */
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
- cache->overlay_weight_verts = GWN_batch_create(
- GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
+ cache->overlay_weight_verts = GPU_batch_create(
+ GPU_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
- GWN_batch_vertbuf_add_ex(
+ GPU_batch_vertbuf_add_ex(
cache->overlay_weight_verts,
mesh_create_vert_pos_with_overlay_data(rdata), true);
mesh_render_data_free(rdata);
@@ -4458,7 +4461,7 @@ void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
/* XXX Force update of all the batches that contains the pos_with_normals buffer.
* TODO(fclem): Ideally, Gawain should provide a way to update a buffer without destroying it. */
mesh_batch_cache_clear_selective(me, cache->pos_with_normals);
- GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
}
cache->is_sculpt_points_tag = false;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index 24930921bee..2172997a714 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -45,18 +45,18 @@
static void metaball_batch_cache_clear(MetaBall *mb);
/* ---------------------------------------------------------------------- */
-/* MetaBall Gwn_Batch Cache */
+/* MetaBall GPUBatch Cache */
typedef struct MetaBallBatchCache {
- Gwn_Batch *batch;
- Gwn_Batch **shaded_triangles;
+ GPUBatch *batch;
+ GPUBatch **shaded_triangles;
int mat_len;
/* settings to determine if cache is invalid */
bool is_dirty;
} MetaBallBatchCache;
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
static bool metaball_batch_cache_valid(MetaBall *mb)
{
@@ -113,7 +113,7 @@ static void metaball_batch_cache_clear(MetaBall *mb)
return;
}
- GWN_BATCH_DISCARD_SAFE(cache->batch);
+ GPU_BATCH_DISCARD_SAFE(cache->batch);
/* Note: shaded_triangles[0] is already freed by cache->batch */
MEM_SAFE_FREE(cache->shaded_triangles);
cache->mat_len = 0;
@@ -130,7 +130,7 @@ void DRW_mball_batch_cache_free(MetaBall *mb)
/** \name Public Object/MetaBall API
* \{ */
-Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
+GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
{
if (!BKE_mball_is_basis(ob)) {
return NULL;
@@ -140,18 +140,18 @@ Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
if (cache->batch == NULL) {
- ListBase *lb = &ob->curve_cache->disp;
- cache->batch = GWN_batch_create_ex(
- GWN_PRIM_TRIS,
+ ListBase *lb = &ob->runtime.curve_cache->disp;
+ cache->batch = GPU_batch_create_ex(
+ GPU_PRIM_TRIS,
DRW_displist_vertbuf_calc_pos_with_normals(lb),
DRW_displist_indexbuf_calc_triangles_in_order(lb),
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
return cache->batch;
}
-Gwn_Batch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
+GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
{
if (!BKE_mball_is_basis(ob)) {
return NULL;
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index da360f89051..d3dacc8e537 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -61,11 +61,11 @@
static void particle_batch_cache_clear(ParticleSystem *psys);
/* ---------------------------------------------------------------------- */
-/* Particle Gwn_Batch Cache */
+/* Particle GPUBatch Cache */
typedef struct ParticlePointCache {
- Gwn_VertBuf *pos;
- Gwn_Batch *points;
+ GPUVertBuf *pos;
+ GPUBatch *points;
int elems_len;
int point_len;
} ParticlePointCache;
@@ -80,19 +80,19 @@ typedef struct ParticleBatchCache {
/* Control points when in edit mode. */
ParticleHairCache edit_hair;
- Gwn_VertBuf *edit_inner_pos;
- Gwn_Batch *edit_inner_points;
+ GPUVertBuf *edit_inner_pos;
+ GPUBatch *edit_inner_points;
int edit_inner_point_len;
- Gwn_VertBuf *edit_tip_pos;
- Gwn_Batch *edit_tip_points;
+ GPUVertBuf *edit_tip_pos;
+ GPUBatch *edit_tip_points;
int edit_tip_point_len;
/* Settings to determine if cache is invalid. */
bool is_dirty;
} ParticleBatchCache;
-/* Gwn_Batch cache management. */
+/* GPUBatch cache management. */
typedef struct HairAttributeID {
uint pos;
@@ -158,8 +158,8 @@ void DRW_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
{
- GWN_BATCH_DISCARD_SAFE(point_cache->points);
- GWN_VERTBUF_DISCARD_SAFE(point_cache->pos);
+ GPU_BATCH_DISCARD_SAFE(point_cache->points);
+ GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
}
static void particle_batch_cache_clear(ParticleSystem *psys)
@@ -174,10 +174,10 @@ static void particle_batch_cache_clear(ParticleSystem *psys)
particle_batch_cache_clear_hair(&cache->edit_hair);
- GWN_BATCH_DISCARD_SAFE(cache->edit_inner_points);
- GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
- GWN_BATCH_DISCARD_SAFE(cache->edit_tip_points);
- GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_inner_points);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_tip_points);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
}
void DRW_particle_batch_cache_free(ParticleSystem *psys)
@@ -483,7 +483,7 @@ static int particle_batch_cache_fill_segments(
uint *col_id,
float (***r_parent_uvs)[2],
MCol ***r_parent_mcol,
- Gwn_IndexBufBuilder *elb,
+ GPUIndexBufBuilder *elb,
HairAttributeID *attr_id,
ParticleHairCache *hair_cache)
{
@@ -530,12 +530,12 @@ static int particle_batch_cache_fill_segments(
else {
sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
}
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co);
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i);
if (psmd != NULL) {
for (int k = 0; k < num_uv_layers; k++) {
- GWN_vertbuf_attr_set(
+ GPU_vertbuf_attr_set(
hair_cache->pos, uv_id[k], curr_point,
(is_simple && is_child) ?
(*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
@@ -547,22 +547,22 @@ static int particle_batch_cache_fill_segments(
(is_simple && is_child) ?
&(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
scol);
- GWN_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
+ GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
}
}
- GWN_indexbuf_add_generic_vert(elb, curr_point);
+ GPU_indexbuf_add_generic_vert(elb, curr_point);
curr_point++;
}
sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
int global_index = i + global_offset;
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co);
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
- GWN_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
+ GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index);
if (psmd != NULL) {
for (int k = 0; k < num_uv_layers; k++) {
- GWN_vertbuf_attr_set(
+ GPU_vertbuf_attr_set(
hair_cache->pos, uv_id[k], curr_point,
(is_simple && is_child) ?
(*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
@@ -574,7 +574,7 @@ static int particle_batch_cache_fill_segments(
(is_simple && is_child) ?
&(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
scol);
- GWN_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
+ GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
}
if (!is_simple) {
MEM_freeN(uv);
@@ -582,8 +582,8 @@ static int particle_batch_cache_fill_segments(
}
}
/* Finish the segment and add restart primitive. */
- GWN_indexbuf_add_generic_vert(elb, curr_point);
- GWN_indexbuf_add_primitive_restart(elb);
+ GPU_indexbuf_add_generic_vert(elb, curr_point);
+ GPU_indexbuf_add_primitive_restart(elb);
curr_point++;
}
return curr_point;
@@ -592,7 +592,7 @@ static int particle_batch_cache_fill_segments(
static void particle_batch_cache_fill_segments_proc_pos(
ParticleCacheKey **path_cache,
const int num_path_keys,
- Gwn_VertBufRaw *attr_step)
+ GPUVertBufRaw *attr_step)
{
for (int i = 0; i < num_path_keys; i++) {
ParticleCacheKey *path = path_cache[i];
@@ -602,7 +602,7 @@ static void particle_batch_cache_fill_segments_proc_pos(
float total_len = 0.0f;
float *co_prev = NULL, *seg_data_first;
for (int j = 0; j <= path->segments; j++) {
- float *seg_data = (float *)GWN_vertbuf_raw_step(attr_step);
+ float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
copy_v3_v3(seg_data, path[j].co);
if (co_prev) {
total_len += len_v3v3(co_prev, path[j].co);
@@ -629,7 +629,7 @@ static int particle_batch_cache_fill_segments_indices(
const int num_path_keys,
const int subdiv,
const int thickness_res,
- Gwn_IndexBufBuilder *elb)
+ GPUIndexBufBuilder *elb)
{
const ParticleSettings *part = psys->part;
const int points_per_curve = (1 << (part->draw_step + subdiv)) + 1;
@@ -643,9 +643,9 @@ static int particle_batch_cache_fill_segments_indices(
}
for (int k = 0; k < points_per_hair; k++) {
- GWN_indexbuf_add_generic_vert(elb, curr_point++);
+ GPU_indexbuf_add_generic_vert(elb, curr_point++);
}
- GWN_indexbuf_add_primitive_restart(elb);
+ GPU_indexbuf_add_primitive_restart(elb);
}
return curr_point;
}
@@ -657,9 +657,9 @@ static int particle_batch_cache_fill_strands_data(
const ParticleSource particle_source,
const int start_index,
const int num_path_keys,
- Gwn_VertBufRaw *data_step,
- float (***r_parent_uvs)[2], Gwn_VertBufRaw *uv_step, MTFace **mtfaces, int num_uv_layers,
- MCol ***r_parent_mcol, Gwn_VertBufRaw *col_step, MCol **mcols, int num_col_layers)
+ GPUVertBufRaw *data_step,
+ float (***r_parent_uvs)[2], GPUVertBufRaw *uv_step, MTFace **mtfaces, int num_uv_layers,
+ MCol ***r_parent_mcol, GPUVertBufRaw *col_step, MCol **mcols, int num_col_layers)
{
const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES);
const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN);
@@ -681,7 +681,7 @@ static int particle_batch_cache_fill_strands_data(
continue;
}
- uint *seg_data = (uint *)GWN_vertbuf_raw_step(data_step);
+ uint *seg_data = (uint *)GPU_vertbuf_raw_step(data_step);
*seg_data = (curr_point & 0xFFFFFF) | (path->segments << 24);
curr_point += path->segments + 1;
@@ -706,11 +706,11 @@ static int particle_batch_cache_fill_strands_data(
*r_parent_mcol, &mcol);
for (int k = 0; k < num_uv_layers; k++) {
- float *t_uv = (float *)GWN_vertbuf_raw_step(uv_step + k);
+ float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k);
copy_v2_v2(t_uv, uv[k]);
}
for (int k = 0; k < num_col_layers; k++) {
- ushort *scol = (ushort *)GWN_vertbuf_raw_step(col_step + k);
+ ushort *scol = (ushort *)GPU_vertbuf_raw_step(col_step + k);
particle_pack_mcol(
(is_simple && is_child) ?
&(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
@@ -753,34 +753,34 @@ static void particle_batch_cache_ensure_procedural_final_points(
/* Same format as point_tex. */
#ifdef USE_POSITION_HAIR_INDEX
- static Gwn_VertFormat format = { 0 };
- GWN_vertformat_clear(&format);
- uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ static GPUVertFormat format = { 0 };
+ GPU_vertformat_clear(&format);
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
#else
- Gwn_VertFormat format = { 0 };
- GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ static GPUVer format = { 0 };
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
#endif
- cache->final[subdiv].proc_point_buf = GWN_vertbuf_create_with_format(&format);
+ cache->final[subdiv].proc_point_buf = GPU_vertbuf_create_with_format(&format);
/* Create a destination buffer for the tranform feedback. Sized appropriately */
/* Thoses are points! not line segments. */
- GWN_vertbuf_data_alloc(cache->final[subdiv].proc_point_buf, cache->final[subdiv].point_len);
+ GPU_vertbuf_data_alloc(cache->final[subdiv].proc_point_buf, cache->final[subdiv].point_len);
#ifdef USE_POSITION_HAIR_INDEX
- Gwn_VertBufRaw data_step;
- GWN_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_point_buf, pos_id, &data_step);
+ GPUVertBufRaw data_step;
+ GPU_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_point_buf, pos_id, &data_step);
const int points_per_curve = (1 << (psys->part->draw_step + subdiv)) + 1;
for (int i = 0; i < cache->final[subdiv].strands_len; i++) {
for (int j = 0; j < points_per_curve; ++j) {
- uint *data = (uint *)GWN_vertbuf_raw_step(&data_step);
+ uint *data = (uint *)GPU_vertbuf_raw_step(&data_step);
*data = (uint)i;
}
}
#endif
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->final[subdiv].proc_point_buf);
+ GPU_vertbuf_use(cache->final[subdiv].proc_point_buf);
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_point_buf);
}
@@ -791,25 +791,25 @@ static void particle_batch_cache_ensure_procedural_final_hair_index(
int subdiv)
{
/* Same format as point_tex. */
- Gwn_VertFormat format = { 0 };
- uint hair_index_id = GWN_vertformat_attr_add(&format, "hair_index", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat format = { 0 };
+ uint hair_index_id = GPU_vertformat_attr_add(&format, "hair_index", GPU_COMP_U32, 1, GPU_FETCH_INT);
- cache->final[subdiv].proc_hair_index_buf = GWN_vertbuf_create_with_format(&format);
+ cache->final[subdiv].proc_hair_index_buf = GPU_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->final[subdiv].proc_hair_index_buf, cache->final[subdiv].point_len);
+ GPU_vertbuf_data_alloc(cache->final[subdiv].proc_hair_index_buf, cache->final[subdiv].point_len);
- Gwn_VertBufRaw data_step;
- GWN_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_hair_index_buf, hair_index_id, &data_step);
+ GPUVertBufRaw data_step;
+ GPU_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_hair_index_buf, hair_index_id, &data_step);
const int points_per_curve = (1 << (psys->part->draw_step + subdiv)) + 1;
for (int i = 0; i < cache->final[subdiv].strands_len; i++) {
for (int j = 0; j < points_per_curve; ++j) {
- uint *data = (uint *)GWN_vertbuf_raw_step(&data_step);
+ uint *data = (uint *)GPU_vertbuf_raw_step(&data_step);
*data = (uint)i;
}
}
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->final[subdiv].proc_hair_index_buf);
+ GPU_vertbuf_use(cache->final[subdiv].proc_hair_index_buf);
cache->final[subdiv].hair_index_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_hair_index_buf);
}
@@ -836,37 +836,37 @@ static void particle_batch_cache_ensure_procedural_strand_data(
}
}
- Gwn_VertBufRaw data_step;
- Gwn_VertBufRaw uv_step[MAX_MTFACE];
- Gwn_VertBufRaw col_step[MAX_MCOL];
+ GPUVertBufRaw data_step;
+ GPUVertBufRaw uv_step[MAX_MTFACE];
+ GPUVertBufRaw col_step[MAX_MCOL];
MTFace *mtfaces[MAX_MTFACE] = {NULL};
MCol *mcols[MAX_MCOL] = {NULL};
float (**parent_uvs)[2] = NULL;
MCol **parent_mcol = NULL;
- Gwn_VertFormat format_data = {0};
- uint data_id = GWN_vertformat_attr_add(&format_data, "data", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat format_data = {0};
+ uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
- Gwn_VertFormat format_uv = {0};
- uint uv_id = GWN_vertformat_attr_add(&format_uv, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat format_uv = {0};
+ uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- Gwn_VertFormat format_col = {0};
- uint col_id = GWN_vertformat_attr_add(&format_col, "col", GWN_COMP_U16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat format_col = {0};
+ uint col_id = GPU_vertformat_attr_add(&format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names));
memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names));
/* Strand Data */
- cache->proc_strand_buf = GWN_vertbuf_create_with_format(&format_data);
- GWN_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
+ cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
+ GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
/* UV layers */
for (int i = 0; i < cache->num_uv_layers; i++) {
- cache->proc_uv_buf[i] = GWN_vertbuf_create_with_format(&format_uv);
- GWN_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
+ cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv);
+ GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
uint hash = BLI_ghashutil_strhash_p(name);
@@ -880,9 +880,9 @@ static void particle_batch_cache_ensure_procedural_strand_data(
}
/* Vertex colors */
for (int i = 0; i < cache->num_col_layers; i++) {
- cache->proc_col_buf[i] = GWN_vertbuf_create_with_format(&format_col);
- GWN_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
- GWN_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
+ cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col);
+ GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
uint hash = BLI_ghashutil_strhash_p(name);
@@ -959,15 +959,15 @@ static void particle_batch_cache_ensure_procedural_strand_data(
}
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->proc_strand_buf);
+ GPU_vertbuf_use(cache->proc_strand_buf);
cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
for (int i = 0; i < cache->num_uv_layers; i++) {
- GWN_vertbuf_use(cache->proc_uv_buf[i]);
+ GPU_vertbuf_use(cache->proc_uv_buf[i]);
cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]);
}
for (int i = 0; i < cache->num_col_layers; i++) {
- GWN_vertbuf_use(cache->proc_col_buf[i]);
+ GPU_vertbuf_use(cache->proc_col_buf[i]);
cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]);
}
}
@@ -986,19 +986,19 @@ static void particle_batch_cache_ensure_procedural_indices(
}
int element_count = cache->final[subdiv].elems_len;
- Gwn_PrimType prim_type = (thickness_res == 1) ? GWN_PRIM_LINE_STRIP : GWN_PRIM_TRI_STRIP;
+ GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
- static Gwn_VertFormat format = { 0 };
- GWN_vertformat_clear(&format);
+ static GPUVertFormat format = { 0 };
+ GPU_vertformat_clear(&format);
/* initialize vertex format */
- GWN_vertformat_attr_add(&format, "dummy", GWN_COMP_U8, 1, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 1);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true);
if (edit != NULL && edit->pathcache != NULL) {
particle_batch_cache_fill_segments_indices(
@@ -1019,11 +1019,11 @@ static void particle_batch_cache_ensure_procedural_indices(
}
}
- cache->final[subdiv].proc_hairs[thickness_res - 1] = GWN_batch_create_ex(
+ cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
prim_type,
vbo,
- GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GPU_indexbuf_build(&elb),
+ GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
static void particle_batch_cache_ensure_procedural_pos(
@@ -1036,14 +1036,14 @@ static void particle_batch_cache_ensure_procedural_pos(
}
/* initialize vertex format */
- Gwn_VertFormat format = {0};
- uint pos_id = GWN_vertformat_attr_add(&format, "posTime", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->proc_point_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
+ cache->proc_point_buf = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
if (edit != NULL && edit->pathcache != NULL) {
particle_batch_cache_fill_segments_proc_pos(
@@ -1070,7 +1070,7 @@ static void particle_batch_cache_ensure_procedural_pos(
}
/* Create vbo immediatly to bind to texture buffer. */
- GWN_vertbuf_use(cache->proc_point_buf);
+ GPU_vertbuf_use(cache->proc_point_buf);
cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
}
@@ -1088,10 +1088,10 @@ static void particle_batch_cache_ensure_pos_and_seg(
int curr_point = 0;
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
+ GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
HairAttributeID attr_id;
uint *uv_id = NULL;
uint *col_id = NULL;
@@ -1115,12 +1115,12 @@ static void particle_batch_cache_ensure_pos_and_seg(
}
}
- GWN_vertformat_clear(&format);
+ GPU_vertformat_clear(&format);
/* initialize vertex format */
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.tan = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.ind = GPU_vertformat_attr_add(&format, "ind", GPU_COMP_I32, 1, GPU_FETCH_INT);
if (psmd) {
uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attrib format");
@@ -1131,10 +1131,10 @@ static void particle_batch_cache_ensure_pos_and_seg(
char uuid[32];
BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
- uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uv_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (i == active_uv) {
- GWN_vertformat_alias_add(&format, "u");
+ GPU_vertformat_alias_add(&format, "u");
}
}
@@ -1143,21 +1143,21 @@ static void particle_batch_cache_ensure_pos_and_seg(
char uuid[32];
BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name));
- col_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ col_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (i == active_col) {
- GWN_vertformat_alias_add(&format, "c");
+ GPU_vertformat_alias_add(&format, "c");
}
}
}
- hair_cache->pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
+ hair_cache->pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init_ex(
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(
&elb,
- GWN_PRIM_LINE_STRIP,
+ GPU_PRIM_LINE_STRIP,
hair_cache->elems_len, hair_cache->point_len,
true);
@@ -1226,7 +1226,7 @@ static void particle_batch_cache_ensure_pos_and_seg(
if (psmd != NULL) {
MEM_freeN(uv_id);
}
- hair_cache->indices = GWN_indexbuf_build(&elb);
+ hair_cache->indices = GPU_indexbuf_build(&elb);
}
static void particle_batch_cache_ensure_pos(
@@ -1238,7 +1238,7 @@ static void particle_batch_cache_ensure_pos(
return;
}
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, rot_id, val_id;
int i, curr_point;
ParticleData *pa;
@@ -1260,17 +1260,17 @@ static void particle_batch_cache_ensure_pos(
}
}
- GWN_VERTBUF_DISCARD_SAFE(point_cache->pos);
+ GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
if (format.attr_len == 0) {
/* initialize vertex format */
- pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ rot_id = GPU_vertformat_attr_add(&format, "rot", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ val_id = GPU_vertformat_attr_add(&format, "val", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
- point_cache->pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(point_cache->pos, psys->totpart);
+ point_cache->pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(point_cache->pos, psys->totpart);
for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
state.time = DEG_get_ctime(draw_ctx->depsgraph);
@@ -1280,8 +1280,8 @@ static void particle_batch_cache_ensure_pos(
float val;
- GWN_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, pa->state.co);
- GWN_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, pa->state.rot);
+ GPU_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, pa->state.co);
+ GPU_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, pa->state.rot);
switch (psys->part->draw_col) {
case PART_DRAW_COL_VEL:
@@ -1297,13 +1297,13 @@ static void particle_batch_cache_ensure_pos(
break;
}
- GWN_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val);
+ GPU_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val);
curr_point++;
}
if (curr_point != psys->totpart) {
- GWN_vertbuf_data_resize(point_cache->pos, curr_point);
+ GPU_vertbuf_data_resize(point_cache->pos, curr_point);
}
}
@@ -1377,7 +1377,7 @@ static void drw_particle_get_hair_source(
}
}
-Gwn_Batch *DRW_particles_batch_cache_get_hair(
+GPUBatch *DRW_particles_batch_cache_get_hair(
Object *object,
ParticleSystem *psys,
ModifierData *md)
@@ -1389,27 +1389,27 @@ Gwn_Batch *DRW_particles_batch_cache_get_hair(
drw_particle_get_hair_source(object, psys, md, NULL, &source);
ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
particle_batch_cache_ensure_pos_and_seg(source.edit, source.psys, source.md, &cache->hair);
- cache->hair.hairs = GWN_batch_create(
- GWN_PRIM_LINE_STRIP,
+ cache->hair.hairs = GPU_batch_create(
+ GPU_PRIM_LINE_STRIP,
cache->hair.pos,
cache->hair.indices);
}
return cache->hair.hairs;
}
-Gwn_Batch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys)
+GPUBatch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys)
{
ParticleBatchCache *cache = particle_batch_cache_get(psys);
if (cache->point.points == NULL) {
particle_batch_cache_ensure_pos(object, psys, &cache->point);
- cache->point.points = GWN_batch_create(GWN_PRIM_POINTS, cache->point.pos, NULL);
+ cache->point.points = GPU_batch_create(GPU_PRIM_POINTS, cache->point.pos, NULL);
}
return cache->point.points;
}
-Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(
+GPUBatch *DRW_particles_batch_cache_get_edit_strands(
Object *object,
ParticleSystem *psys,
PTCacheEdit *edit)
@@ -1421,8 +1421,8 @@ Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(
drw_particle_update_ptcache_edit(object, psys, edit);
ensure_seg_pt_count(edit, psys, &cache->edit_hair);
particle_batch_cache_ensure_pos_and_seg(edit, psys, NULL, &cache->edit_hair);
- cache->edit_hair.hairs = GWN_batch_create(
- GWN_PRIM_LINE_STRIP,
+ cache->edit_hair.hairs = GPU_batch_create(
+ GPU_PRIM_LINE_STRIP,
cache->edit_hair.pos,
cache->edit_hair.indices);
return cache->edit_hair.hairs;
@@ -1462,19 +1462,19 @@ static void particle_batch_cache_ensure_edit_inner_pos(
return;
}
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, color_id;
- GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
if (format.attr_len == 0) {
/* initialize vertex format */
- pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- cache->edit_inner_pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len);
+ cache->edit_inner_pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len);
float selected_color[4], normal_color[4];
edit_colors_get(edit, selected_color, normal_color);
@@ -1484,19 +1484,19 @@ static void particle_batch_cache_ensure_edit_inner_pos(
const PTCacheEditPoint *point = &edit->points[point_index];
for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
PTCacheEditKey *key = &point->keys[key_index];
- GWN_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
+ GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
if (key->flag & PEK_SELECT) {
- GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color);
+ GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color);
}
else {
- GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color);
+ GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color);
}
global_key_index++;
}
}
}
-Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(
+GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(
Object *object,
ParticleSystem *psys,
PTCacheEdit *edit)
@@ -1508,8 +1508,8 @@ Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(
drw_particle_update_ptcache_edit(object, psys, edit);
ensure_edit_inner_points_count(edit, cache);
particle_batch_cache_ensure_edit_inner_pos(edit, cache);
- cache->edit_inner_points = GWN_batch_create(
- GWN_PRIM_POINTS,
+ cache->edit_inner_points = GPU_batch_create(
+ GPU_PRIM_POINTS,
cache->edit_inner_pos,
NULL);
return cache->edit_inner_points;
@@ -1533,19 +1533,19 @@ static void particle_batch_cache_ensure_edit_tip_pos(
return;
}
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint pos_id, color_id;
- GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
if (format.attr_len == 0) {
/* initialize vertex format */
- pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- cache->edit_tip_pos = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len);
+ cache->edit_tip_pos = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len);
float selected_color[4], normal_color[4];
edit_colors_get(edit, selected_color, normal_color);
@@ -1553,17 +1553,17 @@ static void particle_batch_cache_ensure_edit_tip_pos(
for (int point_index = 0; point_index < edit->totpoint; point_index++) {
const PTCacheEditPoint *point = &edit->points[point_index];
PTCacheEditKey *key = &point->keys[point->totkey - 1];
- GWN_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co);
+ GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co);
if (key->flag & PEK_SELECT) {
- GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color);
+ GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color);
}
else {
- GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color);
+ GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color);
}
}
}
-Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(
+GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(
Object *object,
ParticleSystem *psys,
PTCacheEdit *edit)
@@ -1575,8 +1575,8 @@ Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(
drw_particle_update_ptcache_edit(object, psys, edit);
ensure_edit_tip_points_count(edit, cache);
particle_batch_cache_ensure_edit_tip_pos(edit, cache);
- cache->edit_tip_points = GWN_batch_create(
- GWN_PRIM_POINTS,
+ cache->edit_tip_points = GPU_batch_create(
+ GPU_PRIM_POINTS,
cache->edit_tip_pos,
NULL);
return cache->edit_tip_points;
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index a1c60be4742..77d6e888771 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -162,6 +162,8 @@ extern char datatoc_animviz_mpath_lines_vert_glsl[];
extern char datatoc_animviz_mpath_lines_geom_glsl[];
extern char datatoc_animviz_mpath_points_vert_glsl[];
+extern char datatoc_volume_velocity_vert_glsl[];
+
extern char datatoc_armature_axes_vert_glsl[];
extern char datatoc_armature_sphere_solid_vert_glsl[];
extern char datatoc_armature_sphere_solid_frag_glsl[];
@@ -199,33 +201,36 @@ static struct {
struct GPUShader *mpath_line_sh;
struct GPUShader *mpath_points_sh;
+ struct GPUShader *volume_velocity_needle_sh;
+ struct GPUShader *volume_velocity_sh;
+
struct GPUShader *mball_handles;
} g_shaders = {NULL};
static struct {
- struct Gwn_VertFormat *instance_screenspace;
- struct Gwn_VertFormat *instance_color;
- struct Gwn_VertFormat *instance_screen_aligned;
- struct Gwn_VertFormat *instance_scaled;
- struct Gwn_VertFormat *instance_sized;
- struct Gwn_VertFormat *instance_outline;
- struct Gwn_VertFormat *instance;
- struct Gwn_VertFormat *instance_camera;
- struct Gwn_VertFormat *instance_distance_lines;
- struct Gwn_VertFormat *instance_spot;
- struct Gwn_VertFormat *instance_bone;
- struct Gwn_VertFormat *instance_bone_stick;
- struct Gwn_VertFormat *instance_bone_outline;
- struct Gwn_VertFormat *instance_bone_envelope;
- struct Gwn_VertFormat *instance_bone_envelope_distance;
- struct Gwn_VertFormat *instance_bone_envelope_outline;
- struct Gwn_VertFormat *instance_mball_handles;
- struct Gwn_VertFormat *dynlines_color;
+ struct GPUVertFormat *instance_screenspace;
+ struct GPUVertFormat *instance_color;
+ struct GPUVertFormat *instance_screen_aligned;
+ struct GPUVertFormat *instance_scaled;
+ struct GPUVertFormat *instance_sized;
+ struct GPUVertFormat *instance_outline;
+ struct GPUVertFormat *instance;
+ struct GPUVertFormat *instance_camera;
+ struct GPUVertFormat *instance_distance_lines;
+ struct GPUVertFormat *instance_spot;
+ struct GPUVertFormat *instance_bone;
+ struct GPUVertFormat *instance_bone_stick;
+ struct GPUVertFormat *instance_bone_outline;
+ struct GPUVertFormat *instance_bone_envelope;
+ struct GPUVertFormat *instance_bone_envelope_distance;
+ struct GPUVertFormat *instance_bone_envelope_outline;
+ struct GPUVertFormat *instance_mball_handles;
+ struct GPUVertFormat *dynlines_color;
} g_formats = {NULL};
void DRW_globals_free(void)
{
- struct Gwn_VertFormat **format = &g_formats.instance_screenspace;
+ struct GPUVertFormat **format = &g_formats.instance_screenspace;
for (int i = 0; i < sizeof(g_formats) / sizeof(void *); ++i, ++format) {
MEM_SAFE_FREE(*format);
}
@@ -299,7 +304,7 @@ DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4
return grp;
}
-DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *geom, float *size)
+DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct GPUBatch *geom, float *size)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
@@ -317,7 +322,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g
return grp;
}
-DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct GPUBatch *geom)
{
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);
@@ -333,7 +338,7 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
@@ -347,7 +352,7 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED);
@@ -363,7 +368,7 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch
return grp;
}
-DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS);
@@ -379,7 +384,7 @@ DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *ge
return grp;
}
-DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE);
@@ -394,7 +399,7 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
@@ -409,7 +414,7 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct Gwn_Batch *geom, int *baseid)
+DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct GPUBatch *geom, int *baseid)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE);
@@ -425,7 +430,7 @@ DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct Gwn_Batch *geom,
return grp;
}
-DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA);
@@ -442,7 +447,7 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
static float point_size = 4.0f;
@@ -460,7 +465,7 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch
return grp;
}
-DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
static const int True = true;
@@ -547,7 +552,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass)
return grp;
}
-DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass)
+DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, bool transp)
{
if (g_shaders.bone_envelope == NULL) {
g_shaders.bone_envelope = DRW_shader_create(
@@ -567,6 +572,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass)
g_shaders.bone_envelope,
pass, DRW_cache_bone_envelope_solid_get(),
g_formats.instance_bone_envelope);
+ DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f);
return grp;
}
@@ -595,7 +601,7 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass)
}
/* Only works with batches with adjacency infos. */
-DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct GPUBatch *geom)
{
if (g_shaders.shape_outline == NULL) {
g_shaders.shape_outline = DRW_shader_create(
@@ -618,7 +624,7 @@ DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_B
return grp;
}
-DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct Gwn_Batch *geom)
+DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct GPUBatch *geom, bool transp)
{
if (g_shaders.shape_solid == NULL) {
g_shaders.shape_solid = DRW_shader_create(
@@ -636,11 +642,12 @@ DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct Gwn_Bat
g_shaders.shape_solid,
pass, geom, g_formats.instance_bone);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f);
return grp;
}
-DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass)
+DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass, bool transp)
{
if (g_shaders.bone_sphere == NULL) {
g_shaders.bone_sphere = DRW_shader_create(
@@ -657,6 +664,8 @@ DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass)
DRWShadingGroup *grp = DRW_shgroup_instance_create(
g_shaders.bone_sphere,
pass, DRW_cache_bone_point_get(), g_formats.instance_bone);
+ /* More transparent than the shape to be less distractive. */
+ DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.4f : 1.0f);
return grp;
}
@@ -736,6 +745,26 @@ struct GPUShader *mpath_points_shader_get(void)
return g_shaders.mpath_points_sh;
}
+struct GPUShader *volume_velocity_shader_get(bool use_needle)
+{
+ if (use_needle) {
+ if (g_shaders.volume_velocity_needle_sh == NULL) {
+ g_shaders.volume_velocity_needle_sh = DRW_shader_create(
+ datatoc_volume_velocity_vert_glsl, NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl, "#define USE_NEEDLE");
+ }
+ return g_shaders.volume_velocity_needle_sh;
+ }
+ else {
+ if (g_shaders.volume_velocity_sh == NULL) {
+ g_shaders.volume_velocity_sh = DRW_shader_create(
+ datatoc_volume_velocity_vert_glsl, NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl, NULL);
+ }
+ return g_shaders.volume_velocity_sh;
+ }
+}
+
/* ******************************************** COLOR UTILS *********************************************** */
/* TODO FINISH */
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 2e284761b11..54b8655b1df 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -29,7 +29,7 @@
struct Mesh;
struct DRWPass;
struct DRWShadingGroup;
-struct Gwn_Batch;
+struct GPUBatch;
struct GPUMaterial;
struct GPUShader;
struct GPUTexture;
@@ -118,32 +118,34 @@ struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pa
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 Gwn_Batch *geom, float *size);
-struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct Gwn_Batch *geom, int *baseid);
-struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct GPUBatch *geom, float *size);
+struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct GPUBatch *geom, int *baseid);
+struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct GPUBatch *geom);
struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass);
-struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, bool transp);
+struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, struct GPUBatch *geom, bool transp);
struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass);
-struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass);
+struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass, bool transp);
struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass);
struct GPUShader *mpath_line_shader_get(void);
struct GPUShader *mpath_points_shader_get(void);
+struct GPUShader *volume_velocity_shader_get(bool use_needle);
+
int DRW_object_wire_theme_get(
struct Object *ob, struct ViewLayer *view_layer, float **r_color);
float *DRW_color_background_blend_get(int theme_id);
@@ -159,8 +161,8 @@ typedef struct DRWArmaturePasses {
} DRWArmaturePasses;
void DRW_shgroup_armature_object(struct Object *ob, struct ViewLayer *view_layer, struct DRWArmaturePasses passes);
-void DRW_shgroup_armature_pose(struct Object *ob, struct DRWArmaturePasses passes);
-void DRW_shgroup_armature_edit(struct Object *ob, struct DRWArmaturePasses passes);
+void DRW_shgroup_armature_pose(struct Object *ob, struct DRWArmaturePasses passes, bool transp);
+void DRW_shgroup_armature_edit(struct Object *ob, struct DRWArmaturePasses passes, bool transp);
/* draw_hair.c */
diff --git a/source/blender/draw/intern/draw_debug.c b/source/blender/draw/intern/draw_debug.c
index 0e4176f90a6..8af13d66c28 100644
--- a/source/blender/draw/intern/draw_debug.c
+++ b/source/blender/draw/intern/draw_debug.c
@@ -29,6 +29,8 @@
#include "DNA_object_types.h"
+#include "BKE_object.h"
+
#include "BLI_link_utils.h"
#include "GPU_immediate.h"
@@ -105,6 +107,36 @@ void DRW_debug_bbox(const BoundBox *bbox, const float color[4])
DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[7], color);
}
+void DRW_debug_m4_as_bbox(const float m[4][4], const float color[4], const bool invert)
+{
+ BoundBox bb;
+ const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
+ float minv[4][4];
+ if (invert) {
+ invert_m4_m4(minv, m);
+ }
+
+ BKE_boundbox_init_from_minmax(&bb, min, max);
+ for (int i = 0; i < 8; ++i) {
+ mul_project_m4_v3((invert) ? minv : m, bb.vec[i]);
+ }
+ DRW_debug_bbox(&bb, color);
+}
+
+void DRW_debug_sphere(const float center[3], const float radius, const float color[4])
+{
+ float size_mat[4][4];
+ DRWDebugSphere *sphere = MEM_mallocN(sizeof(DRWDebugSphere), "DRWDebugSphere");
+ /* Bake all transform into a Matrix4 */
+ scale_m4_fl(size_mat, radius);
+ copy_m4_m4(sphere->mat, g_modelmat);
+ translate_m4(sphere->mat, center[0], center[1], center[2]);
+ mul_m4_m4m4(sphere->mat, sphere->mat, size_mat);
+
+ copy_v4_v4(sphere->color, color);
+ BLI_LINKS_PREPEND(DST.debug.spheres, sphere);
+}
+
/* --------- Render --------- */
static void drw_debug_draw_lines(void)
@@ -115,13 +147,13 @@ static void drw_debug_draw_lines(void)
return;
}
- Gwn_VertFormat *vert_format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(vert_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *vert_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(vert_format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, count * 2);
+ immBegin(GPU_PRIM_LINES, count * 2);
while (DST.debug.lines) {
void *next = DST.debug.lines->next;
@@ -140,9 +172,51 @@ static void drw_debug_draw_lines(void)
immUnbindProgram();
}
+static void drw_debug_draw_spheres(void)
+{
+ int count = BLI_linklist_count((LinkNode *)DST.debug.spheres);
+
+ if (count == 0) {
+ return;
+ }
+
+ float one = 1.0f;
+ GPUVertFormat vert_format = {0};
+ uint mat = GPU_vertformat_attr_add(&vert_format, "InstanceModelMatrix", GPU_COMP_F32, 16, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(&vert_format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint siz = GPU_vertformat_attr_add(&vert_format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *inst_vbo = GPU_vertbuf_create_with_format(&vert_format);
+
+ GPU_vertbuf_data_alloc(inst_vbo, count);
+
+ int v = 0;
+ while (DST.debug.spheres) {
+ void *next = DST.debug.spheres->next;
+
+ GPU_vertbuf_attr_set(inst_vbo, mat, v, DST.debug.spheres->mat[0]);
+ GPU_vertbuf_attr_set(inst_vbo, col, v, DST.debug.spheres->color);
+ GPU_vertbuf_attr_set(inst_vbo, siz, v, &one);
+ v++;
+
+ MEM_freeN(DST.debug.spheres);
+ DST.debug.spheres = next;
+ }
+
+ GPUBatch *empty_sphere = DRW_cache_empty_sphere_get();
+
+ GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_LINES, empty_sphere->verts[0], NULL);
+ GPU_batch_instbuf_set(draw_batch, inst_vbo, true);
+ GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
+
+ GPU_batch_draw(draw_batch);
+ GPU_batch_discard(draw_batch);
+}
+
void drw_debug_draw(void)
{
drw_debug_draw_lines();
+ drw_debug_draw_spheres();
}
void drw_debug_init(void)
diff --git a/source/blender/draw/intern/draw_debug.h b/source/blender/draw/intern/draw_debug.h
index 1dab431fc88..319d2674279 100644
--- a/source/blender/draw/intern/draw_debug.h
+++ b/source/blender/draw/intern/draw_debug.h
@@ -34,6 +34,8 @@ void DRW_debug_modelmat(const float modelmat[4][4]);
void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]);
void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]);
void DRW_debug_m4(const float m[4][4]);
+void DRW_debug_m4_as_bbox(const float m[4][4], const float color[4], const bool invert);
void DRW_debug_bbox(const BoundBox *bbox, const float color[4]);
+void DRW_debug_sphere(const float center[3], const float radius, const float color[4]);
#endif /* __DRAW_DEBUG_H__ */
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 7406e7a0645..e2680a1821e 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -90,32 +90,32 @@ void DRW_hair_init(void)
void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
/* TODO more granular update tagging. */
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf);
DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex);
for (int i = 0; i < MAX_MTFACE; ++i) {
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]);
}
for (int i = 0; i < MAX_MCOL; ++i) {
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]);
DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]);
}
for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) {
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_point_buf);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_point_buf);
DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex);
for (int j = 0; j < MAX_THICKRES; ++j) {
- GWN_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
+ GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
}
}
/* "Normal" legacy hairs */
- GWN_BATCH_DISCARD_SAFE(hair_cache->hairs);
- GWN_VERTBUF_DISCARD_SAFE(hair_cache->pos);
- GWN_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
+ GPU_BATCH_DISCARD_SAFE(hair_cache->hairs);
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
+ GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
}
static DRWShadingGroup *drw_shgroup_create_particle_hair_procedural_ex(
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index e035131b4d7..395939838f0 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -43,14 +43,14 @@ struct HairSystem;
typedef struct ParticleHairFinalCache {
/* Output of the subdivision stage: vertex buff sized to subdiv level. */
- Gwn_VertBuf *proc_point_buf;
+ GPUVertBuf *proc_point_buf;
GPUTexture *proc_tex;
- Gwn_VertBuf *proc_hair_index_buf; /* Hair strand index for each vertex */
+ GPUVertBuf *proc_hair_index_buf; /* Hair strand index for each vertex */
GPUTexture *hair_index_tex;
/* Just contains a huge index buffer used to draw the final hair. */
- Gwn_Batch *proc_hairs[MAX_THICKRES];
+ GPUBatch *proc_hairs[MAX_THICKRES];
int strands_len;
int elems_len;
@@ -58,22 +58,22 @@ typedef struct ParticleHairFinalCache {
} ParticleHairFinalCache;
typedef struct ParticleHairCache {
- Gwn_VertBuf *pos;
- Gwn_IndexBuf *indices;
- Gwn_Batch *hairs;
+ GPUVertBuf *pos;
+ GPUIndexBuf *indices;
+ GPUBatch *hairs;
/* Hair Procedural display: Interpolation is done on the GPU. */
- Gwn_VertBuf *proc_point_buf; /* Input control points */
+ GPUVertBuf *proc_point_buf; /* Input control points */
GPUTexture *point_tex;
- Gwn_VertBuf *proc_strand_buf; /* Infos of control points strands (segment count and base index) */
+ GPUVertBuf *proc_strand_buf; /* Infos of control points strands (segment count and base index) */
GPUTexture *strand_tex;
- Gwn_VertBuf *proc_uv_buf[MAX_MTFACE];
+ GPUVertBuf *proc_uv_buf[MAX_MTFACE];
GPUTexture *uv_tex[MAX_MTFACE];
char uv_layer_names[MAX_MTFACE][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN];
- Gwn_VertBuf *proc_col_buf[MAX_MCOL];
+ GPUVertBuf *proc_col_buf[MAX_MCOL];
GPUTexture *col_tex[MAX_MCOL];
char col_layer_names[MAX_MCOL][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN];
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index e322d4780d5..89cffd6c19c 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -45,17 +45,17 @@
typedef struct DRWBatchingBuffer {
struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
- Gwn_VertFormat *format; /* Identifier. */
- Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */
- Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */
+ GPUVertFormat *format; /* Identifier. */
+ GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */
+ GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */
} DRWBatchingBuffer;
typedef struct DRWInstancingBuffer {
struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
- Gwn_VertFormat *format; /* Identifier. */
- Gwn_Batch *instance; /* Identifier. */
- Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */
- Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */
+ GPUVertFormat *format; /* Identifier. */
+ GPUBatch *instance; /* Identifier. */
+ GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */
+ GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */
} DRWInstancingBuffer;
typedef struct DRWInstanceChunk {
@@ -100,7 +100,7 @@ static ListBase g_idatalists = {NULL, NULL};
* that would be too slow]).
**/
-static void instance_batch_free(Gwn_Batch *batch, void *UNUSED(user_data))
+static void instance_batch_free(GPUBatch *batch, void *UNUSED(user_data))
{
/* Free all batches that have the same key before they are reused. */
/* TODO: Make it thread safe! Batch freeing can happen from another thread. */
@@ -111,8 +111,8 @@ static void instance_batch_free(Gwn_Batch *batch, void *UNUSED(user_data))
for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
if (ibuf->instance == batch) {
BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */
- GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GPU_BATCH_DISCARD_SAFE(ibuf->batch);
/* Tag as non alloced. */
ibuf->format = NULL;
}
@@ -121,8 +121,8 @@ static void instance_batch_free(Gwn_Batch *batch, void *UNUSED(user_data))
}
void DRW_batching_buffer_request(
- DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup,
- Gwn_Batch **r_batch, Gwn_VertBuf **r_vert)
+ DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUPrimType type, struct DRWShadingGroup *shgroup,
+ GPUBatch **r_batch, GPUVertBuf **r_vert)
{
DRWInstanceChunk *chunk = &idatalist->batching;
DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
@@ -152,16 +152,16 @@ void DRW_batching_buffer_request(
}
/* Create the batch. */
bbuf = chunk->bbufs + new_id;
- bbuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC);
- bbuf->batch = *r_batch = GWN_batch_create_ex(type, bbuf->vert, NULL, 0);
+ bbuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC);
+ bbuf->batch = *r_batch = GPU_batch_create_ex(type, bbuf->vert, NULL, 0);
bbuf->format = format;
bbuf->shgroup = shgroup;
- GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
+ GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
}
void DRW_instancing_buffer_request(
- DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup,
- Gwn_Batch **r_batch, Gwn_VertBuf **r_vert)
+ DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUBatch *instance, struct DRWShadingGroup *shgroup,
+ GPUBatch **r_batch, GPUVertBuf **r_vert)
{
DRWInstanceChunk *chunk = &idatalist->instancing;
DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
@@ -193,15 +193,15 @@ void DRW_instancing_buffer_request(
}
/* Create the batch. */
ibuf = chunk->ibufs + new_id;
- ibuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC);
- ibuf->batch = *r_batch = GWN_batch_duplicate(instance);
+ ibuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC);
+ ibuf->batch = *r_batch = GPU_batch_duplicate(instance);
ibuf->format = format;
ibuf->shgroup = shgroup;
ibuf->instance = instance;
- GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
- GWN_batch_instbuf_set(ibuf->batch, ibuf->vert, false);
+ GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
+ GPU_batch_instbuf_set(ibuf->batch, ibuf->vert, false);
/* Make sure to free this ibuf if the instance batch gets free. */
- GWN_batch_callback_free_set(instance, &instance_batch_free, NULL);
+ GPU_batch_callback_free_set(instance, &instance_batch_free, NULL);
}
void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
@@ -218,14 +218,14 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
if (vert_len + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_len) {
uint size = vert_len + BUFFER_VERTS_CHUNK - 1;
size = size - size % BUFFER_VERTS_CHUNK;
- GWN_vertbuf_data_resize(bbuf->vert, size);
+ GPU_vertbuf_data_resize(bbuf->vert, size);
}
- GWN_vertbuf_use(bbuf->vert); /* Send data. */
+ GPU_vertbuf_use(bbuf->vert); /* Send data. */
bbuf->shgroup = NULL; /* Set as non used for the next round. */
}
else {
- GWN_VERTBUF_DISCARD_SAFE(bbuf->vert);
- GWN_BATCH_DISCARD_SAFE(bbuf->batch);
+ GPU_VERTBUF_DISCARD_SAFE(bbuf->vert);
+ GPU_BATCH_DISCARD_SAFE(bbuf->batch);
bbuf->format = NULL; /* Tag as non alloced. */
}
}
@@ -250,14 +250,14 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
if (vert_len + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_len) {
uint size = vert_len + BUFFER_VERTS_CHUNK - 1;
size = size - size % BUFFER_VERTS_CHUNK;
- GWN_vertbuf_data_resize(ibuf->vert, size);
+ GPU_vertbuf_data_resize(ibuf->vert, size);
}
- GWN_vertbuf_use(ibuf->vert); /* Send data. */
+ GPU_vertbuf_use(ibuf->vert); /* Send data. */
ibuf->shgroup = NULL; /* Set as non used for the next round. */
}
else {
- GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GPU_BATCH_DISCARD_SAFE(ibuf->batch);
ibuf->format = NULL; /* Tag as non alloced. */
}
}
@@ -366,15 +366,15 @@ void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) {
- GWN_VERTBUF_DISCARD_SAFE(bbuf->vert);
- GWN_BATCH_DISCARD_SAFE(bbuf->batch);
+ GPU_VERTBUF_DISCARD_SAFE(bbuf->vert);
+ GPU_BATCH_DISCARD_SAFE(bbuf->batch);
}
MEM_freeN(idatalist->batching.bbufs);
DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
- GWN_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GWN_BATCH_DISCARD_SAFE(ibuf->batch);
+ GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
+ GPU_BATCH_DISCARD_SAFE(ibuf->batch);
}
MEM_freeN(idatalist->instancing.ibufs);
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
index 0ea40a50a6b..174f03e3bc7 100644
--- a/source/blender/draw/intern/draw_instance_data.h
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -43,11 +43,11 @@ DRWInstanceData *DRW_instance_data_request(
DRWInstanceDataList *idatalist, uint attrib_size);
void DRW_batching_buffer_request(
- DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup,
- Gwn_Batch **r_batch, Gwn_VertBuf **r_vert);
+ DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUPrimType type, struct DRWShadingGroup *shgroup,
+ GPUBatch **r_batch, GPUVertBuf **r_vert);
void DRW_instancing_buffer_request(
- DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup,
- Gwn_Batch **r_batch, Gwn_VertBuf **r_vert);
+ DRWInstanceDataList *idatalist, GPUVertFormat *format, GPUBatch *instance, struct DRWShadingGroup *shgroup,
+ GPUBatch **r_batch, GPUVertBuf **r_vert);
/* Upload all instance data to the GPU as soon as possible. */
void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 5d74c8e69c7..ca95e12de2d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -48,6 +48,7 @@
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_gpencil.h"
#include "ED_particle.h"
#include "ED_view3d.h"
@@ -82,7 +83,7 @@
#include "engines/workbench/workbench_engine.h"
#include "engines/external/external_engine.h"
-#include "../../../intern/gawain/gawain/gwn_context.h"
+#include "GPU_context.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -94,7 +95,7 @@
/** Render State: No persistent data between draw calls. */
DRWManager DST = {NULL};
-ListBase DRW_engines = {NULL, NULL};
+static ListBase DRW_engines = {NULL, NULL};
extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */
@@ -120,16 +121,16 @@ void DRW_draw_callbacks_pre_scene(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
}
void DRW_draw_callbacks_post_scene(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
}
struct DRWTextStore *DRW_text_cache_ensure(void)
@@ -224,13 +225,13 @@ bool DRW_check_psys_visible_within_active_context(
* \{ */
/* Use color management profile to draw texture to framebuffer */
-void DRW_transform_to_display(GPUTexture *tex)
+void DRW_transform_to_display(GPUTexture *tex, bool use_view_settings)
{
drw_state_set(DRW_STATE_WRITE_COLOR);
- Gwn_VertFormat *vert_format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *vert_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const float dither = 1.0f;
@@ -239,8 +240,11 @@ void DRW_transform_to_display(GPUTexture *tex)
/* View transform is already applied for offscreen, don't apply again, see: T52046 */
if (!(DST.options.is_image_render && !DST.options.is_scene_render)) {
Scene *scene = DST.draw_ctx.scene;
+ ColorManagedDisplaySettings *display_settings = &scene->display_settings;
+ ColorManagedViewSettings *view_settings = (use_view_settings) ? &scene->view_settings : NULL;
+
use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
- &scene->view_settings, &scene->display_settings, NULL, dither, false);
+ view_settings, display_settings, NULL, dither, false);
}
if (!use_ocio) {
@@ -262,7 +266,7 @@ void DRW_transform_to_display(GPUTexture *tex)
immUniformMatrix4fv("ModelViewProjectionMatrix", mat);
/* Full screen triangle */
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
immAttrib2f(texco, 0.0f, 0.0f);
immVertex2f(pos, -1.0f, -1.0f);
@@ -283,6 +287,29 @@ void DRW_transform_to_display(GPUTexture *tex)
}
}
+/* Draw texture to framebuffer without any color transforms */
+void DRW_transform_none(GPUTexture *tex)
+{
+ /* Draw as texture for final render (without immediate mode). */
+ GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE_COLOR);
+
+ GPU_texture_bind(tex, 0);
+
+ const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ GPU_batch_uniform_4fv(geom, "color", white);
+
+ float mat[4][4];
+ unit_m4(mat);
+ GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
+
+ GPU_batch_program_use_begin(geom);
+ GPU_batch_draw_range_ex(geom, 0, 0, false);
+ GPU_batch_program_use_end(geom);
+
+ GPU_texture_unbind(tex);
+}
+
/** \} */
@@ -294,45 +321,66 @@ void DRW_transform_to_display(GPUTexture *tex)
/* Use manual multisample resolve pass.
* Much quicker than blitting back and forth.
* Assume destination fb is bound*/
-void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color)
+void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool use_depth)
{
- drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL;
+
+ if (use_depth) {
+ state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ }
+ drw_state_set(state);
int samples = GPU_texture_samples(src_depth);
BLI_assert(samples > 0);
BLI_assert(GPU_texture_samples(src_color) == samples);
- Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ GPUBatch *geom = DRW_cache_fullscreen_quad_get();
int builtin;
- switch (samples) {
- case 2: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; break;
- case 4: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4; break;
- case 8: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8; break;
- case 16: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16; break;
- default:
- BLI_assert(0);
- builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
- break;
+ if (use_depth) {
+ switch (samples) {
+ case 2: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST; break;
+ case 4: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST; break;
+ case 8: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST; break;
+ case 16: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST; break;
+ default:
+ BLI_assert("Mulisample count unsupported by blit shader.");
+ builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST;
+ break;
+ }
+ }
+ else {
+ switch (samples) {
+ case 2: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; break;
+ case 4: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4; break;
+ case 8: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8; break;
+ case 16: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16; break;
+ default:
+ BLI_assert("Mulisample count unsupported by blit shader.");
+ builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
+ break;
+ }
}
- GWN_batch_program_set_builtin(geom, builtin);
+ GPU_batch_program_set_builtin(geom, builtin);
+
+ if (use_depth) {
+ GPU_texture_bind(src_depth, 0);
+ GPU_batch_uniform_1i(geom, "depthMulti", 0);
+ }
- GPU_texture_bind(src_depth, 0);
GPU_texture_bind(src_color, 1);
- GWN_batch_uniform_1i(geom, "depthMulti", 0);
- GWN_batch_uniform_1i(geom, "colorMulti", 1);
+ GPU_batch_uniform_1i(geom, "colorMulti", 1);
float mat[4][4];
unit_m4(mat);
- GWN_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
+ GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
/* avoid gpuMatrix calls */
- GWN_batch_program_use_begin(geom);
- GWN_batch_draw_range_ex(geom, 0, 0, false);
- GWN_batch_program_use_end(geom);
+ GPU_batch_program_use_begin(geom);
+ GPU_batch_draw_range_ex(geom, 0, 0, false);
+ GPU_batch_program_use_end(geom);
}
/** \} */
@@ -1175,10 +1223,17 @@ static void drw_engines_enable_from_mode(int mode)
break;
case CTX_MODE_OBJECT:
break;
+ case CTX_MODE_GPENCIL_PAINT:
+ case CTX_MODE_GPENCIL_EDIT:
+ case CTX_MODE_GPENCIL_SCULPT:
+ case CTX_MODE_GPENCIL_WEIGHT:
+ break;
default:
BLI_assert(!"Draw mode invalid");
break;
}
+ /* grease pencil */
+ use_drw_engine(&draw_engine_gpencil_type);
}
static void drw_engines_enable_from_overlays(int overlay_flag)
@@ -1200,7 +1255,7 @@ static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_t
Object *obact = OBACT(view_layer);
const int mode = CTX_data_mode_enum_ex(DST.draw_ctx.object_edit, obact, DST.draw_ctx.object_mode);
View3D * v3d = DST.draw_ctx.v3d;
- const int drawtype = v3d->drawtype;
+ const int drawtype = v3d->shading.type;
drw_engines_enable_from_engine(engine_type, drawtype, v3d->shading.flag);
@@ -1211,6 +1266,10 @@ static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_t
drw_engines_enable_from_object_mode();
drw_engines_enable_from_mode(mode);
}
+ else {
+ /* if gpencil must draw the strokes, but not the object */
+ drw_engines_enable_from_mode(mode);
+ }
}
static void drw_engines_disable(void)
@@ -1304,7 +1363,7 @@ void DRW_draw_view(const bContext *C)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype);
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar);
/* Reset before using it. */
@@ -1330,6 +1389,7 @@ void DRW_draw_render_loop_ex(
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
+ bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0));
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
@@ -1359,7 +1419,7 @@ void DRW_draw_render_loop_ex(
DRW_hair_init();
/* No framebuffer allowed before drawing. */
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
/* Init engines */
drw_engines_init();
@@ -1424,6 +1484,17 @@ void DRW_draw_render_loop_ex(
drw_engines_draw_scene();
+ /* annotations - temporary drawing buffer (3d space) */
+ /* XXX: Or should we use a proper draw/overlay engine for this case? */
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (do_annotations))
+ {
+ glDisable(GL_DEPTH_TEST);
+ /* XXX: as scene->gpd is not copied for COW yet */
+ ED_gpencil_draw_view3d_annotations(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, true);
+ glEnable(GL_DEPTH_TEST);
+ }
+
DRW_draw_callbacks_post_scene();
if (DST.draw_ctx.evil_C) {
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
@@ -1440,7 +1511,7 @@ void DRW_draw_render_loop_ex(
if (DST.draw_ctx.evil_C) {
/* needed so gizmo isn't obscured */
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- ((v3d->mpr_flag & V3D_GIZMO_HIDE) == 0))
+ ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0))
{
glDisable(GL_DEPTH_TEST);
DRW_draw_gizmo_3d();
@@ -1448,6 +1519,17 @@ void DRW_draw_render_loop_ex(
DRW_draw_region_info();
+ /* annotations - temporary drawing buffer (screenspace) */
+ /* XXX: Or should we use a proper draw/overlay engine for this case? */
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (do_annotations))
+ {
+ glDisable(GL_DEPTH_TEST);
+ /* XXX: as scene->gpd is not copied for COW yet */
+ ED_gpencil_draw_view3d_annotations(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
+ glEnable(GL_DEPTH_TEST);
+ }
+
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
/* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
* 'DRW_draw_region_info' sets the projection in pixel-space. */
@@ -1499,7 +1581,7 @@ void DRW_draw_render_loop(
drw_state_prepare_clean_for_draw(&DST);
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype);
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL);
}
@@ -1536,6 +1618,125 @@ void DRW_draw_render_loop_offscreen(
GPU_offscreen_bind(ofs, false);
}
+/* helper to check if exit object type to render */
+static bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
+{
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
+ {
+ if ((ob->type == OB_GPENCIL) && (DRW_check_object_visible_within_active_context(ob))) {
+ return true;
+ }
+ }
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+
+ return false;
+}
+
+static void DRW_render_gpencil_to_image(RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect)
+{
+ if (draw_engine_gpencil_type.render_to_image) {
+ ViewportEngineData *gpdata = drw_viewport_engine_data_ensure(&draw_engine_gpencil_type);
+ draw_engine_gpencil_type.render_to_image(gpdata, engine, render_layer, rect);
+ }
+}
+
+void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ /* This function is only valid for Cycles
+ * Eevee done all work in the Eevee render directly.
+ * Maybe it can be done equal for both engines?
+ */
+ if (STREQ(engine->type->name, "Eevee")) {
+ return;
+ }
+
+ /* Early out if there are no grease pencil objects, especially important
+ * to avoid failing in in background renders without OpenGL context. */
+ if (!DRW_render_check_grease_pencil(depsgraph)) {
+ return;
+ }
+
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ RenderEngineType *engine_type = engine->type;
+ RenderData *r = &scene->r;
+ Render *render = engine->re;
+ /* Changing Context */
+ if (G.background && DST.gl_context == NULL) {
+ WM_init_opengl(G_MAIN);
+ }
+
+ void *re_gl_context = RE_gl_context_get(render);
+ void *re_gpu_context = NULL;
+
+ /* Changing Context */
+ if (re_gl_context != NULL) {
+ DRW_opengl_render_context_enable(re_gl_context);
+ /* We need to query gpu context after a gl context has been bound. */
+ re_gpu_context = RE_gpu_context_get(render);
+ DRW_gawain_render_context_enable(re_gpu_context);
+ }
+ else {
+ DRW_opengl_context_enable();
+ }
+
+ /* Reset before using it. */
+ drw_state_prepare_clean_for_draw(&DST);
+ DST.options.is_image_render = true;
+ DST.options.is_scene_render = true;
+ DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
+ DST.buffer_finish_called = true;
+
+ DST.draw_ctx = (DRWContextState) {
+ .scene = scene, .view_layer = view_layer,
+ .engine_type = engine_type,
+ .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT,
+ };
+ drw_context_state_init();
+
+ DST.viewport = GPU_viewport_create();
+ const int size[2] = { (r->size * r->xsch) / 100, (r->size * r->ysch) / 100 };
+ GPU_viewport_size_set(DST.viewport, size);
+
+ drw_viewport_var_init();
+
+ /* set default viewport */
+ gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, size[0], size[1]);
+
+ /* Main rendering. */
+ rctf view_rect;
+ rcti render_rect;
+ RE_GetViewPlane(render, &view_rect, &render_rect);
+ if (BLI_rcti_is_empty(&render_rect)) {
+ BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
+ }
+
+ RenderResult *render_result = RE_engine_get_result(engine);
+ RenderLayer *render_layer = render_result->layers.first;
+
+ DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
+
+ /* Force cache to reset. */
+ drw_viewport_cache_resize();
+ GPU_viewport_free(DST.viewport);
+ DRW_state_reset();
+
+ glDisable(GL_DEPTH_TEST);
+
+ /* Restore Drawing area. */
+ gpuPopAttrib();
+ glEnable(GL_SCISSOR_TEST);
+ GPU_framebuffer_restore();
+
+ /* Changing Context */
+ /* GPXX Review this context */
+ DRW_opengl_context_disable();
+
+ DST.buffer_finish_called = false;
+}
+
void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
@@ -1550,14 +1751,14 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
}
void *re_gl_context = RE_gl_context_get(render);
- void *re_gwn_context = NULL;
+ void *re_gpu_context = NULL;
/* Changing Context */
if (re_gl_context != NULL) {
DRW_opengl_render_context_enable(re_gl_context);
- /* We need to query gwn context after a gl context has been bound. */
- re_gwn_context = RE_gwn_context_get(render);
- DRW_gawain_render_context_enable(re_gwn_context);
+ /* We need to query gpu context after a gl context has been bound. */
+ re_gpu_context = RE_gpu_context_get(render);
+ DRW_gawain_render_context_enable(re_gpu_context);
}
else {
DRW_opengl_context_enable();
@@ -1616,6 +1817,10 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
RE_SetActiveRenderView(render, render_view->name);
engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
+ /* grease pencil: render result is merged in the previous render result. */
+ if (DRW_render_check_grease_pencil(depsgraph)) {
+ DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
+ }
DST.buffer_finish_called = false;
}
@@ -1624,8 +1829,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Force cache to reset. */
drw_viewport_cache_resize();
- /* TODO grease pencil */
-
GPU_viewport_free(DST.viewport);
GPU_framebuffer_restore();
@@ -1636,7 +1839,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Changing Context */
if (re_gl_context != NULL) {
- DRW_gawain_render_context_disable(re_gwn_context);
+ DRW_gawain_render_context_disable(re_gpu_context);
DRW_opengl_render_context_disable(re_gl_context);
}
else {
@@ -1764,7 +1967,7 @@ void DRW_draw_select_loop(
DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype);
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
Object *obact = OBACT(view_layer);
Object *obedit = OBEDIT_FROM_OBACT(obact);
@@ -1944,9 +2147,9 @@ static void draw_depth_texture_to_screen(GPUTexture *texture)
const float w = (float)GPU_texture_width(texture);
const float h = (float)GPU_texture_height(texture);
- Gwn_VertFormat *format = immVertexFormat();
- uint texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY);
@@ -1954,7 +2157,7 @@ static void draw_depth_texture_to_screen(GPUTexture *texture)
immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- immBegin(GWN_PRIM_TRI_STRIP, 4);
+ immBegin(GPU_PRIM_TRI_STRIP, 4);
immAttrib2f(texcoord, 0.0f, 0.0f);
immVertex2f(pos, 0.0f, 0.0f);
@@ -1983,7 +2186,7 @@ void DRW_draw_depth_loop(
ARegion *ar, View3D *v3d)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype);
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
@@ -2074,18 +2277,18 @@ void DRW_draw_depth_loop(
DRW_opengl_context_disable();
/* XXX Drawing the resulting buffer to the BACK_BUFFER */
- gpuPushMatrix();
- gpuPushProjectionMatrix();
+ GPU_matrix_push();
+ GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */
glDepthFunc(GL_ALWAYS);
draw_depth_texture_to_screen(g_select_buffer.texture_depth);
glDepthFunc(GL_LEQUAL);
- gpuPopMatrix();
- gpuPopProjectionMatrix();
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
}
/** \} */
@@ -2218,7 +2421,7 @@ void DRW_engine_register(DrawEngineType *draw_engine_type)
void DRW_engines_register(void)
{
RE_engines_register(&DRW_engine_viewport_eevee_type);
- RE_engines_register(&DRW_engine_viewport_workbench_type);
+ RE_engines_register(&DRW_engine_viewport_opengl_type);
DRW_engine_register(&draw_engine_workbench_solid);
DRW_engine_register(&draw_engine_workbench_transparent);
@@ -2239,6 +2442,7 @@ void DRW_engines_register(void)
DRW_engine_register(&draw_engine_particle_type);
DRW_engine_register(&draw_engine_pose_type);
DRW_engine_register(&draw_engine_sculpt_type);
+ DRW_engine_register(&draw_engine_gpencil_type);
/* setup callbacks */
{
@@ -2257,6 +2461,9 @@ void DRW_engines_register(void)
/* BKE: particle.c */
extern void *BKE_particle_batch_cache_dirty_cb;
extern void *BKE_particle_batch_cache_free_cb;
+ /* BKE: gpencil.c */
+ extern void *BKE_gpencil_batch_cache_dirty_cb;
+ extern void *BKE_gpencil_batch_cache_free_cb;
/* BKE: hair.c */
extern void *BKE_hair_batch_cache_dirty_cb;
extern void *BKE_hair_batch_cache_free_cb;
@@ -2276,12 +2483,15 @@ void DRW_engines_register(void)
BKE_particle_batch_cache_dirty_cb = DRW_particle_batch_cache_dirty;
BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free;
+ BKE_gpencil_batch_cache_dirty_cb = DRW_gpencil_batch_cache_dirty;
+ BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
+
BKE_hair_batch_cache_dirty_cb = DRW_hair_batch_cache_dirty;
BKE_hair_batch_cache_free_cb = DRW_hair_batch_cache_free;
}
}
-extern struct Gwn_VertFormat *g_pos_format; /* draw_shgroup.c */
+extern struct GPUVertFormat *g_pos_format; /* draw_shgroup.c */
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
extern struct GPUTexture *globals_ramp; /* draw_common.c */
void DRW_engines_free(void)
@@ -2334,8 +2544,9 @@ void DRW_opengl_context_create(void)
}
/* This changes the active context. */
DST.gl_context = WM_opengl_context_create();
+ WM_opengl_context_activate(DST.gl_context);
/* Be sure to create gawain.context too. */
- DST.gwn_context = GWN_context_create();
+ DST.gpu_context = GPU_context_create();
if (!G.background) {
immActivate();
}
@@ -2350,28 +2561,28 @@ void DRW_opengl_context_destroy(void)
BLI_assert(BLI_thread_is_main());
if (DST.gl_context != NULL) {
WM_opengl_context_activate(DST.gl_context);
- GWN_context_active_set(DST.gwn_context);
- GWN_context_discard(DST.gwn_context);
+ GPU_context_active_set(DST.gpu_context);
+ GPU_context_discard(DST.gpu_context);
WM_opengl_context_dispose(DST.gl_context);
BLI_ticket_mutex_free(DST.gl_context_mutex);
}
}
-void DRW_opengl_context_enable(void)
+void DRW_opengl_context_enable_ex(bool restore)
{
if (DST.gl_context != NULL) {
/* IMPORTANT: We dont support immediate mode in render mode!
* This shall remain in effect until immediate mode supports
* multiple threads. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
- if (BLI_thread_is_main()) {
+ if (BLI_thread_is_main() && restore) {
if (!G.background) {
immDeactivate();
}
}
WM_opengl_context_activate(DST.gl_context);
- GWN_context_active_set(DST.gwn_context);
- if (BLI_thread_is_main()) {
+ GPU_context_active_set(DST.gpu_context);
+ if (BLI_thread_is_main() && restore) {
if (!G.background) {
immActivate();
}
@@ -2380,7 +2591,7 @@ void DRW_opengl_context_enable(void)
}
}
-void DRW_opengl_context_disable(void)
+void DRW_opengl_context_disable_ex(bool restore)
{
if (DST.gl_context != NULL) {
#ifdef __APPLE__
@@ -2389,18 +2600,28 @@ void DRW_opengl_context_disable(void)
glFlush();
#endif
- if (BLI_thread_is_main()) {
+ if (BLI_thread_is_main() && restore) {
wm_window_reset_drawable();
}
else {
WM_opengl_context_release(DST.gl_context);
- GWN_context_active_set(NULL);
+ GPU_context_active_set(NULL);
}
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
}
+void DRW_opengl_context_enable(void)
+{
+ DRW_opengl_context_enable_ex(true);
+}
+
+void DRW_opengl_context_disable(void)
+{
+ DRW_opengl_context_disable_ex(true);
+}
+
void DRW_opengl_render_context_enable(void *re_gl_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
@@ -2420,20 +2641,20 @@ void DRW_opengl_render_context_disable(void *re_gl_context)
}
/* Needs to be called AFTER DRW_opengl_render_context_enable() */
-void DRW_gawain_render_context_enable(void *re_gwn_context)
+void DRW_gawain_render_context_enable(void *re_gpu_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
BLI_assert(!BLI_thread_is_main());
- GWN_context_active_set(re_gwn_context);
+ GPU_context_active_set(re_gpu_context);
DRW_shape_cache_reset(); /* XXX fix that too. */
}
/* Needs to be called BEFORE DRW_opengl_render_context_disable() */
-void DRW_gawain_render_context_disable(void *UNUSED(re_gwn_context))
+void DRW_gawain_render_context_disable(void *UNUSED(re_gpu_context))
{
DRW_shape_cache_reset(); /* XXX fix that too. */
- GWN_context_active_set(NULL);
+ GPU_context_active_set(NULL);
}
/** \} */
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 6eae3459c2b..902ecb9ee9b 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -35,6 +35,7 @@
#include "BLI_threads.h"
#include "GPU_batch.h"
+#include "GPU_context.h"
#include "GPU_framebuffer.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
@@ -129,7 +130,7 @@ typedef enum {
DRW_CALL_RANGE, /* Like single but only draw a range of vertices/indices. */
DRW_CALL_INSTANCES, /* Draw instances without any instancing attribs. */
DRW_CALL_GENERATE, /* Uses a callback to draw with any number of batches. */
- DRW_CALL_PROCEDURAL, /* Generate a drawcall without any Gwn_Batch. */
+ DRW_CALL_PROCEDURAL, /* Generate a drawcall without any GPUBatch. */
} DRWCallType;
typedef struct DRWCall {
@@ -138,14 +139,14 @@ typedef struct DRWCall {
union {
struct { /* type == DRW_CALL_SINGLE */
- Gwn_Batch *geometry;
+ GPUBatch *geometry;
} single;
struct { /* type == DRW_CALL_RANGE */
- Gwn_Batch *geometry;
+ GPUBatch *geometry;
uint start, count;
} range;
struct { /* type == DRW_CALL_INSTANCES */
- Gwn_Batch *geometry;
+ GPUBatch *geometry;
/* Count can be adjusted between redraw. If needed, we can add fixed count. */
uint *count;
} instances;
@@ -155,7 +156,7 @@ typedef struct DRWCall {
} generate;
struct { /* type == DRW_CALL_PROCEDURAL */
uint vert_count;
- Gwn_PrimType prim_type;
+ GPUPrimType prim_type;
} procedural;
};
@@ -225,16 +226,16 @@ struct DRWShadingGroup {
} calls;
struct { /* DRW_SHG_FEEDBACK_TRANSFORM */
DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
- struct Gwn_VertBuf *tfeedback_target; /* Transform Feedback target. */
+ struct GPUVertBuf *tfeedback_target; /* Transform Feedback target. */
};
struct { /* DRW_SHG_***_BATCH */
- struct Gwn_Batch *batch_geom; /* Result of call batching */
- struct Gwn_VertBuf *batch_vbo;
+ struct GPUBatch *batch_geom; /* Result of call batching */
+ struct GPUVertBuf *batch_vbo;
uint primitive_count;
};
struct { /* DRW_SHG_INSTANCE[_EXTERNAL] */
- struct Gwn_Batch *instance_geom;
- struct Gwn_VertBuf *instance_vbo;
+ struct GPUBatch *instance_geom;
+ struct GPUVertBuf *instance_vbo;
uint instance_count;
float instance_orcofac[2][3]; /* TODO find a better place. */
};
@@ -261,10 +262,11 @@ struct DRWShadingGroup {
#ifndef NDEBUG
char attribs_count;
#endif
-
-#ifdef USE_GPU_SELECT
- Gwn_VertBuf *inst_selectid;
+#if !defined(NDEBUG) || defined(USE_GPU_SELECT)
DRWPass *pass_parent; /* backlink to pass we're in */
+#endif
+#ifdef USE_GPU_SELECT
+ GPUVertBuf *inst_selectid;
int override_selectid; /* Override for single object instances. */
#endif
};
@@ -296,6 +298,12 @@ typedef struct DRWDebugLine {
float color[4];
} DRWDebugLine;
+typedef struct DRWDebugSphere {
+ struct DRWDebugSphere *next; /* linked list */
+ float mat[4][4];
+ float color[4];
+} DRWDebugSphere;
+
/* ------------- DRAW MANAGER ------------ */
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
@@ -372,7 +380,7 @@ typedef struct DRWManager {
/* gl_context serves as the offset for clearing only
* the top portion of the struct so DO NOT MOVE IT! */
void *gl_context; /* Unique ghost context used by the draw manager. */
- Gwn_Context *gwn_context;
+ GPUContext *gpu_context;
TicketMutex *gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */
/** GPU Resource State: Memory storage between drawing. */
@@ -388,6 +396,7 @@ typedef struct DRWManager {
struct {
/* TODO(fclem) optimize: use chunks. */
DRWDebugLine *lines;
+ DRWDebugSphere *spheres;
} debug;
} DRWManager;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index c259633982e..b97101c0e6d 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -41,7 +41,7 @@
#include "intern/gpu_codegen.h"
-struct Gwn_VertFormat *g_pos_format = NULL;
+struct GPUVertFormat *g_pos_format = NULL;
extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */
@@ -122,7 +122,7 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, const char *name,
if (location == -1) {
if (G.debug & G_DEBUG)
- fprintf(stderr, "Uniform '%s' not found!\n", name);
+ fprintf(stderr, "Pass : %s, Uniform '%s' not found!\n", shgroup->pass_parent->name, name);
/* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
// BLI_assert(0);
return;
@@ -355,7 +355,7 @@ static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obm
return DST.ob_state;
}
-void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4])
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -371,7 +371,7 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
BLI_LINKS_APPEND(&shgroup->calls, call);
}
-void DRW_shgroup_call_range_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count)
+void DRW_shgroup_call_range_add(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count)
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -391,7 +391,7 @@ void DRW_shgroup_call_range_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float
}
static void drw_shgroup_call_procedural_add_ex(
- DRWShadingGroup *shgroup, Gwn_PrimType prim_type, uint vert_count, float (*obmat)[4], Object *ob)
+ DRWShadingGroup *shgroup, GPUPrimType prim_type, uint vert_count, float (*obmat)[4], Object *ob)
{
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -414,28 +414,28 @@ static void drw_shgroup_call_procedural_add_ex(
void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, uint point_len, float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_POINTS, point_len, obmat, NULL);
+ drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_POINTS, point_len, obmat, NULL);
}
void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, uint line_count, float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_LINES, line_count * 2, obmat, NULL);
+ drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_LINES, line_count * 2, obmat, NULL);
}
void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, uint tria_count, float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_TRIS, tria_count * 3, obmat, NULL);
+ drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, obmat, NULL);
}
/* TODO (fclem): this is a sign that the api is starting to be limiting.
* Maybe add special function that general purpose for special cases. */
void DRW_shgroup_call_object_procedural_triangles_culled_add(DRWShadingGroup *shgroup, uint tria_count, Object *ob)
{
- drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_TRIS, tria_count * 3, NULL, ob);
+ drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, NULL, ob);
}
/* These calls can be culled and are optimized for redraw */
-void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, bool bypass_culling)
+void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, bool bypass_culling)
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -455,7 +455,7 @@ void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, Gwn_Batch *geom, O
}
void DRW_shgroup_call_object_add_with_callback(
- DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob,
+ DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob,
DRWCallVisibilityFn *callback, void *user_data)
{
BLI_assert(geom != NULL);
@@ -474,7 +474,7 @@ void DRW_shgroup_call_object_add_with_callback(
BLI_LINKS_APPEND(&shgroup->calls, call);
}
-void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint *count)
+void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4], uint *count)
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -492,7 +492,7 @@ void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, f
}
/* These calls can be culled and are optimized for redraw */
-void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, uint *count)
+void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, uint *count)
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
@@ -531,7 +531,7 @@ void DRW_shgroup_call_generate_add(
static void sculpt_draw_cb(
DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, Gwn_Batch *geom),
+ void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom),
void *user_data)
{
Object *ob = user_data;
@@ -540,7 +540,7 @@ static void sculpt_draw_cb(
if (pbvh) {
BKE_pbvh_draw_cb(
pbvh, NULL, NULL, false,
- (void (*)(void *, Gwn_Batch *))draw_fn, shgroup);
+ (void (*)(void *, GPUBatch *))draw_fn, shgroup);
}
}
@@ -554,9 +554,9 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
#ifdef USE_GPU_SELECT
if (G.f & G_PICKSEL) {
if (shgroup->instance_count == shgroup->inst_selectid->vertex_len) {
- GWN_vertbuf_data_resize(shgroup->inst_selectid, shgroup->instance_count + 32);
+ GPU_vertbuf_data_resize(shgroup->inst_selectid, shgroup->instance_count + 32);
}
- GWN_vertbuf_attr_set(shgroup->inst_selectid, 0, shgroup->instance_count, &DST.select_id);
+ GPU_vertbuf_attr_set(shgroup->inst_selectid, 0, shgroup->instance_count, &DST.select_id);
}
#endif
@@ -565,9 +565,9 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
for (int i = 0; i < attr_len; ++i) {
if (shgroup->instance_count == shgroup->instance_vbo->vertex_len) {
- GWN_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32);
+ GPU_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32);
}
- GWN_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]);
+ GPU_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]);
}
shgroup->instance_count += 1;
@@ -601,25 +601,25 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
}
else {
/* Only here to support builtin shaders. This should not be used by engines. */
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_PERSINV], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_PERSINV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1);
+ drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2);
}
- shgroup->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
- shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
- shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
- shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW_INV);
- shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MVP);
- shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_NORMAL);
- shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL);
- shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO);
- shgroup->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE);
- shgroup->callid = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CALLID);
+ shgroup->model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
+ shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
+ shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW);
+ shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV);
+ shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
+ shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL);
+ shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_WORLDNORMAL);
+ shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO);
+ shgroup->eye = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_EYE);
+ shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID);
shgroup->matflag = 0;
if (shgroup->modelinverse > -1)
@@ -641,7 +641,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
}
static void drw_shgroup_instance_init(
- DRWShadingGroup *shgroup, GPUShader *shader, Gwn_Batch *batch, Gwn_VertFormat *format)
+ DRWShadingGroup *shgroup, GPUShader *shader, GPUBatch *batch, GPUVertFormat *format)
{
BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
BLI_assert(batch != NULL);
@@ -661,20 +661,20 @@ static void drw_shgroup_instance_init(
if (G.f & G_PICKSEL) {
/* Not actually used for rendering but alloced in one chunk.
* Plus we don't have to care about ownership. */
- static Gwn_VertFormat inst_select_format = {0};
+ static GPUVertFormat inst_select_format = {0};
if (inst_select_format.attr_len == 0) {
- GWN_vertformat_attr_add(&inst_select_format, "selectId", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- Gwn_Batch *batch_dummy; /* Not used */
+ GPUBatch *batch_dummy; /* Not used */
DRW_batching_buffer_request(DST.idatalist, &inst_select_format,
- GWN_PRIM_POINTS, shgroup,
+ GPU_PRIM_POINTS, shgroup,
&batch_dummy, &shgroup->inst_selectid);
}
#endif
}
static void drw_shgroup_batching_init(
- DRWShadingGroup *shgroup, GPUShader *shader, Gwn_VertFormat *format)
+ DRWShadingGroup *shgroup, GPUShader *shader, GPUVertFormat *format)
{
drw_shgroup_init(shgroup, shader);
@@ -683,12 +683,12 @@ static void drw_shgroup_batching_init(
#endif
BLI_assert(format != NULL);
- Gwn_PrimType type;
+ GPUPrimType type;
switch (shgroup->type) {
- case DRW_SHG_POINT_BATCH: type = GWN_PRIM_POINTS; break;
- case DRW_SHG_LINE_BATCH: type = GWN_PRIM_LINES; break;
- case DRW_SHG_TRIANGLE_BATCH: type = GWN_PRIM_TRIS; break;
- default: type = GWN_PRIM_NONE; BLI_assert(0); break;
+ case DRW_SHG_POINT_BATCH: type = GPU_PRIM_POINTS; break;
+ case DRW_SHG_LINE_BATCH: type = GPU_PRIM_LINES; break;
+ case DRW_SHG_TRIANGLE_BATCH: type = GPU_PRIM_TRIS; break;
+ default: type = GPU_PRIM_NONE; BLI_assert(0); break;
}
DRW_batching_buffer_request(DST.idatalist, format, type, shgroup,
@@ -697,13 +697,13 @@ static void drw_shgroup_batching_init(
#ifdef USE_GPU_SELECT
if (G.f & G_PICKSEL) {
/* Not actually used for rendering but alloced in one chunk. */
- static Gwn_VertFormat inst_select_format = {0};
+ static GPUVertFormat inst_select_format = {0};
if (inst_select_format.attr_len == 0) {
- GWN_vertformat_attr_add(&inst_select_format, "selectId", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- Gwn_Batch *batch; /* Not used */
+ GPUBatch *batch; /* Not used */
DRW_batching_buffer_request(DST.idatalist, &inst_select_format,
- GWN_PRIM_POINTS, shgroup,
+ GPU_PRIM_POINTS, shgroup,
&batch, &shgroup->inst_selectid);
}
#endif
@@ -730,7 +730,7 @@ static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass
shgroup->instance_vbo = NULL;
#endif
-#ifdef USE_GPU_SELECT
+#if !defined(NDEBUG) || defined(USE_GPU_SELECT)
shgroup->pass_parent = pass;
#endif
@@ -776,7 +776,9 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct
}
/* Color Ramps */
else if (input->tex) {
- DRW_shgroup_uniform_texture(grp, input->shadername, input->tex);
+ /* HACK : input->tex is a (GPUTexture **) in this case. */
+ GPUTexture *tex = *((GPUTexture **)input->tex);
+ DRW_shgroup_uniform_texture(grp, input->shadername, tex);
}
/* Floats */
else {
@@ -807,15 +809,15 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct
return grp;
}
-Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize)
+GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize)
{
- Gwn_VertFormat *format = MEM_callocN(sizeof(Gwn_VertFormat), "Gwn_VertFormat");
+ GPUVertFormat *format = MEM_callocN(sizeof(GPUVertFormat), "GPUVertFormat");
for (int i = 0; i < arraysize; ++i) {
- GWN_vertformat_attr_add(format, attribs[i].name,
- (attribs[i].type == DRW_ATTRIB_INT) ? GWN_COMP_I32 : GWN_COMP_F32,
+ GPU_vertformat_attr_add(format, attribs[i].name,
+ (attribs[i].type == DRW_ATTRIB_INT) ? GPU_COMP_I32 : GPU_COMP_F32,
attribs[i].components,
- (attribs[i].type == DRW_ATTRIB_INT) ? GWN_FETCH_INT : GWN_FETCH_FLOAT);
+ (attribs[i].type == DRW_ATTRIB_INT) ? GPU_FETCH_INT : GPU_FETCH_FLOAT);
}
return format;
}
@@ -835,7 +837,7 @@ DRWShadingGroup *DRW_shgroup_material_create(
}
DRWShadingGroup *DRW_shgroup_material_instance_create(
- struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob, Gwn_VertFormat *format)
+ struct GPUMaterial *material, DRWPass *pass, GPUBatch *geom, Object *ob, GPUVertFormat *format)
{
GPUPass *gpupass = GPU_material_get_pass(material);
DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
@@ -861,7 +863,7 @@ DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
if (shgroup) {
- /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */
+ /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */
drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
shgroup->type = DRW_SHG_TRIANGLE_BATCH;
shgroup->instance_count = tri_count * 3;
@@ -879,7 +881,7 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
}
DRWShadingGroup *DRW_shgroup_instance_create(
- struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom, Gwn_VertFormat *format)
+ struct GPUShader *shader, DRWPass *pass, GPUBatch *geom, GPUVertFormat *format)
{
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
shgroup->type = DRW_SHG_INSTANCE;
@@ -903,7 +905,7 @@ DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPas
}
DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(
- struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format)
+ struct GPUShader *shader, DRWPass *pass, GPUVertFormat *format)
{
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
shgroup->type = DRW_SHG_LINE_BATCH;
@@ -930,7 +932,7 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
#endif
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */
+ /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */
drw_shgroup_init(shgroup, shader);
shgroup->type = DRW_SHG_TRIANGLE_BATCH;
@@ -939,7 +941,7 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
return shgroup;
}
-DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, Gwn_VertBuf *tf_target)
+DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, GPUVertBuf *tf_target)
{
BLI_assert(tf_target != NULL);
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
@@ -953,7 +955,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
}
/* Specify an external batch instead of adding each attrib one by one. */
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch)
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch)
{
BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
BLI_assert(shgroup->instance_count == 0);
@@ -966,7 +968,7 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batc
/* Note: This WILL break if batch->verts[0] is destroyed and reallocated
* at the same adress. Bindings/VAOs would remain obsolete. */
//if (shgroup->instancing_geom->inst != batch->verts[0])
- GWN_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false);
+ GPU_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false);
#ifdef USE_GPU_SELECT
shgroup->override_selectid = DST.select_id;
@@ -998,6 +1000,23 @@ void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
shgroup->stencil_mask = mask;
}
+bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup)
+{
+ switch (shgroup->type) {
+ case DRW_SHG_NORMAL:
+ case DRW_SHG_FEEDBACK_TRANSFORM:
+ return shgroup->calls.first == NULL;
+ case DRW_SHG_POINT_BATCH:
+ case DRW_SHG_LINE_BATCH:
+ case DRW_SHG_TRIANGLE_BATCH:
+ case DRW_SHG_INSTANCE:
+ case DRW_SHG_INSTANCE_EXTERNAL:
+ return shgroup->instance_count == 0;
+ }
+ BLI_assert(!"Shading Group type not supported");
+ return true;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1009,7 +1028,7 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
{
DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
pass->state = state;
- if (G.debug_value > 20) {
+ if ((G.debug_value > 20) || (G.debug & G_DEBUG)) {
BLI_strncpy(pass->name, name, MAX_PASS_NAME);
}
@@ -1019,6 +1038,16 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
return pass;
}
+bool DRW_pass_is_empty(DRWPass *pass)
+{
+ for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+ if (!DRW_shgroup_is_empty(shgroup)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void DRW_pass_state_set(DRWPass *pass, DRWState state)
{
pass->state = state;
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 5957643d090..004e0137c66 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -34,6 +34,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "intern/gpu_shader_private.h"
#ifdef USE_GPU_SELECT
# include "ED_view3d.h"
@@ -49,6 +50,8 @@ void DRW_select_load_id(uint id)
}
#endif
+#define DEBUG_UBO_BINDING
+
struct GPUUniformBuffer *view_ubo;
/* -------------------------------------------------------------------- */
@@ -827,29 +830,29 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCallState *state)
}
static void draw_geometry_execute_ex(
- DRWShadingGroup *shgroup, Gwn_Batch *geom, uint start, uint count, bool draw_instance)
+ DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance)
{
/* Special case: empty drawcall, placement is done via shader, don't bind anything. */
/* TODO use DRW_CALL_PROCEDURAL instead */
if (geom == NULL) {
BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */
/* Shader is already bound. */
- GWN_draw_primitive(GWN_PRIM_TRIS, count);
+ GPU_draw_primitive(GPU_PRIM_TRIS, count);
return;
}
/* step 2 : bind vertex array & draw */
- GWN_batch_program_set_no_use(
+ GPU_batch_program_set_no_use(
geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
/* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
geom->program_in_use = true;
- GWN_batch_draw_range_ex(geom, start, count, draw_instance);
+ GPU_batch_draw_range_ex(geom, start, count, draw_instance);
geom->program_in_use = false; /* XXX hacking gawain */
}
-static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
+static void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom)
{
draw_geometry_execute_ex(shgroup, geom, 0, 0, false);
}
@@ -911,6 +914,54 @@ static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
slot_flags[bind_num] = bind_type;
}
+#ifndef NDEBUG
+/**
+ * Opengl specification is strict on buffer binding.
+ *
+ * " If any active uniform block is not backed by a
+ * sufficiently large buffer object, the results of shader
+ * execution are undefined, and may result in GL interruption or
+ * termination. " - Opengl 3.3 Core Specification
+ *
+ * For now we only check if the binding is correct. Not the size of
+ * the bound ubo.
+ *
+ * See T55475.
+ * */
+static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
+{
+ bool valid = true;
+# ifdef DEBUG_UBO_BINDING
+ /* Check that all active uniform blocks have a non-zero buffer bound. */
+ GLint program = 0;
+ GLint active_blocks = 0;
+
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &active_blocks);
+
+ for (uint i = 0; i < active_blocks; ++i) {
+ int binding = 0;
+ int buffer = 0;
+
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &binding);
+ glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, binding, &buffer);
+
+ if (buffer == 0) {
+ char blockname[64];
+ glGetActiveUniformBlockName(program, i, sizeof(blockname), NULL, blockname);
+
+ if (valid) {
+ printf("Trying to draw with missing UBO binding.\n");
+ valid = false;
+ }
+ printf("Pass : %s, Shader : %s, Block : %s\n", shgroup->pass_parent->name, shgroup->shader->name, blockname);
+ }
+ }
+# endif
+ return valid;
+}
+#endif
+
static void release_texture_slots(bool with_persist)
{
if (with_persist) {
@@ -1055,9 +1106,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
if (G.f & G_PICKSEL) { \
if (_shgroup->override_selectid == -1) { \
/* Hack : get vbo data without actually drawing. */ \
- Gwn_VertBufRaw raw; \
- GWN_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \
- select_id = GWN_vertbuf_raw_step(&raw); \
+ GPUVertBufRaw raw; \
+ GPU_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \
+ select_id = GPU_vertbuf_raw_step(&raw); \
switch (_shgroup->type) { \
case DRW_SHG_TRIANGLE_BATCH: _count = 3; break; \
case DRW_SHG_LINE_BATCH: _count = 2; break; \
@@ -1087,6 +1138,8 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
#endif
+ BLI_assert(ubo_bindings_validate(shgroup));
+
/* Rendering Calls */
if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) {
/* Replacing multiple calls with only one */
@@ -1168,7 +1221,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
call->generate.geometry_fn(shgroup, draw_geometry_execute, call->generate.user_data);
break;
case DRW_CALL_PROCEDURAL:
- GWN_draw_primitive(call->procedural.prim_type, call->procedural.vert_count);
+ GPU_draw_primitive(call->procedural.prim_type, call->procedural.vert_count);
break;
default:
BLI_assert(0);
diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c
index e4c0877b907..edeb6c07733 100644
--- a/source/blender/draw/intern/draw_manager_profiling.c
+++ b/source/blender/draw/intern/draw_manager_profiling.c
@@ -305,7 +305,7 @@ void DRW_stats_draw(rcti *rect)
/* Memory Stats */
uint tex_mem = GPU_texture_memory_usage_get();
- uint vbo_mem = GWN_vertbuf_get_memory_usage();
+ uint vbo_mem = GPU_vertbuf_get_memory_usage();
sprintf(stat_string, "GPU Memory");
draw_stat(rect, 0, v, stat_string, sizeof(stat_string));
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index b0aec4a7600..7aa40b0ce04 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -72,6 +72,7 @@ typedef struct DRWShaderCompiler {
ThreadMutex compilation_lock;
void *gl_context;
+ bool own_context;
int shaders_done; /* To compute progress. */
} DRWShaderCompiler;
@@ -146,7 +147,7 @@ static void drw_deferred_shader_compilation_free(void *custom_data)
BLI_spin_end(&comp->list_lock);
BLI_mutex_end(&comp->compilation_lock);
- if (comp->gl_context) {
+ if (comp->own_context) {
/* Only destroy if the job owns the context. */
WM_opengl_context_dispose(comp->gl_context);
}
@@ -189,8 +190,11 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
BLI_movelisttolist(&comp->queue, &old_comp->queue);
BLI_spin_unlock(&old_comp->list_lock);
/* Do not recreate context, just pass ownership. */
- comp->gl_context = old_comp->gl_context;
- old_comp->gl_context = NULL;
+ if (old_comp->gl_context) {
+ comp->gl_context = old_comp->gl_context;
+ old_comp->own_context = false;
+ comp->own_context = true;
+ }
}
BLI_addtail(&comp->queue, dsh);
@@ -199,6 +203,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
if (comp->gl_context == NULL) {
comp->gl_context = WM_opengl_context_create();
WM_opengl_context_activate(DST.gl_context);
+ comp->own_context = true;
}
WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free);
@@ -252,7 +257,7 @@ void DRW_deferred_shader_remove(GPUMaterial *mat)
GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
{
- return GPU_shader_create(vert, frag, geom, NULL, defines);
+ return GPU_shader_create(vert, frag, geom, NULL, defines, __func__);
}
GPUShader *DRW_shader_create_with_lib(
@@ -269,7 +274,7 @@ GPUShader *DRW_shader_create_with_lib(
geom_with_lib = BLI_string_joinN(lib, geom);
}
- sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines);
+ sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, __func__);
MEM_freeN(vert_with_lib);
MEM_freeN(frag_with_lib);
@@ -285,22 +290,22 @@ GPUShader *DRW_shader_create_with_transform_feedback(
const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count)
{
return GPU_shader_create_ex(vert, NULL, geom, NULL, defines, GPU_SHADER_FLAGS_NONE,
- prim_type, varying_names, varying_count);
+ prim_type, varying_names, varying_count, __func__);
}
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);
+ return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, __func__);
}
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);
+ return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, __func__);
}
GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
{
- return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines);
+ return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__);
}
GPUShader *DRW_shader_create_3D_depth_only(void)
@@ -346,7 +351,7 @@ GPUMaterial *DRW_shader_create_from_world(
if (mat == NULL) {
mat = GPU_material_from_nodetree(
scene, wo->nodetree, &wo->gpumaterial, engine_type, options,
- vert, geom, frag_lib, defines);
+ vert, geom, frag_lib, defines, wo->id.name);
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
@@ -368,7 +373,7 @@ GPUMaterial *DRW_shader_create_from_material(
if (mat == NULL) {
mat = GPU_material_from_nodetree(
scene, ma->nodetree, &ma->gpumaterial, engine_type, options,
- vert, geom, frag_lib, defines);
+ vert, geom, frag_lib, defines, ma->id.name);
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c
index 977374a00c5..b32853959c8 100644
--- a/source/blender/draw/intern/draw_manager_text.c
+++ b/source/blender/draw/intern/draw_manager_text.c
@@ -141,11 +141,11 @@ void DRW_text_cache_draw(DRWTextStore *dt, ARegion *ar)
}
float original_proj[4][4];
- gpuGetProjectionMatrix(original_proj);
+ GPU_matrix_projection_get(original_proj);
wmOrtho2_region_pixelspace(ar);
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
const int font_id = BLF_default();
@@ -173,8 +173,8 @@ void DRW_text_cache_draw(DRWTextStore *dt, ARegion *ar)
}
}
- gpuPopMatrix();
- gpuLoadProjectionMatrix(original_proj);
+ GPU_matrix_pop();
+ GPU_matrix_projection_set(original_proj);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_enable();
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 75a7d567d5c..95835a691a3 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -214,9 +214,9 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
glDepthMask(GL_FALSE); /* disable write in zbuffer */
#endif
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -253,7 +253,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
if (gridline_len == 0)
goto drawgrid_cleanup; /* nothing to draw */
- immBegin(GWN_PRIM_LINES, gridline_len * 2);
+ immBegin(GPU_PRIM_LINES, gridline_len * 2);
}
float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
@@ -306,7 +306,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
if (gridline_len == 0)
goto drawgrid_cleanup; /* nothing to draw */
- immBegin(GWN_PRIM_LINES, gridline_len * 2);
+ immBegin(GPU_PRIM_LINES, gridline_len * 2);
if (grids_to_draw == 2) {
UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
@@ -381,13 +381,13 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
uchar col_bg[3], col_grid_emphasise[3], col_grid_light[3];
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, vertex_len);
+ immBegin(GPU_PRIM_LINES, vertex_len);
/* draw normal grid lines */
UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
@@ -469,12 +469,12 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
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 */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
+ immBegin(GPU_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
if (show_axis_x) {
UI_make_axis_color(col_grid, col_axis, 'X');
@@ -548,8 +548,8 @@ void DRW_draw_grid(void)
*(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
drawgrid(&scene->unit, ar, v3d, &grid_unit);
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
}
else {
glDepthMask(GL_TRUE);
@@ -561,42 +561,33 @@ void DRW_draw_grid(void)
void DRW_draw_background(void)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
-
/* Just to make sure */
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilMask(0xFF);
- if ((draw_ctx->v3d->flag3 & V3D_SHOW_WORLD) &&
- (draw_ctx->scene->world != NULL))
- {
- const World *world = draw_ctx->scene->world;
- glClearColor(world->horr, world->horg, world->horb, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
- else if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
float m[4][4];
unit_m4(m);
/* Gradient background Color */
glDisable(GL_DEPTH_TEST);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
uchar col_hi[3], col_lo[3];
- gpuPushMatrix();
- gpuLoadIdentity();
- gpuLoadProjectionMatrix(m);
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ GPU_matrix_projection_set(m);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR_DITHER);
UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib3ubv(color, col_lo);
immVertex2f(pos, -1.0f, -1.0f);
immVertex2f(pos, 1.0f, -1.0f);
@@ -608,7 +599,7 @@ void DRW_draw_background(void)
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -689,10 +680,10 @@ void DRW_draw_cursor(void)
/* Draw lines */
if (is_aligned == false) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor3(TH_VIEW_OVERLAY);
- immBegin(GWN_PRIM_LINES, 12);
+ immBegin(GPU_PRIM_LINES, 12);
const float scale = ED_view3d_pixel_size_no_ui_scale(rv3d, cursor->location) * U.widget_unit;
@@ -724,14 +715,14 @@ void DRW_draw_cursor(void)
}
ED_region_pixelspace(ar);
- gpuTranslate2f(co[0] + 0.5f, co[1] + 0.5f);
- gpuScale2f(U.widget_unit, U.widget_unit);
+ GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
+ GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
- Gwn_Batch *cursor_batch = DRW_cache_cursor_get(is_aligned);
+ GPUBatch *cursor_batch = DRW_cache_cursor_get(is_aligned);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
- GWN_batch_program_set(cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
+ GPU_batch_program_set(cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
- GWN_batch_draw(cursor_batch);
+ GPU_batch_draw(cursor_batch);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h
index f88d49dfa96..8e8ddfef5a4 100644
--- a/source/blender/draw/modes/draw_mode_engines.h
+++ b/source/blender/draw/modes/draw_mode_engines.h
@@ -42,5 +42,6 @@ extern DrawEngineType draw_engine_particle_type;
extern DrawEngineType draw_engine_pose_type;
extern DrawEngineType draw_engine_sculpt_type;
extern DrawEngineType draw_engine_overlay_type;
+extern DrawEngineType draw_engine_gpencil_type;
#endif /* __DRAW_MODE_ENGINES_H__ */
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
index 285e703afbf..1e8293b5dbb 100644
--- a/source/blender/draw/modes/edit_armature_mode.c
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -60,7 +60,7 @@ typedef struct EDIT_ARMATURE_Data {
/* *********** STATIC *********** */
typedef struct EDIT_ARMATURE_PrivateData {
- char pad; /* UNUSED */
+ bool transparent_bones;
} EDIT_ARMATURE_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
@@ -69,15 +69,18 @@ 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;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
if (!stl->g_data) {
/* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
+ stl->g_data->transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
{
/* Solid bones */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
+ state |= (stl->g_data->transparent_bones) ? DRW_STATE_BLEND : DRW_STATE_WRITE_DEPTH;
psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
}
@@ -116,10 +119,12 @@ static void EDIT_ARMATURE_cache_init(void *vedata)
static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob)
{
bArmature *arm = ob->data;
- EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
if (ob->type == OB_ARMATURE) {
if (arm->edbo) {
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
+
DRWArmaturePasses passes = {
.bone_solid = psl->bone_solid,
.bone_outline = psl->bone_outline,
@@ -128,7 +133,7 @@ static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob)
.bone_axes = psl->bone_axes,
.relationship_lines = psl->relationship,
};
- DRW_shgroup_armature_edit(ob, passes);
+ DRW_shgroup_armature_edit(ob, passes, stl->g_data->transparent_bones);
}
}
}
@@ -136,22 +141,20 @@ static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob)
static void EDIT_ARMATURE_draw_scene(void *vedata)
{
EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
DRW_draw_pass(psl->bone_envelope);
- if (transparent_bones) {
- DRW_pass_state_add(psl->bone_solid, DRW_STATE_BLEND);
- DRW_pass_state_remove(psl->bone_solid, DRW_STATE_WRITE_DEPTH);
+ if (stl->g_data->transparent_bones) {
+ /* For performance reason, avoid blending on MS target. */
DRW_draw_pass(psl->bone_solid);
}
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl)
- if (!transparent_bones) {
+ if (!stl->g_data->transparent_bones) {
DRW_draw_pass(psl->bone_solid);
}
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index 50ce29b7b1a..c8b8f678ca6 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -244,7 +244,7 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
{
Curve *cu = ob->data;
/* Get geometry cache */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
geom = DRW_cache_curve_edge_wire_get(ob);
DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
index 870dd14d677..ca7903c555b 100644
--- a/source/blender/draw/modes/edit_lattice_mode.c
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -196,7 +196,7 @@ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_LATTICE) {
if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) {
/* Get geometry cache */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
geom = DRW_cache_lattice_wire_get(ob, true);
DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index 1e05b154974..67a424b8081 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -365,7 +365,7 @@ static void EDIT_MESH_cache_init(void *vedata)
const bool xray_enabled = ((draw_ctx->v3d->shading.flag & V3D_SHADING_XRAY) != 0) &&
- (draw_ctx->v3d->drawtype < OB_MATERIAL);
+ (draw_ctx->v3d->shading.type < OB_MATERIAL);
stl->g_data->do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0) || xray_enabled;
{
@@ -432,7 +432,7 @@ static void EDIT_MESH_cache_init(void *vedata)
DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo);
/* we need a full screen pass to combine the result */
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
psl->mix_occlude = DRW_pass_create(
"Mix Occluded Wires",
@@ -450,7 +450,7 @@ 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 Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter;
+ struct GPUBatch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter;
ToolSettings *tsettings = scene->toolsettings;
DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
@@ -477,7 +477,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
if (ob->type == OB_MESH) {
if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) {
@@ -512,7 +512,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
}
if (vnormals_do || lnormals_do) {
- struct Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts;
+ struct GPUBatch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts;
DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
if (vnormals_do) {
diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c
index 7074ba3d024..3c5d0dbf5a1 100644
--- a/source/blender/draw/modes/edit_surface_mode.c
+++ b/source/blender/draw/modes/edit_surface_mode.c
@@ -180,7 +180,7 @@ static void EDIT_SURFACE_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_MESH) {
/* Get geometry cache */
- struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
/* Add geom to a shading group */
DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index 5750dc8a0b9..f21715ef399 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -197,7 +197,7 @@ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
if (ob == draw_ctx->object_edit) {
const Curve *cu = ob->data;
/* Get geometry cache */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
if (cu->flag & CU_FAST) {
geom = DRW_cache_text_edge_wire_get(ob);
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 834a90ba3cf..e0a78c48a4c 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -37,6 +37,7 @@
#include "DNA_lightprobe_types.h"
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
+#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@@ -60,6 +61,7 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_draw.h"
#include "MEM_guardedalloc.h"
@@ -144,6 +146,9 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *cube;
DRWShadingGroup *circle;
DRWShadingGroup *sphere;
+ DRWShadingGroup *cylinder;
+ DRWShadingGroup *capsule_cap;
+ DRWShadingGroup *capsule_body;
DRWShadingGroup *cone;
DRWShadingGroup *single_arrow;
DRWShadingGroup *single_arrow_line;
@@ -161,6 +166,9 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *field_tube_limit;
DRWShadingGroup *field_cone_limit;
+ /* Grease Pencil */
+ DRWShadingGroup *gpencil_axes;
+
/* Speaker */
DRWShadingGroup *speaker;
@@ -254,9 +262,9 @@ typedef struct OBJECT_PrivateData {
static struct {
/* Instance Data format */
- struct Gwn_VertFormat *particle_format;
- struct Gwn_VertFormat *empty_image_format;
- struct Gwn_VertFormat *empty_image_wire_format;
+ struct GPUVertFormat *particle_format;
+ struct GPUVertFormat *empty_image_format;
+ struct GPUVertFormat *empty_image_wire_format;
/* fullscreen shaders */
GPUShader *outline_prepass_sh;
@@ -292,6 +300,8 @@ static struct {
struct GPUTexture *outlines_id_tx;
struct GPUTexture *outlines_color_tx;
struct GPUTexture *outlines_blur_tx;
+
+ ListBase smoke_domains;
} e_data = {NULL}; /* Engine data */
@@ -848,7 +858,7 @@ static void DRW_shgroup_empty_image(
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
});
- struct Gwn_Batch *geom = DRW_cache_image_plane_get();
+ struct GPUBatch *geom = DRW_cache_image_plane_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
e_data.object_empty_image_sh, psl->non_meshes, geom, e_data.empty_image_format);
DRW_shgroup_uniform_texture(grp, "image", tex);
@@ -868,7 +878,7 @@ static void DRW_shgroup_empty_image(
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
});
- struct Gwn_Batch *geom = DRW_cache_image_plane_wire_get();
+ struct GPUBatch *geom = DRW_cache_image_plane_wire_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
e_data.object_empty_image_wire_sh, psl->non_meshes, geom, e_data.empty_image_wire_format);
DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
@@ -904,7 +914,7 @@ static void OBJECT_cache_init(void *vedata)
OBJECT_PrivateData *g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool xray_enabled = ((draw_ctx->v3d->shading.flag & V3D_SHADING_XRAY) != 0) &&
- (draw_ctx->v3d->drawtype < OB_MATERIAL);
+ (draw_ctx->v3d->shading.type < OB_MATERIAL);
/* TODO : use dpi setting for enabling the second pass */
const bool do_outline_expand = false;
@@ -937,8 +947,8 @@ static void OBJECT_cache_init(void *vedata)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_POINT;
DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state);
- struct Gwn_Batch *sphere = DRW_cache_sphere_get();
- struct Gwn_Batch *quad = DRW_cache_quad_get();
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
+ struct GPUBatch *quad = DRW_cache_quad_get();
/* Cubemap */
g_data->lightprobes_cube_select = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_select);
@@ -957,7 +967,7 @@ static void OBJECT_cache_init(void *vedata)
{
DRWState state = DRW_STATE_WRITE_COLOR;
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
/* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */
float alphaOcclu = (xray_enabled) ? 1.0f : 0.35f;
/* Reminder : bool uniforms need to be 4 bytes. */
@@ -997,7 +1007,7 @@ static void OBJECT_cache_init(void *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state);
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
GPUTexture **outline_tx = (do_outline_expand) ? &e_data.outlines_blur_tx : &e_data.outlines_color_tx;
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_aa_sh, psl->outlines_resolve);
@@ -1011,7 +1021,7 @@ static void OBJECT_cache_init(void *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
psl->grid = DRW_pass_create("Infinite Grid Pass", state);
- struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
static float mat[4][4];
unit_m4(mat);
@@ -1072,7 +1082,7 @@ static void OBJECT_cache_init(void *vedata)
{
/* Non Meshes Pass (Camera, empties, lamps ...) */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
DRWState state =
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
@@ -1084,7 +1094,7 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_plain_axes_get();
stl->g_data->plain_axes = shgroup_instance(psl->non_meshes, geom);
- geom = DRW_cache_cube_get();
+ geom = DRW_cache_empty_cube_get();
stl->g_data->cube = shgroup_instance(psl->non_meshes, geom);
geom = DRW_cache_circle_get();
@@ -1093,6 +1103,15 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_empty_sphere_get();
stl->g_data->sphere = shgroup_instance(psl->non_meshes, geom);
+ geom = DRW_cache_empty_cylinder_get();
+ stl->g_data->cylinder = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_capsule_cap_get();
+ stl->g_data->capsule_cap = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_capsule_body_get();
+ stl->g_data->capsule_body = shgroup_instance(psl->non_meshes, geom);
+
geom = DRW_cache_empty_cone_get();
stl->g_data->cone = shgroup_instance(psl->non_meshes, geom);
@@ -1124,6 +1143,10 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_screenspace_circle_get();
stl->g_data->field_curve_sta = shgroup_instance_screen_aligned(psl->non_meshes, geom);
+ /* Grease Pencil */
+ geom = DRW_cache_gpencil_axes_get();
+ stl->g_data->gpencil_axes = shgroup_instance(psl->non_meshes, geom);
+
/* Speaker */
geom = DRW_cache_speaker_get();
stl->g_data->speaker = shgroup_instance(psl->non_meshes, geom);
@@ -1162,7 +1185,7 @@ static void OBJECT_cache_init(void *vedata)
stl->g_data->camera_mist_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
/* Texture Space */
- geom = DRW_cache_cube_get();
+ geom = DRW_cache_empty_cube_get();
stl->g_data->texspace = shgroup_instance(psl->non_meshes, geom);
}
@@ -1209,7 +1232,7 @@ static void OBJECT_cache_init(void *vedata)
/* TODO
* for now we create multiple times the same VBO with only lamp center coordinates
* but ideally we would only create it once */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
/* start with buflimit because we don't want stipples */
geom = DRW_cache_single_line_get();
@@ -1261,7 +1284,7 @@ static void OBJECT_cache_init(void *vedata)
{
/* -------- STIPPLES ------- */
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
/* Relationship Lines */
stl->g_data->relationship_lines = shgroup_dynlines_dashed_uniform_color(psl->non_meshes, ts.colorWire);
@@ -1665,7 +1688,7 @@ static void DRW_shgroup_forcefield(OBJECT_StorageList *stl, Object *ob, ViewLaye
}
break;
case PFIELD_GUIDE:
- if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
+ if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) {
where_on_path(ob, 0.0f, pd->drawvec1, tmp, NULL, NULL, NULL);
where_on_path(ob, 1.0f, pd->drawvec2, tmp, NULL, NULL, NULL);
}
@@ -1706,7 +1729,7 @@ static void DRW_shgroup_forcefield(OBJECT_StorageList *stl, Object *ob, ViewLaye
DRW_shgroup_call_dynamic_add(stl->g_data->field_vortex, color, &pd->drawvec1, ob->obmat);
break;
case PFIELD_GUIDE:
- if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
+ if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) {
DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_sta, color, &pd->f_strength, ob->obmat);
DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->f_strength, ob->obmat);
}
@@ -1743,6 +1766,93 @@ static void DRW_shgroup_forcefield(OBJECT_StorageList *stl, Object *ob, ViewLaye
}
}
+static void DRW_shgroup_volume_extra(
+ OBJECT_PassList *psl, OBJECT_StorageList *stl,
+ Object *ob, ViewLayer *view_layer, Scene *scene, ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ SmokeDomainSettings *sds = smd->domain;
+ float *color;
+ float one = 1.0f;
+
+ if (sds == NULL) {
+ return;
+ }
+
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ /* Small cube showing voxel size. */
+ float voxel_cubemat[4][4] = {{0.0f}};
+ voxel_cubemat[0][0] = 1.0f / (float)sds->res[0];
+ voxel_cubemat[1][1] = 1.0f / (float)sds->res[1];
+ voxel_cubemat[2][2] = 1.0f / (float)sds->res[2];
+ voxel_cubemat[3][0] = voxel_cubemat[3][1] = voxel_cubemat[3][2] = -1.0f;
+ voxel_cubemat[3][3] = 1.0f;
+ translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f);
+ mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, voxel_cubemat);
+
+ /* Don't show smoke before simulation starts, this could be made an option in the future. */
+ if (!sds->draw_velocity || !sds->fluid || CFRA < sds->point_cache[0]->startframe) {
+ return;
+ }
+
+ const bool use_needle = (sds->vector_draw_type == VECTOR_DRAW_NEEDLE);
+ int line_count = (use_needle) ? 6 : 1;
+ int slice_axis = -1;
+ line_count *= sds->res[0] * sds->res[1] * sds->res[2];
+
+ if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED &&
+ sds->axis_slice_method == AXIS_SLICE_SINGLE)
+ {
+ float invviewmat[4][4];
+ DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+
+ const int axis = (sds->slice_axis == SLICE_AXIS_AUTO)
+ ? axis_dominant_v3_single(invviewmat[2])
+ : sds->slice_axis - 1;
+ slice_axis = axis;
+ line_count /= sds->res[axis];
+ }
+
+ GPU_create_smoke_velocity(smd);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(volume_velocity_shader_get(use_needle), psl->non_meshes);
+ DRW_shgroup_uniform_texture(grp, "velocityX", sds->tex_velocity_x);
+ DRW_shgroup_uniform_texture(grp, "velocityY", sds->tex_velocity_y);
+ DRW_shgroup_uniform_texture(grp, "velocityZ", sds->tex_velocity_z);
+ DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth);
+ DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis);
+ DRW_shgroup_call_procedural_lines_add(grp, line_count, ob->obmat);
+
+ BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
+}
+
+static void volumes_free_smoke_textures(void)
+{
+ /* Free Smoke Textures after rendering */
+ /* XXX This is a waste of processing and GPU bandwidth if nothing
+ * is updated. But the problem is since Textures are stored in the
+ * modifier we don't want them to take precious VRAM if the
+ * modifier is not used for display. We should share them for
+ * all viewport in a redraw at least. */
+ for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
+ SmokeModifierData *smd = (SmokeModifierData *)link->data;
+ GPU_free_smoke(smd);
+ }
+ BLI_freelistN(&e_data.smoke_domains);
+}
+
+static void DRW_shgroup_gpencil(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ float *color;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->gpencil_axes, color, &ob->empty_drawsize, ob->obmat);
+}
+
static void DRW_shgroup_speaker(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
{
float *color;
@@ -1829,9 +1939,9 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
DRW_shgroup_call_procedural_points_add(grp, prb_data->cell_count, NULL);
}
else if (prb->type == LIGHTPROBE_TYPE_CUBE) {
- prb_data->draw_size = prb->data_draw_size * 0.1f;
- unit_m4(prb_data->probe_cube_mat);
- copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]);
+ // prb_data->draw_size = prb->data_draw_size * 0.1f;
+ // unit_m4(prb_data->probe_cube_mat);
+ // copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]);
DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp(stl, theme_id);
/* TODO remove or change the drawing of the cube probes. Theses line draws nothing on purpose
@@ -2081,6 +2191,82 @@ static void DRW_shgroup_texture_space(OBJECT_StorageList *stl, Object *ob, int t
DRW_shgroup_call_dynamic_add(stl->g_data->texspace, color, &one, tmp);
}
+static void DRW_shgroup_bounds(OBJECT_StorageList *stl, Object *ob, int theme_id)
+{
+ float color[4], center[3], size[3], tmp[4][4], final_mat[4][4], one = 1.0f;
+ BoundBox bb_local;
+
+ if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) {
+ return;
+ }
+
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+
+ if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT,
+ OB_MBALL, OB_ARMATURE, OB_LATTICE))
+ {
+ const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
+ bb = &bb_local;
+ BKE_boundbox_init_from_minmax(bb, min, max);
+ }
+
+ UI_GetThemeColor4fv(theme_id, color);
+ BKE_boundbox_calc_center_aabb(bb, center);
+ BKE_boundbox_calc_size_aabb(bb, size);
+
+ switch (ob->boundtype) {
+ case OB_BOUND_BOX:
+ size_to_mat4(tmp, size);
+ copy_v3_v3(tmp[3], center);
+ mul_m4_m4m4(tmp, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, tmp);
+ break;
+ case OB_BOUND_SPHERE:
+ size[0] = max_fff(size[0], size[1], size[2]);
+ size[1] = size[2] = size[0];
+ size_to_mat4(tmp, size);
+ copy_v3_v3(tmp[3], center);
+ mul_m4_m4m4(tmp, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &one, tmp);
+ break;
+ case OB_BOUND_CYLINDER:
+ size[0] = max_ff(size[0], size[1]);
+ size[1] = size[0];
+ size_to_mat4(tmp, size);
+ copy_v3_v3(tmp[3], center);
+ mul_m4_m4m4(tmp, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->cylinder, color, &one, tmp);
+ break;
+ case OB_BOUND_CONE:
+ size[0] = max_ff(size[0], size[1]);
+ size[1] = size[0];
+ size_to_mat4(tmp, size);
+ copy_v3_v3(tmp[3], center);
+ /* Cone batch has base at 0 and is pointing towards +Y. */
+ swap_v3_v3(tmp[1], tmp[2]);
+ tmp[3][2] -= size[2];
+ mul_m4_m4m4(tmp, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->cone, color, &one, tmp);
+ break;
+ case OB_BOUND_CAPSULE:
+ size[0] = max_ff(size[0], size[1]);
+ size[1] = size[0];
+ scale_m4_fl(tmp, size[0]);
+ copy_v2_v2(tmp[3], center);
+ tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]);
+ mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->capsule_cap, color, &one, final_mat);
+ negate_v3(tmp[2]);
+ tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]);
+ mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->capsule_cap, color, &one, final_mat);
+ tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f);
+ mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ DRW_shgroup_call_dynamic_add(stl->g_data->capsule_body, color, &one, final_mat);
+ break;
+ }
+}
+
static void OBJECT_cache_populate_particles(Object *ob,
OBJECT_PassList *psl)
{
@@ -2099,7 +2285,7 @@ static void OBJECT_cache_populate_particles(Object *ob,
unit_m4(mat);
if (draw_as != PART_DRAW_PATH) {
- struct Gwn_Batch *geom = DRW_cache_particles_get_dots(ob, psys);
+ struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys);
DRWShadingGroup *shgrp = NULL;
static int screen_space[2] = {0, 1};
static float def_prim_col[3] = {0.5f, 0.5f, 0.5f};
@@ -2162,7 +2348,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
+ Scene *scene = draw_ctx->scene;
View3D *v3d = draw_ctx->v3d;
+ ModifierData *md = NULL;
int theme_id = TH_UNDEFINED;
/* Handle particles first in case the emitter itself shouldn't be rendered. */
@@ -2174,15 +2362,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
return;
}
- bool do_outlines = (draw_ctx->v3d->flag & V3D_SELECT_OUTLINE) && ((ob->base_flag & BASE_SELECTED) != 0);
- bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
+ const bool do_outlines = (draw_ctx->v3d->flag & V3D_SELECT_OUTLINE) && ((ob->base_flag & BASE_SELECTED) != 0);
+ const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
const bool hide_object_extra = (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) != 0;
if (do_outlines) {
if ((ob != draw_ctx->object_edit) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) {
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
const bool xray_enabled = ((v3d->shading.flag & V3D_SHADING_XRAY) != 0) &&
- (v3d->drawtype < OB_MATERIAL);
+ (v3d->shading.type < OB_MATERIAL);
if (xray_enabled) {
geom = DRW_cache_object_edge_detection_get(ob, NULL);
}
@@ -2208,7 +2396,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (ob != draw_ctx->object_edit) {
Mesh *me = ob->data;
if (me->totedge == 0) {
- struct Gwn_Batch *geom = DRW_cache_mesh_verts_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_verts_get(ob);
if (geom) {
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
@@ -2219,7 +2407,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
}
else {
- struct Gwn_Batch *geom = DRW_cache_mesh_loose_edges_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob);
if (geom) {
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
@@ -2240,7 +2428,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (hide_object_extra) {
break;
}
- struct Gwn_Batch *geom = DRW_cache_lattice_wire_get(ob, false);
+ struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
@@ -2256,7 +2444,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (hide_object_extra) {
break;
}
- struct Gwn_Batch *geom = DRW_cache_curve_edge_wire_get(ob);
+ struct GPUBatch *geom = DRW_cache_curve_edge_wire_get(ob);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
@@ -2290,6 +2478,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
DRW_shgroup_empty(stl, psl, ob, view_layer);
break;
+ case OB_GPENCIL:
+ DRW_shgroup_gpencil(stl, ob, view_layer);
+ break;
case OB_SPEAKER:
if (hide_object_extra) {
break;
@@ -2333,8 +2524,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
/* don't show object extras in set's */
if ((ob->base_flag & (BASE_FROM_SET | BASE_FROMDUPLI)) == 0) {
-
- DRW_shgroup_object_center(stl, ob, view_layer, v3d);
+ if ((draw_ctx->object_mode & OB_MODE_ALL_PAINT) == 0) {
+ DRW_shgroup_object_center(stl, ob, view_layer, v3d);
+ }
if (show_relations) {
DRW_shgroup_relationship_lines(stl, ob);
@@ -2359,6 +2551,17 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if ((ob->dtx & OB_TEXSPACE) && ELEM(ob->type, OB_MESH, OB_CURVE, OB_MBALL)) {
DRW_shgroup_texture_space(stl, ob, theme_id);
}
+
+ if (ob->dtx & OB_DRAWBOUNDOX) {
+ DRW_shgroup_bounds(stl, ob, theme_id);
+ }
+
+ if ((md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
+ (((SmokeModifierData *)md)->domain != NULL))
+ {
+ DRW_shgroup_volume_extra(psl, stl, ob, view_layer, scene, md);
+ }
}
}
@@ -2458,6 +2661,8 @@ static void OBJECT_draw_scene(void *vedata)
BLI_ghash_free(stl->g_data->image_plane_map, NULL, MEM_freeN);
stl->g_data->image_plane_map = NULL;
}
+
+ volumes_free_smoke_textures();
}
static const DrawEngineDataSize OBJECT_data_size = DRW_VIEWPORT_DATA_SIZE(OBJECT_Data);
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index a67c7ffb131..e3c986bde5a 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -175,7 +175,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
return;
if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat);
}
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 85cff28b313..cf8e520323e 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -227,6 +227,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
DRW_shgroup_uniform_texture(grp, "image", tex);
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
stl->g_data->shgroup_image_array[i] = grp;
}
else {
@@ -259,6 +260,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
}
{
@@ -293,9 +295,9 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if (use_surface) {
if (me->mloopuv != NULL) {
if (use_material_slots) {
- struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
+ struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
if ((me->totcol == 0) || (geom_array == NULL)) {
- struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
ok = true;
}
@@ -312,7 +314,7 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
}
}
else {
- struct Gwn_Batch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
if (geom && stl->g_data->shgroup_image_array[0]) {
DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
ok = true;
@@ -321,7 +323,7 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
}
if (!ok) {
- struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
}
}
@@ -329,7 +331,7 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
/* Face Mask */
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
if (use_face_sel) {
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
/* Note: ideally selected faces wouldn't show interior wire. */
const bool use_wire = true;
geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index 9cf6ea52d33..236f76367d4 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -36,6 +36,8 @@
#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
+#include "DEG_depsgraph_query.h"
+
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
extern struct GlobalsUboStorage ts; /* draw_common.c */
@@ -125,6 +127,7 @@ static void PAINT_VERTEX_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
}
{
@@ -146,11 +149,13 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
const View3D *v3d = draw_ctx->v3d;
if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) {
+ /* We're always painting on original, display original data. */
+ ob = DEG_get_original_object(ob);
const Mesh *me = ob->data;
const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0;
const bool use_surface = v3d->overlay.vertex_paint_mode_opacity != 0.0f;
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
if (use_surface) {
geom = DRW_cache_mesh_surface_vert_colors_get(ob);
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
index 14fae743d8c..3bbe8911491 100644
--- a/source/blender/draw/modes/paint_weight_mode.c
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -154,6 +154,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
}
{
@@ -173,6 +174,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.vert_overlay_shader, psl->vert_overlay);
+ DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", globals_ubo);
}
}
@@ -190,7 +192,7 @@ static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob)
const bool use_surface = v3d->overlay.weight_paint_mode_opacity != 0.0f;
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
- struct Gwn_Batch *geom;
+ struct GPUBatch *geom;
if (use_surface) {
geom = DRW_cache_mesh_surface_weights_get(ob);
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
index 19c3ddd4b50..f4879483540 100644
--- a/source/blender/draw/modes/particle_mode.c
+++ b/source/blender/draw/modes/particle_mode.c
@@ -148,17 +148,17 @@ static void particle_edit_cache_populate(void *vedata,
const DRWContextState *draw_ctx = DRW_context_state_get();
ParticleEditSettings *pset = PE_settings(draw_ctx->scene);
{
- struct Gwn_Batch *strands =
+ struct GPUBatch *strands =
DRW_cache_particles_get_edit_strands(object, psys, edit);
DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL);
}
if (pset->selectmode == SCE_SELECT_POINT) {
- struct Gwn_Batch *points =
+ struct GPUBatch *points =
DRW_cache_particles_get_edit_inner_points(object, psys, edit);
DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL);
}
if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) {
- struct Gwn_Batch *points =
+ struct GPUBatch *points =
DRW_cache_particles_get_edit_tip_points(object, psys, edit);
DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL);
}
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
index 57efc65542c..7a4abcac179 100644
--- a/source/blender/draw/modes/pose_mode.c
+++ b/source/blender/draw/modes/pose_mode.c
@@ -75,6 +75,7 @@ typedef struct POSE_PrivateData {
DRWShadingGroup *bone_selection_invert_shgrp;
float blend_color[4];
float blend_color_invert[4];
+ bool transparent_bones;
} POSE_PrivateData; /* Transient data */
static struct {
@@ -112,9 +113,10 @@ static void POSE_cache_init(void *vedata)
if (!stl->g_data) {
/* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
POSE_PrivateData *ppd = stl->g_data;
+ ppd->transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
{
/* Solid bones */
@@ -195,7 +197,7 @@ static bool POSE_is_driven_by_active_armature(Object *ob)
static void POSE_cache_populate(void *vedata, Object *ob)
{
POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
- POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+ POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
/* In the future this will allow us to implement face gizmos,
@@ -214,20 +216,20 @@ static void POSE_cache_populate(void *vedata, Object *ob)
.bone_axes = psl->bone_axes,
.relationship_lines = psl->relationship,
};
- DRW_shgroup_armature_pose(ob, passes);
+ DRW_shgroup_armature_pose(ob, passes, ppd->transparent_bones);
}
}
else if (ob->type == OB_MESH &&
!DRW_state_is_select() &&
POSE_is_bone_selection_overlay_active())
{
- struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
if (POSE_is_driven_by_active_armature(ob)) {
- DRW_shgroup_call_object_add(stl->g_data->bone_selection_shgrp, geom, ob);
+ DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob);
}
else {
- DRW_shgroup_call_object_add(stl->g_data->bone_selection_invert_shgrp, geom, ob);
+ DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob);
}
}
}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl
index b20656ff326..78b29296601 100644
--- a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl
+++ b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl
@@ -1,4 +1,6 @@
+uniform float alpha = 0.6;
+
flat in vec3 finalStateColor;
flat in vec3 finalBoneColor;
in vec3 normalView;
@@ -12,5 +14,5 @@ void main()
float n = normalize(normalView).z;
float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0);
fragColor.rgb = mix(finalStateColor, finalBoneColor, fac);
- fragColor.a = 0.6; /* Hardcoded transparency factor. */
+ fragColor.a = alpha;
}
diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl
index 89f4d97f29b..45748bf5644 100644
--- a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl
+++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl
@@ -1,9 +1,11 @@
+uniform float alpha = 0.6;
+
in vec4 finalColor;
out vec4 fragColor;
void main()
{
- fragColor = vec4(finalColor.rgb, 0.6); /* Hardcoded transparency factor. */
+ fragColor = vec4(finalColor.rgb, alpha);
}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl
index 3c80f629d79..a0fdd55931f 100644
--- a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl
+++ b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl
@@ -3,6 +3,7 @@
uniform mat4 ViewMatrixInverse;
uniform mat4 ProjectionMatrix;
+uniform float alpha = 0.4;
flat in vec3 finalStateColor;
flat in vec3 finalBoneColor;
@@ -73,8 +74,7 @@ void main()
float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25;
dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */
- /* Hardcoded transparency factor. Less than shape to be less distractive. */
- fragColor = vec4(fragColor.rgb + dither, 0.4);
+ fragColor = vec4(fragColor.rgb + dither, alpha);
t /= ray_len;
gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z);
diff --git a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
new file mode 100644
index 00000000000..574c434920e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
@@ -0,0 +1,115 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform sampler3D velocityX;
+uniform sampler3D velocityY;
+uniform sampler3D velocityZ;
+uniform float displaySize = 1.0;
+uniform float slicePosition;
+uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+
+flat out vec4 finalColor;
+
+const vec3 corners[4] = vec3[4](
+ vec3(0.0, 0.2, -0.5),
+ vec3(-0.2 * 0.866, -0.2 * 0.5, -0.5),
+ vec3(0.2 * 0.866, -0.2 * 0.5, -0.5),
+ vec3(0.0, 0.0, 0.5)
+);
+
+const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3);
+
+/* Straight Port from BKE_defvert_weight_to_rgb()
+ * TODO port this to a color ramp. */
+vec3 weight_to_color(float weight)
+{
+ vec3 r_rgb = vec3(0.0);
+ float blend = ((weight / 2.0) + 0.5);
+
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb.g = blend * weight * 4.0;
+ r_rgb.b = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb.g = blend;
+ r_rgb.b = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb.r = blend * ((weight - 0.50) * 4.0);
+ r_rgb.g = blend;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb.r = blend;
+ r_rgb.g = blend * (1.0 - ((weight - 0.75) * 4.0));
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb = vec3(1.0, 0.0, 1.0);
+ }
+
+ return r_rgb;
+}
+
+mat3 rotation_from_vector(vec3 v)
+{
+ /* Add epsilon to avoid NaN. */
+ vec3 N = normalize(v + 1e-8);
+ vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0);
+ vec3 T = normalize(cross(UpVector, N));
+ vec3 B = cross(N, T);
+ return mat3(T, B, N);
+}
+
+void main()
+{
+#ifdef USE_NEEDLE
+ int cell = gl_VertexID / 12;
+#else
+ int cell = gl_VertexID / 2;
+#endif
+
+ ivec3 volume_size = textureSize(velocityX, 0);
+ float voxel_size = 1.0 / float(max(max(volume_size.x, volume_size.y), volume_size.z));
+
+ ivec3 cell_ofs = ivec3(0);
+ ivec3 cell_div = volume_size;
+ if (sliceAxis == 0) {
+ cell_ofs.x = int(slicePosition * float(volume_size.x));
+ cell_div.x = 1;
+ }
+ else if (sliceAxis == 1) {
+ cell_ofs.y = int(slicePosition * float(volume_size.y));
+ cell_div.y = 1;
+ }
+ else if (sliceAxis == 2) {
+ cell_ofs.z = int(slicePosition * float(volume_size.z));
+ cell_div.z = 1;
+ }
+
+ ivec3 cell_co;
+ cell_co.x = cell % cell_div.x;
+ cell_co.y = (cell / cell_div.x) % cell_div.y;
+ cell_co.z = cell / (cell_div.x * cell_div.y);
+ cell_co += cell_ofs;
+
+ vec3 pos = (vec3(cell_co) + 0.5) / vec3(volume_size);
+ pos = pos * 2.0 - 1.0;
+
+ vec3 velocity;
+ velocity.x = texelFetch(velocityX, cell_co, 0).r;
+ velocity.y = texelFetch(velocityY, cell_co, 0).r;
+ velocity.z = texelFetch(velocityZ, cell_co, 0).r;
+
+ finalColor = vec4(weight_to_color(length(velocity)), 1.0);
+
+#ifdef USE_NEEDLE
+ mat3 rot_mat = rotation_from_vector(velocity);
+ vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]];
+ pos += rotated_pos * length(velocity) * displaySize * voxel_size;
+#else
+ pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size;
+#endif
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index c70790e0550..79b7c7988fd 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -64,6 +64,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_gpencil.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_nla.h"
@@ -146,7 +147,7 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
@@ -235,7 +236,7 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
@@ -661,6 +662,8 @@ static int acf_object_icon(bAnimListElem *ale)
return ICON_OUTLINER_OB_SURFACE;
case OB_EMPTY:
return ICON_OUTLINER_OB_EMPTY;
+ case OB_GPENCIL:
+ return ICON_OUTLINER_OB_GREASEPENCIL;
default:
return ICON_OBJECT_DATA;
}
@@ -3868,7 +3871,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* for F-Curves, draw color-preview of curve behind checkbox */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3924,7 +3927,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* draw red underline if channel is disabled */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3933,7 +3936,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
GPU_line_width(2.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, (float)offset, yminc);
immVertex2f(pos, (float)v2d->cur.xmax, yminc);
immEnd();
@@ -3952,7 +3955,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
short draw_sliders = 0;
float ymin_ofs = 0.0f;
float color[3];
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -4048,8 +4051,16 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
return;
}
- if (ale_setting->type == ANIMTYPE_GPLAYER)
+ if (ale_setting->type == ANIMTYPE_GPLAYER) {
+ /* draw cache updates for settings that affect the visible strokes */
+ if (setting == ACHANNEL_SETTING_VISIBLE) {
+ bGPdata *gpd = (bGPdata *)ale_setting->id;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+
+ /* UI updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+ }
/* tag copy-on-write flushing (so that the settings will have an effect) */
if (ale_setting->id) {
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index d768be49ad4..3f22ac6fa3a 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -1727,8 +1727,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
bGPDlayer *gpl = (bGPDlayer *)ale->data;
/* try to delete the layer's data and the layer itself */
- BKE_gpencil_free_frames(gpl);
- BLI_freelinkN(&gpd->layers, gpl);
+ BKE_gpencil_layer_delete(gpd, gpl);
break;
}
case ANIMTYPE_MASKLAYER:
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index adb5a10c19d..898c8b6464a 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -435,6 +435,16 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
ANIM_list_elem_update(ac->bmain, ac->scene, ale);
}
}
+ else if (ale->update) {
+#if 0
+ if (G.debug & G_DEBUG) {
+ printf("%s: Unhandled animchannel updates (%d) for type=%d (%p)\n",
+ __func__, ale->update, ale->type, ale->data);
+ }
+#endif
+ /* Prevent crashes in cases where it can't be handled */
+ ale->update = 0;
+ }
BLI_assert(ale->update == 0);
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 51ba7d9c269..05ea3fd6314 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -87,8 +87,8 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
/* because the frame number text is subject to the same scaling as the contents of the view */
UI_view2d_scale_get(v2d, &xscale, NULL);
- gpuPushMatrix();
- gpuScale2f(1.0f / xscale, 1.0f);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
/* get timecode string
* - padding on str-buf passed so that it doesn't sit on the frame indicator
@@ -128,7 +128,7 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
numstr, col);
/* restore view transform */
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* General call for drawing current frame indicator in animation editor */
@@ -141,15 +141,15 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
GPU_line_width((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* Draw a light green line to indicate current frame */
immUniformThemeColor(TH_CFRAME);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
immVertex2f(pos, x, v2d->cur.ymax);
immEnd();
@@ -170,8 +170,8 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_ANIM_ACTIVE, -25, -30);
@@ -203,8 +203,8 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d)
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
@@ -222,7 +222,7 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d)
/* thin lines where the actual frames are */
immUniformThemeColorShade(TH_BACK, -60);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
@@ -552,11 +552,11 @@ static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prev
/* populate tree with keyframe nodes */
scene_to_keylist(&ads, scene, &keys, NULL);
- gpencil_to_keylist(&ads, scene->gpd, &keys);
+ gpencil_to_keylist(&ads, scene->gpd, &keys, false);
if (ob) {
ob_to_keylist(&ads, ob, &keys, NULL);
- gpencil_to_keylist(&ads, ob->gpd, &keys);
+ gpencil_to_keylist(&ads, ob->data, &keys, false);
}
if (mask) {
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index c59d24bbdf8..54590c5f66c 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -72,6 +72,7 @@
#include "DNA_speaker_types.h"
#include "DNA_world_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
#include "DNA_layer_types.h"
@@ -1660,7 +1661,7 @@ static size_t animdata_filter_gpencil_data(ListBase *anim_data, bDopeSheet *ads,
*/
if (filter_mode & ANIMFILTER_ANIMDATA) {
/* just add GPD as a channel - this will add everything needed */
- ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, NULL);
+ ANIMCHANNEL_NEW_CHANNEL(gpd, ANIMTYPE_GPDATABLOCK, gpd);
}
else {
ListBase tmp_data = {NULL, NULL};
@@ -1711,7 +1712,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
/* Objects in the scene */
for (base = view_layer->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) {
+ if (base->object && (base->object->type == OB_GPENCIL)) {
Object *ob = base->object;
/* firstly, check if object can be included, by the following factors:
@@ -1748,7 +1749,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
/* finally, include this object's grease pencil datablock */
/* XXX: Should we store these under expanders per item? */
- items += animdata_filter_gpencil_data(anim_data, ads, ob->gpd, filter_mode);
+ items += animdata_filter_gpencil_data(anim_data, ads, ob->data, filter_mode);
}
}
}
@@ -2613,8 +2614,10 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
}
/* grease pencil */
- if ((ob->gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
- tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->gpd, filter_mode);
+ if ((ob->type == OB_GPENCIL) &&
+ (ob->data) && !(ads->filterflag & ADS_FILTER_NOGPENCIL))
+ {
+ tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->data, filter_mode);
}
}
END_ANIMFILTER_SUBCHANNELS;
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index c5f7782dcee..e1f4092c494 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -400,8 +400,8 @@ static void draw_marker(
if (flag & DRAW_MARKERS_LINES)
#endif
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -418,7 +418,7 @@ static void draw_marker(
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, xpos + 0.5f, 12.0f);
immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
immEnd();
@@ -486,7 +486,7 @@ void ED_markers_draw(const bContext *C, int flag)
v2d = UI_view2d_fromcontext(C);
if (flag & DRAW_MARKERS_MARGIN) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
const unsigned char shade[4] = {0, 0, 0, 16};
@@ -505,8 +505,8 @@ void ED_markers_draw(const bContext *C, int flag)
/* 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);
- gpuPushMatrix();
- gpuScale2f(1.0f / xscale, 1.0f);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(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;
@@ -529,7 +529,7 @@ void ED_markers_draw(const bContext *C, int flag)
}
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* ************************ Marker Wrappers API ********************* */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 5f6b299c617..45fe7233f94 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -45,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_sound.h"
+#include "BKE_scene.h"
#include "UI_view2d.h"
@@ -98,8 +99,13 @@ static void change_frame_apply(bContext *C, wmOperator *op)
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)) {
- frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ if (do_snap) {
+ if (CTX_wm_space_seq(C)) {
+ frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ }
+ else {
+ frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
+ }
}
/* set the new frame number */
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 78ce24db503..a8b63e01ac1 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -48,6 +48,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_brush_types.h"
#include "DNA_mask_types.h"
#include "BKE_fcurve.h"
@@ -593,12 +594,12 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
}
if (block_len > 0) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_TRIS, 6 * block_len);
+ immBegin(GPU_PRIM_TRIS, 6 * block_len);
for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
if (actkeyblock_is_valid(ab, keys)) {
if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
@@ -633,14 +634,14 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
if (key_len > 0) {
/* draw keys */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, key_len);
+ immBegin(GPU_PRIM_POINTS, key_len);
for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
@@ -783,7 +784,7 @@ void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos
BLI_dlrbTree_init(&keys);
- gpencil_to_keylist(ads, gpd, &keys);
+ gpencil_to_keylist(ads, gpd, &keys, false);
BLI_dlrbTree_linkedlist_sync(&keys);
@@ -1019,7 +1020,7 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree
}
-void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
+void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys, const bool active)
{
bGPDlayer *gpl;
@@ -1027,7 +1028,9 @@ void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
/* for now, just aggregate out all the frames, but only for visible layers */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if ((gpl->flag & GP_LAYER_HIDE) == 0) {
- gpl_to_keylist(ads, gpl, keys);
+ if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) {
+ gpl_to_keylist(ads, gpl, keys);
+ }
}
}
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index a6ed6643257..b98feac2384 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -183,7 +183,8 @@ void duplicate_fcurve_keys(FCurve *fcu)
/* Various Tools */
/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only
- * optionally clears up curve if one keyframe with default value remains */
+ * optionally clears up curve if one keyframe with default value remains
+ */
void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
{
FCurve *fcu = (FCurve *)ale->key_data;
@@ -206,7 +207,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
/* now insert first keyframe, as it should be ok */
bezt = old_bezts;
- insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
if (!(bezt->f2 & SELECT)) {
lastb = fcu->bezt;
lastb->f1 = lastb->f2 = lastb->f3 = 0;
@@ -235,7 +236,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
if (!(bezt->f2 & SELECT)) {
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
lastb = (fcu->bezt + (fcu->totvert - 1));
lastb->f1 = lastb->f2 = lastb->f3 = 0;
continue;
@@ -254,7 +255,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
if (cur[1] > next[1]) {
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
}
}
}
@@ -262,7 +263,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
/* only add if values are a considerable distance apart */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
}
}
}
@@ -271,19 +272,19 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
if (beztn) {
/* does current have same value as previous and next? */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
- /* add new keyframe*/
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ /* add new keyframe */
+ insert_bezt_fcurve(fcu, bezt, 0);
}
else if (IS_EQT(cur[1], next[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
}
}
else {
/* add if value doesn't equal that of previous */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
+ insert_bezt_fcurve(fcu, bezt, 0);
}
}
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index ae2e7339c66..7602bccc48c 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -426,7 +426,7 @@ static EditBone *get_nearest_editbonepoint(
if (use_cycle) {
static int last_mval[2] = {-100, -100};
- if (vc->v3d->drawtype > OB_WIRE) {
+ if (vc->v3d->shading.type > OB_WIRE) {
do_nearest = true;
if (len_manhattan_v2v2_int(vc->mval, last_mval) < 3) {
do_nearest = false;
@@ -435,7 +435,7 @@ static EditBone *get_nearest_editbonepoint(
copy_v2_v2_int(last_mval, vc->mval);
}
else {
- if (vc->v3d->drawtype > OB_WIRE) {
+ if (vc->v3d->shading.type > OB_WIRE) {
do_nearest = true;
}
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 02d45a4e041..2b28b76bcf6 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -681,7 +681,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
/* so all users of this armature should get rebuilt */
for (obt = bmain->object.first; obt; obt = obt->id.next) {
if (obt->data == arm) {
- BKE_pose_rebuild(obt, arm);
+ BKE_pose_rebuild(bmain, obt, arm, true);
}
}
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index a9ba8c405ba..a2cd3c57101 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -70,6 +70,15 @@
#include "armature_intern.h"
+
+#define DEBUG_TIME
+
+#include "PIL_time.h"
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
+
/* matches logic with ED_operator_posemode_context() */
Object *ED_pose_object_from_context(bContext *C)
{
@@ -256,10 +265,18 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+#ifdef DEBUG_TIME
+ TIMEIT_START(recalc_pose_paths);
+#endif
+
/* calculate the bones that now have motionpaths... */
/* TODO: only make for the selected bones? */
ED_pose_recalculate_paths(C, scene, ob);
+#ifdef DEBUG_TIME
+ TIMEIT_END(recalc_pose_paths);
+#endif
+
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -287,7 +304,8 @@ void POSE_OT_paths_calculate(wmOperatorType *ot)
RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
"Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items, 0,
+ RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items,
+ MOTIONPATH_BAKE_HEADS,
"Bake Location",
"Which point on the bones is used when calculating paths");
}
@@ -364,6 +382,9 @@ static void ED_pose_clear_paths(Object *ob, bool only_selected)
/* if nothing was skipped, there should be no paths left! */
if (skipped == false)
ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+
+ /* tag armature object for copy on write - so removed paths don't still show */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
/* operator callback - wrapper for the backend function */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 1d7a9ac46c7..f7d54e3bc4f 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -6260,12 +6260,12 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
float min[3], max[3], size[3], loc[3];
int a;
- if (object->curve_cache == NULL) {
+ if (object->runtime.curve_cache == NULL) {
BKE_displist_make_curveTypes(depsgraph, scene, object, false);
}
INIT_MINMAX(min, max);
- BKE_displist_minmax(&object->curve_cache->disp, min, max);
+ BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max);
mid_v3_v3v3(loc, min, max);
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 90f9b2e0569..dd0430f4f65 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -387,17 +387,17 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
float color[3];
UI_GetThemeColor3fv(TH_WIRE, color);
- Gwn_Batch *sphere = GPU_batch_preset_sphere(0);
- GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
- GWN_batch_uniform_3fv(sphere, "color", color);
+ GPUBatch *sphere = GPU_batch_preset_sphere(0);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_batch_uniform_3fv(sphere, "color", color);
/* scale to edit-mode space */
- gpuPushMatrix();
- gpuMultMatrix(obedit->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(obedit->obmat);
BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- gpuTranslate3f(
+ GPU_matrix_translate_3f(
selem->location_local[0] - location_prev[0],
selem->location_local[1] - location_prev[1],
selem->location_local[2] - location_prev[2]);
@@ -405,15 +405,15 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
const float radius = stroke_elem_radius(cdd, selem);
- gpuPushMatrix();
- gpuScaleUniform(radius);
- GWN_batch_draw(sphere);
- gpuPopMatrix();
+ GPU_matrix_push();
+ GPU_matrix_scale_1f(radius);
+ GPU_batch_draw(sphere);
+ GPU_matrix_pop();
location_prev = selem->location_local;
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
if (stroke_len > 1) {
@@ -430,8 +430,8 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
}
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_depth_test(false);
@@ -440,7 +440,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
GPU_line_width(3.0f);
imm_cpack(0x0);
- immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
+ immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
for (int i = 0; i < stroke_len; i++) {
immVertex3fv(pos, coord_array[i]);
}
@@ -449,7 +449,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
GPU_line_width(1.0f);
imm_cpack(0xffffffff);
- immBegin(GWN_PRIM_LINE_STRIP, stroke_len);
+ immBegin(GPU_PRIM_LINE_STRIP, stroke_len);
for (int i = 0; i < stroke_len; i++) {
immVertex3fv(pos, coord_array[i]);
}
@@ -1095,7 +1095,7 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
- (v3d->drawtype > OB_WIRE))
+ (v3d->shading.type > OB_WIRE))
{
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 0e09ef6f583..910b61cbdd8 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -536,6 +536,16 @@ set(ICON_NAMES
# This section is maintained by the updating script, keep BEGIN/END comments.
set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
# BEGIN ICON_GEOM_NAMES
+ brush.gpencil.draw.eraser_hard
+ brush.gpencil.draw.eraser_soft
+ brush.gpencil.draw.eraser_stroke
+ brush.gpencil.draw_block
+ brush.gpencil.draw_fill
+ brush.gpencil.draw_ink
+ brush.gpencil.draw_marker
+ brush.gpencil.draw_noise
+ brush.gpencil.draw_pen
+ brush.gpencil.draw_pencil
brush.paint_texture.airbrush
brush.paint_texture.clone
brush.paint_texture.draw
@@ -554,6 +564,13 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.paint_weight.lighten
brush.paint_weight.mix
brush.paint_weight.multiply
+ brush.particle.add
+ brush.particle.comb
+ brush.particle.cut
+ brush.particle.length
+ brush.particle.puff
+ brush.particle.smooth
+ brush.particle.weight
brush.sculpt.blob
brush.sculpt.clay
brush.sculpt.clay_strips
@@ -583,6 +600,24 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.generic.select_border
ops.generic.select_circle
ops.generic.select_lasso
+ ops.gpencil.draw
+ ops.gpencil.draw.eraser
+ ops.gpencil.draw.line
+ ops.gpencil.draw.poly
+ ops.gpencil.edit_bend
+ ops.gpencil.edit_mirror
+ ops.gpencil.edit_shear
+ ops.gpencil.edit_to_sphere
+ ops.gpencil.sculpt_clone
+ ops.gpencil.sculpt_grab
+ ops.gpencil.sculpt_pinch
+ ops.gpencil.sculpt_push
+ ops.gpencil.sculpt_randomize
+ ops.gpencil.sculpt_smooth
+ ops.gpencil.sculpt_strength
+ ops.gpencil.sculpt_thickness
+ ops.gpencil.sculpt_twist
+ ops.gpencil.sculpt_weight
ops.mesh.bevel
ops.mesh.bisect
ops.mesh.dupli_extrude_cursor
@@ -634,6 +669,7 @@ if(WITH_BLENDER)
# blends
data_to_c_simple(../../../../release/datafiles/preview.blend SRC)
data_to_c_simple(../../../../release/datafiles/preview_cycles.blend SRC)
+ data_to_c_simple(../../../../release/datafiles/preview_grease_pencil.blend SRC)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
@@ -689,6 +725,29 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
+ # grease pencil sculpt
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_smooth.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_thickness.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_strength.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_grab.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_push.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_twist.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pinch.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_randomize.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_clone.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_weight.png SRC)
+
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pencil.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_pen.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_ink.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_inknoise.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_block.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_marker.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_fill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_soft.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_hard.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/gp_brush_erase_stroke.png SRC)
+
endif()
data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
diff --git a/source/blender/editors/gizmo_library/CMakeLists.txt b/source/blender/editors/gizmo_library/CMakeLists.txt
index 389820240e2..e1ea5c22ce5 100644
--- a/source/blender/editors/gizmo_library/CMakeLists.txt
+++ b/source/blender/editors/gizmo_library/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SRC
geometry/geom_dial_gizmo.c
gizmo_types/arrow2d_gizmo.c
gizmo_types/arrow3d_gizmo.c
+ gizmo_types/blank3d_gizmo.c
gizmo_types/button2d_gizmo.c
gizmo_types/cage2d_gizmo.c
gizmo_types/cage3d_gizmo.c
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index aaaee182c71..5ccb1fa1f6d 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -64,31 +64,31 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(sel
/* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes
* So we don't need to re-created and discard it every time */
- Gwn_VertBuf *vbo;
- Gwn_IndexBuf *el;
- Gwn_Batch *batch;
- Gwn_IndexBufBuilder elb = {0};
+ GPUVertBuf *vbo;
+ GPUIndexBuf *el;
+ GPUBatch *batch;
+ GPUIndexBufBuilder elb = {0};
- Gwn_VertFormat format = {0};
- uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
/* Elements */
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, info->ntris, info->nverts);
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, info->ntris, info->nverts);
for (int i = 0; i < info->ntris; ++i) {
const unsigned short *idx = &info->indices[i * 3];
- GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
}
- el = GWN_indexbuf_build(&elb);
+ el = GPU_indexbuf_build(&elb);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, info->nverts);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, info->nverts);
- GWN_vertbuf_attr_fill(vbo, pos_id, info->verts);
+ GPU_vertbuf_attr_fill(vbo, pos_id, info->verts);
- batch = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, el, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, el, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
- GWN_batch_uniform_4fv(batch, "color", color);
+ GPU_batch_uniform_4fv(batch, "color", color);
/* We may want to re-visit this, for now disable
* since it causes issues leaving the GL state modified. */
@@ -97,7 +97,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(sel
GPU_depth_test(true);
#endif
- GWN_batch_draw(batch);
+ GPU_batch_draw(batch);
#if 0
GPU_depth_test(false);
@@ -105,7 +105,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info, const bool UNUSED(sel
#endif
- GWN_batch_discard(batch);
+ GPU_batch_discard(batch);
}
void wm_gizmo_vec_draw(
diff --git a/source/blender/editors/gizmo_library/gizmo_library_intern.h b/source/blender/editors/gizmo_library/gizmo_library_intern.h
index f1689ee93db..f5584d86847 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_intern.h
+++ b/source/blender/editors/gizmo_library/gizmo_library_intern.h
@@ -76,25 +76,25 @@ float gizmo_value_from_offset(
const bool constrained, const bool inverted, const bool use_precision);
void gizmo_property_data_update(
- struct wmGizmo *mpr, GizmoCommonData *data, wmGizmoProperty *mpr_prop,
+ struct wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop,
const bool constrained, const bool inverted);
void gizmo_property_value_reset(
- bContext *C, const struct wmGizmo *mpr, GizmoInteraction *inter, wmGizmoProperty *mpr_prop);
+ bContext *C, const struct wmGizmo *gz, GizmoInteraction *inter, wmGizmoProperty *gz_prop);
/* -------------------------------------------------------------------- */
void gizmo_color_get(
- const struct wmGizmo *mpr, const bool highlight,
+ const struct wmGizmo *gz, const bool highlight,
float r_color[4]);
bool gizmo_window_project_2d(
- bContext *C, const struct wmGizmo *mpr, const float mval[2], int axis, bool use_offset,
+ bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset,
float r_co[2]);
bool gizmo_window_project_3d(
- bContext *C, const struct wmGizmo *mpr, const float mval[2], bool use_offset,
+ bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset,
float r_co[3]);
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c
index 8a6b92e48d6..ab92905192b 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_presets.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c
@@ -81,23 +81,23 @@ static void single_axis_convert(
* Use for all geometry.
*/
static void ed_gizmo_draw_preset_geometry(
- const struct wmGizmo *mpr, float mat[4][4], int select_id,
+ const struct wmGizmo *gz, float mat[4][4], int select_id,
const GizmoGeomInfo *info)
{
const bool is_select = (select_id != -1);
- const bool is_highlight = is_select && (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
float color[4];
- gizmo_color_get(mpr, is_highlight, color);
+ gizmo_color_get(gz, is_highlight, color);
if (is_select) {
GPU_select_load_id(select_id);
}
- gpuPushMatrix();
- gpuMultMatrix(mat);
+ GPU_matrix_push();
+ GPU_matrix_mul(mat);
wm_gizmo_geometryinfo_draw(info, is_select, color);
- gpuPopMatrix();
+ GPU_matrix_pop();
if (is_select) {
GPU_select_load_id(-1);
@@ -105,44 +105,44 @@ static void ed_gizmo_draw_preset_geometry(
}
void ED_gizmo_draw_preset_box(
- const struct wmGizmo *mpr, float mat[4][4], int select_id)
+ const struct wmGizmo *gz, float mat[4][4], int select_id)
{
- ed_gizmo_draw_preset_geometry(mpr, mat, select_id, &wm_gizmo_geom_data_cube);
+ ed_gizmo_draw_preset_geometry(gz, mat, select_id, &wm_gizmo_geom_data_cube);
}
void ED_gizmo_draw_preset_arrow(
- const struct wmGizmo *mpr, float mat[4][4], int axis, int select_id)
+ const struct wmGizmo *gz, float mat[4][4], int axis, int select_id)
{
float mat_rotate[4][4];
single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
- ed_gizmo_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_gizmo_geom_data_arrow);
+ ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_arrow);
}
void ED_gizmo_draw_preset_circle(
- const struct wmGizmo *mpr, float mat[4][4], int axis, int select_id)
+ const struct wmGizmo *gz, float mat[4][4], int axis, int select_id)
{
float mat_rotate[4][4];
single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
- ed_gizmo_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
+ ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
}
void ED_gizmo_draw_preset_facemap(
- const bContext *C, const struct wmGizmo *mpr, struct Scene *scene, Object *ob, const int facemap, int select_id)
+ const bContext *C, const struct wmGizmo *gz, struct Scene *scene, Object *ob, const int facemap, int select_id)
{
const bool is_select = (select_id != -1);
- const bool is_highlight = is_select && (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
float color[4];
- gizmo_color_get(mpr, is_highlight, color);
+ gizmo_color_get(gz, is_highlight, color);
if (is_select) {
GPU_select_load_id(select_id);
}
- gpuPushMatrix();
- gpuMultMatrix(ob->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(ob->obmat);
ED_draw_object_facemap(CTX_data_depsgraph(C), scene, ob, color, facemap);
- gpuPopMatrix();
+ GPU_matrix_pop();
if (is_select) {
GPU_select_load_id(-1);
diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c
index 6e6bc2ed824..07c230c5503 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c
@@ -107,13 +107,13 @@ float gizmo_value_from_offset(
}
void gizmo_property_data_update(
- wmGizmo *mpr, GizmoCommonData *data, wmGizmoProperty *mpr_prop,
+ wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop,
const bool constrained, const bool inverted)
{
- if (mpr_prop->custom_func.value_get_fn != NULL) {
+ if (gz_prop->custom_func.value_get_fn != NULL) {
/* pass */
}
- else if (mpr_prop->prop != NULL) {
+ else if (gz_prop->prop != NULL) {
/* pass */
}
else {
@@ -121,12 +121,12 @@ void gizmo_property_data_update(
return;
}
- float value = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ float value = WM_gizmo_target_property_value_get(gz, gz_prop);
if (constrained) {
if ((data->flag & GIZMO_CUSTOM_RANGE_SET) == 0) {
float range[2];
- if (WM_gizmo_target_property_range_get(mpr, mpr_prop, range)) {
+ if (WM_gizmo_target_property_range_get(gz, gz_prop, range)) {
data->range = range[1] - range[0];
data->min = range[0];
}
@@ -142,23 +142,23 @@ void gizmo_property_data_update(
}
void gizmo_property_value_reset(
- bContext *C, const wmGizmo *mpr, GizmoInteraction *inter,
- wmGizmoProperty *mpr_prop)
+ bContext *C, const wmGizmo *gz, GizmoInteraction *inter,
+ wmGizmoProperty *gz_prop)
{
- WM_gizmo_target_property_value_set(C, mpr, mpr_prop, inter->init_value);
+ WM_gizmo_target_property_value_set(C, gz, gz_prop, inter->init_value);
}
/* -------------------------------------------------------------------- */
void gizmo_color_get(
- const wmGizmo *mpr, const bool highlight,
+ const wmGizmo *gz, const bool highlight,
float r_col[4])
{
- if (highlight && !(mpr->flag & WM_GIZMO_DRAW_HOVER)) {
- copy_v4_v4(r_col, mpr->color_hi);
+ if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) {
+ copy_v4_v4(r_col, gz->color_hi);
}
else {
- copy_v4_v4(r_col, mpr->color);
+ copy_v4_v4(r_col, gz->color);
}
}
@@ -169,7 +169,7 @@ void gizmo_color_get(
* Both 2D & 3D supported, use so we can use 2D gizmos in the 3D view.
*/
bool gizmo_window_project_2d(
- bContext *C, const struct wmGizmo *mpr, const float mval[2], int axis, bool use_offset,
+ bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset,
float r_co[2])
{
float mat[4][4];
@@ -180,11 +180,11 @@ bool gizmo_window_project_2d(
unit_m4(mat_identity);
params.matrix_offset = mat_identity;
}
- WM_gizmo_calc_matrix_final_params(mpr, &params, mat);
+ WM_gizmo_calc_matrix_final_params(gz, &params, mat);
}
/* rotate mouse in relation to the center and relocate it */
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
/* For 3d views, transform 2D mouse pos onto plane. */
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
@@ -221,7 +221,7 @@ bool gizmo_window_project_2d(
}
bool gizmo_window_project_3d(
- bContext *C, const struct wmGizmo *mpr, const float mval[2], bool use_offset,
+ bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset,
float r_co[3])
{
float mat[4][4];
@@ -232,10 +232,10 @@ bool gizmo_window_project_3d(
unit_m4(mat_identity);
params.matrix_offset = mat_identity;
}
- WM_gizmo_calc_matrix_final_params(mpr, &params, mat);
+ WM_gizmo_calc_matrix_final_params(gz, &params, mat);
}
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
/* Note: we might want a custom reference point passed in,
diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
index dfa2eeeb38b..953e763a33c 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow2d_gizmo.c
@@ -61,31 +61,31 @@
#include "../gizmo_library_intern.h"
-static void arrow2d_draw_geom(wmGizmo *mpr, const float matrix[4][4], const float color[4])
+static void arrow2d_draw_geom(wmGizmo *gz, const float matrix[4][4], const float color[4])
{
const float size = 0.11f;
const float size_breadth = size / 2.0f;
const float size_length = size * 1.7f;
/* Subtract the length so the arrow fits in the hotspot. */
- const float arrow_length = RNA_float_get(mpr->ptr, "length") - size_length;
- const float arrow_angle = RNA_float_get(mpr->ptr, "angle");
+ const float arrow_length = RNA_float_get(gz->ptr, "length") - size_length;
+ const float arrow_angle = RNA_float_get(gz->ptr, "angle");
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- gpuPushMatrix();
- gpuMultMatrix(matrix);
- gpuRotate2D(RAD2DEGF(arrow_angle));
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix);
+ GPU_matrix_rotate_2d(RAD2DEGF(arrow_angle));
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, 0.0f, 0.0f);
immVertex2f(pos, 0.0f, arrow_length);
immEnd();
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
immVertex2f(pos, size_breadth, arrow_length);
immVertex2f(pos, -size_breadth, arrow_length);
immVertex2f(pos, 0.0f, arrow_length + size_length);
@@ -93,63 +93,63 @@ static void arrow2d_draw_geom(wmGizmo *mpr, const float matrix[4][4], const floa
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
-static void gizmo_arrow2d_draw(const bContext *UNUSED(C), wmGizmo *mpr)
+static void gizmo_arrow2d_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
float color[4];
float matrix_final[4][4];
- gizmo_color_get(mpr, mpr->state & WM_GIZMO_STATE_HIGHLIGHT, color);
+ gizmo_color_get(gz, gz->state & WM_GIZMO_STATE_HIGHLIGHT, color);
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
GPU_blend(true);
- arrow2d_draw_geom(mpr, matrix_final, color);
+ arrow2d_draw_geom(gz, matrix_final, color);
GPU_blend(false);
- if (mpr->interaction_data) {
- GizmoInteraction *inter = mpr->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
GPU_blend(true);
- arrow2d_draw_geom(mpr, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
+ arrow2d_draw_geom(gz, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
GPU_blend(false);
}
}
-static void gizmo_arrow2d_setup(wmGizmo *mpr)
+static void gizmo_arrow2d_setup(wmGizmo *gz)
{
- mpr->flag |= WM_GIZMO_DRAW_MODAL;
+ gz->flag |= WM_GIZMO_DRAW_MODAL;
}
static int gizmo_arrow2d_invoke(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *UNUSED(event))
+ bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
{
GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- copy_m4_m4(inter->init_matrix_basis, mpr->matrix_basis);
- WM_gizmo_calc_matrix_final(mpr, inter->init_matrix_final);
+ copy_m4_m4(inter->init_matrix_basis, gz->matrix_basis);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
}
static int gizmo_arrow2d_test_select(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- const float mval[2] = {event->mval[0], event->mval[1]};
- const float arrow_length = RNA_float_get(mpr->ptr, "length");
- const float arrow_angle = RNA_float_get(mpr->ptr, "angle");
- const float line_len = arrow_length * mpr->scale_final;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ const float arrow_length = RNA_float_get(gz->ptr, "length");
+ const float arrow_angle = RNA_float_get(gz->ptr, "angle");
+ const float line_len = arrow_length * gz->scale_final;
float mval_local[2];
- copy_v2_v2(mval_local, mval);
- sub_v2_v2(mval_local, mpr->matrix_basis[3]);
+ copy_v2_v2(mval_local, mval_fl);
+ sub_v2_v2(mval_local, gz->matrix_basis[3]);
float line[2][2];
line[0][0] = line[0][1] = line[1][0] = 0.0f;
@@ -165,7 +165,7 @@ static int gizmo_arrow2d_test_select(
/* arrow line intersection check */
float isect_1[2], isect_2[2];
const int isect = isect_line_sphere_v2(
- line[0], line[1], mval_local, GIZMO_HOTSPOT + mpr->line_width * 0.5f,
+ line[0], line[1], mval_local, GIZMO_HOTSPOT + gz->line_width * 0.5f,
isect_1, isect_2);
if (isect > 0) {
@@ -197,29 +197,29 @@ static int gizmo_arrow2d_test_select(
*
* \{ */
-static void GIZMO_WT_arrow_2d(wmGizmoType *wt)
+static void GIZMO_GT_arrow_2d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_arrow_2d";
+ gzt->idname = "GIZMO_GT_arrow_2d";
/* api callbacks */
- wt->draw = gizmo_arrow2d_draw;
- wt->setup = gizmo_arrow2d_setup;
- wt->invoke = gizmo_arrow2d_invoke;
- wt->test_select = gizmo_arrow2d_test_select;
+ gzt->draw = gizmo_arrow2d_draw;
+ gzt->setup = gizmo_arrow2d_setup;
+ gzt->invoke = gizmo_arrow2d_invoke;
+ gzt->test_select = gizmo_arrow2d_test_select;
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
/* rna */
- RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
RNA_def_float_rotation(
- wt->srna, "angle", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f),
+ gzt->srna, "angle", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f),
"Roll", "", DEG2RADF(-360.0f), DEG2RADF(360.0f));
}
void ED_gizmotypes_arrow_2d(void)
{
- WM_gizmotype_append(GIZMO_WT_arrow_2d);
+ WM_gizmotype_append(GIZMO_GT_arrow_2d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
index 9807a111d26..0f8389af17d 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
@@ -80,9 +80,9 @@ typedef struct ArrowGizmo3D {
/* -------------------------------------------------------------------- */
-static void gizmo_arrow_matrix_basis_get(const wmGizmo *mpr, float r_matrix[4][4])
+static void gizmo_arrow_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4])
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
copy_m4_m4(r_matrix, arrow->gizmo.matrix_basis);
madd_v3_v3fl(r_matrix[3], arrow->gizmo.matrix_basis[2], arrow->data.offset);
@@ -90,7 +90,7 @@ static void gizmo_arrow_matrix_basis_get(const wmGizmo *mpr, float r_matrix[4][4
static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const float color[4])
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
bool unbind_shader = true;
const int draw_style = RNA_enum_get(arrow->gizmo.ptr, "draw_style");
const int draw_options = RNA_enum_get(arrow->gizmo.ptr, "draw_options");
@@ -100,7 +100,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
if (draw_style == ED_GIZMO_ARROW_STYLE_CROSS) {
immUniformColor4fv(color);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex3f(pos, -1.0f, 0.0f, 0.0f);
immVertex3f(pos, 1.0f, 0.0f, 0.0f);
immVertex3f(pos, 0.0f, -1.0f, 0.0f);
@@ -120,7 +120,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
};
GPU_line_width(arrow->gizmo.line_width);
- wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_LOOP);
+ wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
}
else {
#ifdef USE_GIZMO_CUSTOM_ARROWS
@@ -135,7 +135,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_STEM) {
GPU_line_width(arrow->gizmo.line_width);
- wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
+ wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_STRIP);
}
else {
immUniformColor4fv(color);
@@ -143,15 +143,15 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
/* *** draw arrow head *** */
- gpuPushMatrix();
+ GPU_matrix_push();
if (draw_style == ED_GIZMO_ARROW_STYLE_BOX) {
const float size = 0.05f;
/* translate to line end with some extra offset so box starts exactly where line ends */
- gpuTranslate3f(0.0f, 0.0f, arrow_length + size);
+ GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length + size);
/* scale down to box size */
- gpuScale3f(size, size, size);
+ GPU_matrix_scale_3f(size, size, size);
/* draw cube */
immUnbindProgram();
@@ -165,13 +165,13 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
const float width = 0.06f;
/* translate to line end */
- gpuTranslate3f(0.0f, 0.0f, arrow_length);
+ GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
#endif /* USE_GIZMO_CUSTOM_ARROWS */
}
@@ -182,48 +182,48 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight)
{
- wmGizmo *mpr = &arrow->gizmo;
+ wmGizmo *gz = &arrow->gizmo;
float color[4];
float matrix_final[4][4];
- gizmo_color_get(mpr, highlight, color);
+ gizmo_color_get(gz, highlight, color);
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
GPU_blend(true);
arrow_draw_geom(arrow, select, color);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
- if (mpr->interaction_data) {
- GizmoInteraction *inter = mpr->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
- gpuPushMatrix();
- gpuMultMatrix(inter->init_matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init_matrix_final);
GPU_blend(true);
arrow_draw_geom(arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
static void gizmo_arrow_draw_select(
- const bContext *UNUSED(C), wmGizmo *mpr,
+ const bContext *UNUSED(C), wmGizmo *gz,
int select_id)
{
GPU_select_load_id(select_id);
- arrow_draw_intern((ArrowGizmo3D *)mpr, true, false);
+ arrow_draw_intern((ArrowGizmo3D *)gz, true, false);
}
-static void gizmo_arrow_draw(const bContext *UNUSED(C), wmGizmo *mpr)
+static void gizmo_arrow_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- arrow_draw_intern((ArrowGizmo3D *)mpr, false, (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0);
+ arrow_draw_intern((ArrowGizmo3D *)gz, false, (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0);
}
/**
@@ -231,11 +231,11 @@ static void gizmo_arrow_draw(const bContext *UNUSED(C), wmGizmo *mpr)
* meaning the range will not be offset by min value first.
*/
static int gizmo_arrow_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak tweak_flag)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
- GizmoInteraction *inter = mpr->interaction_data;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ GizmoInteraction *inter = gz->interaction_data;
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
@@ -299,19 +299,19 @@ static int gizmo_arrow_modal(
GizmoCommonData *data = &arrow->data;
const float ofs_new = facdir * len_v3(offset);
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
/* set the property for the operator and call its modal function */
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
const bool use_precision = (tweak_flag & WM_GIZMO_TWEAK_PRECISE) != 0;
float value = gizmo_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
- WM_gizmo_target_property_value_set(C, mpr, mpr_prop, value);
+ WM_gizmo_target_property_value_set(C, gz, gz_prop, value);
/* get clamped value */
- value = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ value = WM_gizmo_target_property_value_get(gz, gz_prop);
data->offset = gizmo_offset_from_value(data, value, constrained, inverted);
}
@@ -326,9 +326,9 @@ static int gizmo_arrow_modal(
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_arrow_setup(wmGizmo *mpr)
+static void gizmo_arrow_setup(wmGizmo *gz)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
arrow->gizmo.flag |= WM_GIZMO_DRAW_MODAL;
@@ -336,15 +336,15 @@ static void gizmo_arrow_setup(wmGizmo *mpr)
}
static int gizmo_arrow_invoke(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
/* Some gizmos don't use properties. */
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- inter->init_value = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ inter->init_value = WM_gizmo_target_property_value_get(gz, gz_prop);
}
inter->init_offset = arrow->data.offset;
@@ -352,42 +352,42 @@ static int gizmo_arrow_invoke(
inter->init_mval[0] = event->mval[0];
inter->init_mval[1] = event->mval[1];
- gizmo_arrow_matrix_basis_get(mpr, inter->init_matrix_basis);
- WM_gizmo_calc_matrix_final(mpr, inter->init_matrix_final);
+ gizmo_arrow_matrix_basis_get(gz, inter->init_matrix_basis);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_arrow_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop)
+static void gizmo_arrow_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
const bool inverted = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_INVERTED) != 0;
- gizmo_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted);
+ gizmo_property_data_update(gz, &arrow->data, gz_prop, constrained, inverted);
}
-static void gizmo_arrow_exit(bContext *C, wmGizmo *mpr, const bool cancel)
+static void gizmo_arrow_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
GizmoCommonData *data = &arrow->data;
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
- const bool is_prop_valid = WM_gizmo_target_property_is_valid(mpr_prop);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ const bool is_prop_valid = WM_gizmo_target_property_is_valid(gz_prop);
if (!cancel) {
/* Assign incase applying the opetration needs an updated offset
* editmesh bisect needs this. */
if (is_prop_valid) {
- data->offset = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ data->offset = WM_gizmo_target_property_value_get(gz, gz_prop);
}
return;
}
- GizmoInteraction *inter = mpr->interaction_data;
+ GizmoInteraction *inter = gz->interaction_data;
if (is_prop_valid) {
- gizmo_property_value_reset(C, mpr, inter, mpr_prop);
+ gizmo_property_value_reset(C, gz, inter, gz_prop);
}
data->offset = inter->init_offset;
}
@@ -403,12 +403,12 @@ static void gizmo_arrow_exit(bContext *C, wmGizmo *mpr, const bool cancel)
*
* \note Needs to be called before WM_gizmo_target_property_def_rna!
*/
-void ED_gizmo_arrow3d_set_ui_range(wmGizmo *mpr, const float min, const float max)
+void ED_gizmo_arrow3d_set_ui_range(wmGizmo *gz, const float min, const float max)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
BLI_assert(min < max);
- BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(mpr, "offset")) &&
+ BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
"Make sure this function is called before WM_gizmo_target_property_def_rna"));
arrow->data.range = max - min;
@@ -421,31 +421,31 @@ void ED_gizmo_arrow3d_set_ui_range(wmGizmo *mpr, const float min, const float ma
*
* \note Needs to be called before WM_gizmo_target_property_def_rna!
*/
-void ED_gizmo_arrow3d_set_range_fac(wmGizmo *mpr, const float range_fac)
+void ED_gizmo_arrow3d_set_range_fac(wmGizmo *gz, const float range_fac)
{
- ArrowGizmo3D *arrow = (ArrowGizmo3D *)mpr;
- BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(mpr, "offset")) &&
+ ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
+ BLI_assert(!(WM_gizmo_target_property_is_valid(WM_gizmo_target_property_find(gz, "offset")) &&
"Make sure this function is called before WM_gizmo_target_property_def_rna"));
arrow->data.range_fac = range_fac;
}
-static void GIZMO_WT_arrow_3d(wmGizmoType *wt)
+static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_arrow_3d";
+ gzt->idname = "GIZMO_GT_arrow_3d";
/* api callbacks */
- wt->draw = gizmo_arrow_draw;
- wt->draw_select = gizmo_arrow_draw_select;
- wt->matrix_basis_get = gizmo_arrow_matrix_basis_get;
- wt->modal = gizmo_arrow_modal;
- wt->setup = gizmo_arrow_setup;
- wt->invoke = gizmo_arrow_invoke;
- wt->property_update = gizmo_arrow_property_update;
- wt->exit = gizmo_arrow_exit;
+ gzt->draw = gizmo_arrow_draw;
+ gzt->draw_select = gizmo_arrow_draw_select;
+ gzt->matrix_basis_get = gizmo_arrow_matrix_basis_get;
+ gzt->modal = gizmo_arrow_modal;
+ gzt->setup = gizmo_arrow_setup;
+ gzt->invoke = gizmo_arrow_invoke;
+ gzt->property_update = gizmo_arrow_property_update;
+ gzt->exit = gizmo_arrow_exit;
- wt->struct_size = sizeof(ArrowGizmo3D);
+ gzt->struct_size = sizeof(ArrowGizmo3D);
/* rna */
static EnumPropertyItem rna_enum_draw_style_items[] = {
@@ -466,27 +466,27 @@ static void GIZMO_WT_arrow_3d(wmGizmoType *wt)
};
RNA_def_enum(
- wt->srna, "draw_style", rna_enum_draw_style_items,
+ gzt->srna, "draw_style", rna_enum_draw_style_items,
ED_GIZMO_ARROW_STYLE_NORMAL,
"Draw Style", "");
RNA_def_enum_flag(
- wt->srna, "draw_options", rna_enum_draw_options_items,
+ gzt->srna, "draw_options", rna_enum_draw_options_items,
ED_GIZMO_ARROW_DRAW_FLAG_STEM,
"Draw Options", "");
RNA_def_enum_flag(
- wt->srna, "transform", rna_enum_transform_items,
+ gzt->srna, "transform", rna_enum_transform_items,
0,
"Transform", "");
- RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
- RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
+ RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float_vector(gzt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
- WM_gizmotype_target_property_def(wt, "offset", PROP_FLOAT, 1);
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
}
void ED_gizmotypes_arrow_3d(void)
{
- WM_gizmotype_append(GIZMO_WT_arrow_3d);
+ WM_gizmotype_append(GIZMO_GT_arrow_3d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
new file mode 100644
index 00000000000..0c67e8c606d
--- /dev/null
+++ b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
@@ -0,0 +1,89 @@
+/*
+ * ***** 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): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blank3d_gizmo.c
+ * \ingroup wm
+ *
+ * \name Blank Gizmo
+ *
+ * \brief Gizmo to use as a fallback (catch events).
+ */
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "ED_view3d.h"
+#include "ED_gizmo_library.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+/* own includes */
+#include "../gizmo_geometry.h"
+#include "../gizmo_library_intern.h"
+
+
+static void gizmo_blank_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz))
+{
+ /* pass */
+}
+
+static int gizmo_blank_invoke(
+ bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event))
+{
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int gizmo_blank_test_select(
+ bContext *UNUSED(C), wmGizmo *UNUSED(gz), const int UNUSED(mval[2]))
+{
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Blank Gizmo API
+ *
+ * \{ */
+
+static void GIZMO_GT_blank_3d(wmGizmoType *gzt)
+{
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_blank_3d";
+
+ /* api callbacks */
+ gzt->draw = gizmo_blank_draw;
+ gzt->invoke = gizmo_blank_invoke;
+ gzt->test_select = gizmo_blank_test_select;
+
+ gzt->struct_size = sizeof(wmGizmo);
+}
+
+void ED_gizmotypes_blank_3d(void)
+{
+ WM_gizmotype_append(GIZMO_GT_blank_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
index ede070f0bed..dfc0dcd791c 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -72,7 +72,7 @@ typedef struct ButtonGizmo2D {
bool is_init;
/* Use an icon or shape */
int icon;
- Gwn_Batch *shape_batch[2];
+ GPUBatch *shape_batch[2];
} ButtonGizmo2D;
#define CIRCLE_RESOLUTION 32
@@ -80,12 +80,12 @@ typedef struct ButtonGizmo2D {
/* -------------------------------------------------------------------- */
static void button2d_geom_draw_backdrop(
- const wmGizmo *mpr, const float color[4], const bool select)
+ const wmGizmo *gz, const float color[4], const bool select)
{
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -100,24 +100,24 @@ static void button2d_geom_draw_backdrop(
}
static void button2d_draw_intern(
- const bContext *C, wmGizmo *mpr,
+ const bContext *C, wmGizmo *gz,
const bool select, const bool highlight)
{
- ButtonGizmo2D *button = (ButtonGizmo2D *)mpr;
+ ButtonGizmo2D *button = (ButtonGizmo2D *)gz;
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if (button->is_init == false) {
button->is_init = true;
- PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "icon");
- if (RNA_property_is_set(mpr->ptr, prop)) {
- button->icon = RNA_property_enum_get(mpr->ptr, prop);
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
+ if (RNA_property_is_set(gz->ptr, prop)) {
+ button->icon = RNA_property_enum_get(gz->ptr, prop);
}
else {
- prop = RNA_struct_find_property(mpr->ptr, "shape");
- const uint polys_len = RNA_property_string_length(mpr->ptr, prop);
+ prop = RNA_struct_find_property(gz->ptr, "shape");
+ const uint polys_len = RNA_property_string_length(gz->ptr, prop);
/* We shouldn't need the +1, but a NULL char is set. */
char *polys = MEM_mallocN(polys_len + 1, __func__);
- RNA_property_string_get(mpr->ptr, prop, polys);
+ RNA_property_string_get(gz->ptr, prop, polys);
button->shape_batch[0] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
button->shape_batch[1] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
MEM_freeN(polys);
@@ -127,22 +127,22 @@ static void button2d_draw_intern(
float color[4];
float matrix_final[4][4];
- gizmo_color_get(mpr, highlight, color);
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ gizmo_color_get(gz, highlight, color);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- bool is_3d = (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0;
+ bool is_3d = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) != 0;
if (draw_options & ED_GIZMO_BUTTON_SHOW_HELPLINE) {
float matrix_final_no_offset[4][4];
- WM_gizmo_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(color);
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
immUniformColor4fv(color);
- immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immBegin(GPU_PRIM_LINE_STRIP, 2);
immVertex3fv(pos, matrix_final[3]);
immVertex3fv(pos, matrix_final_no_offset[3]);
immEnd();
@@ -150,8 +150,8 @@ static void button2d_draw_intern(
}
bool need_to_pop = true;
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
if (is_3d) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -161,12 +161,12 @@ static void button2d_draw_intern(
mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
zero_v3(matrix_align[3]);
transpose_m4(matrix_align);
- gpuMultMatrix(matrix_align);
+ GPU_matrix_mul(matrix_align);
}
if (select) {
BLI_assert(is_3d);
- button2d_geom_draw_backdrop(mpr, color, select);
+ button2d_geom_draw_backdrop(gz, color, select);
}
else {
@@ -177,9 +177,9 @@ static void button2d_draw_intern(
GPU_line_width(1.0f);
for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) {
/* Invert line color for wire. */
- GWN_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
- GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
- GWN_batch_draw(button->shape_batch[i]);
+ GPU_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
+ GPU_batch_draw(button->shape_batch[i]);
if (draw_options & ED_GIZMO_BUTTON_SHOW_OUTLINE) {
color[0] = 1.0f - color[0];
@@ -191,19 +191,19 @@ static void button2d_draw_intern(
GPU_polygon_smooth(true);
}
else if (button->icon != ICON_NONE) {
- button2d_geom_draw_backdrop(mpr, color, select);
+ button2d_geom_draw_backdrop(gz, color, select);
float size[2];
if (is_3d) {
const float fac = 2.0f;
- gpuTranslate2f(-(fac / 2), -(fac / 2));
- gpuScale2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
+ GPU_matrix_translate_2f(-(fac / 2), -(fac / 2));
+ GPU_matrix_scale_2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
size[0] = 1.0f;
size[1] = 1.0f;
}
else {
- size[0] = mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
- size[1] = mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
- gpuPopMatrix();
+ size[0] = gz->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
+ size[1] = gz->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
+ GPU_matrix_pop();
need_to_pop = false;
}
UI_icon_draw(size[0], size[1], button->icon);
@@ -212,44 +212,44 @@ static void button2d_draw_intern(
}
if (need_to_pop) {
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
-static void gizmo_button2d_draw_select(const bContext *C, wmGizmo *mpr, int select_id)
+static void gizmo_button2d_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
GPU_select_load_id(select_id);
- button2d_draw_intern(C, mpr, true, false);
+ button2d_draw_intern(C, gz, true, false);
}
-static void gizmo_button2d_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_button2d_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
GPU_blend(true);
- button2d_draw_intern(C, mpr, false, is_highlight);
+ button2d_draw_intern(C, gz, false, is_highlight);
GPU_blend(false);
}
static int gizmo_button2d_test_select(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const int mval[2])
{
float point_local[2];
if (0) {
/* correct, but unnecessarily slow. */
if (gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+ C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
{
return -1;
}
}
else {
- copy_v2_v2(point_local, (float[2]){UNPACK2(event->mval)});
- sub_v2_v2(point_local, mpr->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * UI_DPI_FAC));
+ copy_v2_v2(point_local, (float[2]){UNPACK2(mval)});
+ sub_v2_v2(point_local, gz->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
}
- /* The 'mpr->scale_final' is already applied when projecting. */
+ /* The 'gz->scale_final' is already applied when projecting. */
if (len_squared_v2(point_local) < 1.0f) {
return 0;
}
@@ -257,20 +257,20 @@ static int gizmo_button2d_test_select(
return -1;
}
-static int gizmo_button2d_cursor_get(wmGizmo *mpr)
+static int gizmo_button2d_cursor_get(wmGizmo *gz)
{
- if (RNA_boolean_get(mpr->ptr, "show_drag")) {
+ if (RNA_boolean_get(gz->ptr, "show_drag")) {
return BC_NSEW_SCROLLCURSOR;
}
return CURSOR_STD;
}
-static void gizmo_button2d_free(wmGizmo *mpr)
+static void gizmo_button2d_free(wmGizmo *gz)
{
- ButtonGizmo2D *shape = (ButtonGizmo2D *)mpr;
+ ButtonGizmo2D *shape = (ButtonGizmo2D *)gz;
for (uint i = 0; i < ARRAY_SIZE(shape->shape_batch); i++) {
- GWN_BATCH_DISCARD_SAFE(shape->shape_batch[i]);
+ GPU_BATCH_DISCARD_SAFE(shape->shape_batch[i]);
}
}
@@ -281,19 +281,19 @@ static void gizmo_button2d_free(wmGizmo *mpr)
*
* \{ */
-static void GIZMO_WT_button_2d(wmGizmoType *wt)
+static void GIZMO_GT_button_2d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_button_2d";
+ gzt->idname = "GIZMO_GT_button_2d";
/* api callbacks */
- wt->draw = gizmo_button2d_draw;
- wt->draw_select = gizmo_button2d_draw_select;
- wt->test_select = gizmo_button2d_test_select;
- wt->cursor_get = gizmo_button2d_cursor_get;
- wt->free = gizmo_button2d_free;
+ gzt->draw = gizmo_button2d_draw;
+ gzt->draw_select = gizmo_button2d_draw_select;
+ gzt->test_select = gizmo_button2d_test_select;
+ gzt->cursor_get = gizmo_button2d_cursor_get;
+ gzt->free = gizmo_button2d_free;
- wt->struct_size = sizeof(ButtonGizmo2D);
+ gzt->struct_size = sizeof(ButtonGizmo2D);
/* rna */
static EnumPropertyItem rna_enum_draw_options[] = {
@@ -303,21 +303,21 @@ static void GIZMO_WT_button_2d(wmGizmoType *wt)
};
PropertyRNA *prop;
- RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(gzt->srna, "icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_icon_items);
/* Passed to 'GPU_batch_tris_from_poly_2d_encoded' */
- RNA_def_property(wt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
+ RNA_def_property(gzt->srna, "shape", PROP_STRING, PROP_BYTESTRING);
/* Currently only used for cursor display. */
- RNA_def_boolean(wt->srna, "show_drag", true, "Show Drag", "");
+ RNA_def_boolean(gzt->srna, "show_drag", true, "Show Drag", "");
}
void ED_gizmotypes_button_2d(void)
{
- WM_gizmotype_append(GIZMO_WT_button_2d);
+ WM_gizmotype_append(GIZMO_GT_button_2d);
}
/** \} */ // Button Gizmo API
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index a037727de58..bb9cac595be 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -68,7 +68,7 @@
#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
static void gizmo_calc_rect_view_scale(
- const wmGizmo *mpr, const float dims[2], float scale[2])
+ const wmGizmo *gz, const float dims[2], float scale[2])
{
float matrix_final_no_offset[4][4];
float asp[2] = {1.0f, 1.0f};
@@ -79,9 +79,9 @@ static void gizmo_calc_rect_view_scale(
asp[1] = dims[0] / dims[1];
}
float x_axis[3], y_axis[3];
- WM_gizmo_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
- mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
- mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
+ WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
mul_v2_v2(x_axis, asp);
mul_v2_v2(y_axis, asp);
@@ -91,18 +91,18 @@ static void gizmo_calc_rect_view_scale(
}
static void gizmo_calc_rect_view_margin(
- const wmGizmo *mpr, const float dims[2], float margin[2])
+ const wmGizmo *gz, const float dims[2], float margin[2])
{
float handle_size;
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
handle_size = 0.15f;
}
else {
handle_size = GIZMO_RESIZER_SIZE;
}
- handle_size *= mpr->scale_final;
+ handle_size *= gz->scale_final;
float scale_xy[2];
- gizmo_calc_rect_view_scale(mpr, dims, scale_xy);
+ gizmo_calc_rect_view_scale(gz, dims, scale_xy);
margin[0] = ((handle_size * scale_xy[0]));
margin[1] = ((handle_size * scale_xy[1]));
}
@@ -136,12 +136,12 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_con
static void cage2d_draw_box_corners(
const rctf *r, const float margin[2], const float color[3])
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fv(color);
- immBegin(GWN_PRIM_LINES, 16);
+ immBegin(GPU_PRIM_LINES, 16);
immVertex2f(pos, r->xmin, r->ymin + margin[1]);
immVertex2f(pos, r->xmin, r->ymin);
@@ -176,7 +176,7 @@ static void cage2d_draw_box_interaction(
/* 4 verts for translate, otherwise only 3 are used. */
float verts[4][2];
uint verts_len = 0;
- Gwn_PrimType prim_type = GWN_PRIM_NONE;
+ GPUPrimType prim_type = GPU_PRIM_NONE;
switch (highlighted) {
case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X:
@@ -192,10 +192,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
verts_len += 2;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -212,10 +212,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
verts_len += 2;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -232,10 +232,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
verts_len += 2;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -252,10 +252,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
verts_len += 2;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -272,10 +272,10 @@ static void cage2d_draw_box_interaction(
if (is_solid) {
ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
verts_len += 1;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -292,10 +292,10 @@ static void cage2d_draw_box_interaction(
if (is_solid) {
ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
verts_len += 1;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -312,10 +312,10 @@ static void cage2d_draw_box_interaction(
if (is_solid) {
ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
verts_len += 1;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -332,10 +332,10 @@ static void cage2d_draw_box_interaction(
if (is_solid) {
ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
verts_len += 1;
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -355,10 +355,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
verts_len = 4;
if (is_solid) {
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
break;
}
@@ -371,10 +371,10 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
verts_len = 4;
if (is_solid) {
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
- prim_type = GWN_PRIM_LINES;
+ prim_type = GPU_PRIM_LINES;
}
}
else {
@@ -385,12 +385,12 @@ static void cage2d_draw_box_interaction(
ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
verts_len = 4;
if (is_solid) {
- prim_type = GWN_PRIM_TRI_FAN;
+ prim_type = GPU_PRIM_TRI_FAN;
}
else {
/* unreachable */
BLI_assert(0);
- prim_type = GWN_PRIM_LINE_STRIP;
+ prim_type = GPU_PRIM_LINE_STRIP;
}
}
break;
@@ -398,20 +398,20 @@ static void cage2d_draw_box_interaction(
return;
}
- BLI_assert(prim_type != GWN_PRIM_NONE);
+ BLI_assert(prim_type != GPU_PRIM_NONE);
- Gwn_VertFormat *format = immVertexFormat();
+ GPUVertFormat *format = immVertexFormat();
struct {
uint pos, col;
} attr_id = {
- .pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT),
- .col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT),
+ .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT),
+ .col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT),
};
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
{
if (is_solid) {
- BLI_assert(ELEM(prim_type, GWN_PRIM_TRI_FAN));
+ BLI_assert(ELEM(prim_type, GPU_PRIM_TRI_FAN));
immBegin(prim_type, verts_len);
immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f);
for (uint i = 0; i < verts_len; i++) {
@@ -420,7 +420,7 @@ static void cage2d_draw_box_interaction(
immEnd();
}
else {
- BLI_assert(ELEM(prim_type, GWN_PRIM_LINE_STRIP, GWN_PRIM_LINES));
+ BLI_assert(ELEM(prim_type, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINES));
GPU_line_width(line_width + 3.0f);
immBegin(prim_type, verts_len);
@@ -455,7 +455,7 @@ static void cage2d_draw_box_interaction(
static void imm_draw_point_aspect_2d(
uint pos, float x, float y, float rad_x, float rad_y, bool solid)
{
- immBegin(solid ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
+ immBegin(solid ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, x - rad_x, y - rad_y);
immVertex2f(pos, x - rad_x, y + rad_y);
immVertex2f(pos, x + rad_x, y + rad_y);
@@ -467,12 +467,12 @@ static void cage2d_draw_circle_wire(
const rctf *r, const float margin[2], const float color[3],
const int transform_flag, const int draw_options)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fv(color);
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, r->xmin, r->ymin);
immVertex2f(pos, r->xmax, r->ymin);
immVertex2f(pos, r->xmax, r->ymax);
@@ -480,7 +480,7 @@ static void cage2d_draw_circle_wire(
immEnd();
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
- immBegin(GWN_PRIM_LINE_LOOP, 2);
+ immBegin(GPU_PRIM_LINE_LOOP, 2);
immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax);
immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]);
immEnd();
@@ -491,7 +491,7 @@ static void cage2d_draw_circle_wire(
const float rad[2] = {margin[0] / 2, margin[1] / 2};
const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
@@ -508,7 +508,7 @@ static void cage2d_draw_circle_handles(
const int transform_flag,
bool solid)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
void (*circle_fn)(uint, float, float, float, float, int) =
(solid) ? imm_draw_circle_fill_aspect_2d : imm_draw_circle_wire_aspect_2d;
const int resolu = 12;
@@ -536,31 +536,31 @@ static void cage2d_draw_circle_handles(
/** \} */
static void gizmo_cage2d_draw_intern(
- wmGizmo *mpr, const bool select, const bool highlight, const int select_id)
+ wmGizmo *gz, const bool select, const bool highlight, const int select_id)
{
- // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
+ // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
float dims[2];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
float matrix_final[4][4];
- const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
- const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
float margin[2];
- gizmo_calc_rect_view_margin(mpr, dims, margin);
+ gizmo_calc_rect_view_margin(gz, dims, margin);
/* Handy for quick testing draw (if it's outside bounds). */
if (false) {
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
float s = 0.5f;
@@ -588,18 +588,18 @@ static void gizmo_cage2d_draw_intern(
for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
GPU_select_load_id(select_id | scale_parts[i]);
cage2d_draw_box_interaction(
- mpr->color, scale_parts[i], size, margin, mpr->line_width, true, draw_options);
+ gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
GPU_select_load_id(select_id | transform_part);
cage2d_draw_box_interaction(
- mpr->color, transform_part, size, margin, mpr->line_width, true, draw_options);
+ gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
cage2d_draw_box_interaction(
- mpr->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, true, draw_options);
+ gz->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, gz->line_width, true, draw_options);
}
}
else {
@@ -611,17 +611,17 @@ static void gizmo_cage2d_draw_intern(
};
if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
/* corner gizmos */
- GPU_line_width(mpr->line_width + 3.0f);
+ GPU_line_width(gz->line_width + 3.0f);
cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
/* corner gizmos */
float color[4];
- gizmo_color_get(mpr, highlight, color);
- GPU_line_width(mpr->line_width);
+ gizmo_color_get(gz, highlight, color);
+ GPU_line_width(gz->line_width);
cage2d_draw_box_corners(&r, margin, color);
bool show = false;
- if (mpr->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
+ if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
/* Only show if we're drawing the center handle
* otherwise the entire rectangle is the hotspot. */
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
@@ -634,24 +634,24 @@ static void gizmo_cage2d_draw_intern(
if (show) {
cage2d_draw_box_interaction(
- mpr->color, mpr->highlight_part, size_real, margin, mpr->line_width, false, draw_options);
+ gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
cage2d_draw_box_interaction(
- mpr->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, false, draw_options);
+ gz->color, ED_GIZMO_CAGE2D_PART_ROTATE, size_real, margin, gz->line_width, false, draw_options);
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
float color[4];
- gizmo_color_get(mpr, highlight, color);
+ gizmo_color_get(gz, highlight, color);
GPU_line_smooth(true);
GPU_blend(true);
- GPU_line_width(mpr->line_width + 3.0f);
+ GPU_line_width(gz->line_width + 3.0f);
cage2d_draw_circle_wire(&r, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options);
@@ -668,28 +668,28 @@ static void gizmo_cage2d_draw_intern(
}
GPU_line_width(1.0);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/**
* For when we want to draw 2d cage in 3d views.
*/
-static void gizmo_cage2d_draw_select(const bContext *UNUSED(C), wmGizmo *mpr, int select_id)
+static void gizmo_cage2d_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
{
- gizmo_cage2d_draw_intern(mpr, true, false, select_id);
+ gizmo_cage2d_draw_intern(gz, true, false, select_id);
}
-static void gizmo_cage2d_draw(const bContext *UNUSED(C), wmGizmo *mpr)
+static void gizmo_cage2d_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- gizmo_cage2d_draw_intern(mpr, false, is_highlight, -1);
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ gizmo_cage2d_draw_intern(gz, false, is_highlight, -1);
}
-static int gizmo_cage2d_get_cursor(wmGizmo *mpr)
+static int gizmo_cage2d_get_cursor(wmGizmo *gz)
{
- int highlight_part = mpr->highlight_part;
+ int highlight_part = gz->highlight_part;
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
return BC_NSEW_SCROLLCURSOR;
}
@@ -718,26 +718,26 @@ static int gizmo_cage2d_get_cursor(wmGizmo *mpr)
}
static int gizmo_cage2d_test_select(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const int mval[2])
{
float point_local[2];
float dims[2];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
if (gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+ C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
{
return -1;
}
float margin[2];
- gizmo_calc_rect_view_margin(mpr, dims, margin);
+ gizmo_calc_rect_view_margin(gz, dims, margin);
/* expand for hotspot */
const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
- const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
rctf r;
@@ -821,32 +821,32 @@ typedef struct RectTransformInteraction {
Dial *dial;
} RectTransformInteraction;
-static void gizmo_cage2d_setup(wmGizmo *mpr)
+static void gizmo_cage2d_setup(wmGizmo *gz)
{
- mpr->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE;
+ gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE;
}
static int gizmo_cage2d_invoke(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const wmEvent *event)
{
RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
- copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
- WM_gizmo_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
+ copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
+ WM_gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset);
if (gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
{
zero_v2(data->orig_mouse);
}
- mpr->interaction_data = data;
+ gz->interaction_data = data;
return OPERATOR_RUNNING_MODAL;
}
static int gizmo_cage2d_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
/* For transform logic to be managable we operate in -0.5..0.5 2D space,
@@ -856,40 +856,40 @@ static int gizmo_cage2d_modal(
* - The cursor offset are multiplied by 'dims'.
* - Matrix translation is also multiplied by 'dims'.
*/
- RectTransformInteraction *data = mpr->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
float point_local[2];
float dims[2];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
{
float matrix_back[4][4];
- copy_m4_m4(matrix_back, mpr->matrix_offset);
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(matrix_back, gz->matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
bool ok = gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
- copy_m4_m4(mpr->matrix_offset, matrix_back);
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
+ copy_m4_m4(gz->matrix_offset, matrix_back);
if (!ok) {
return OPERATOR_RUNNING_MODAL;
}
}
- const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
- wmGizmoProperty *mpr_prop;
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ wmGizmoProperty *gz_prop;
- mpr_prop = WM_gizmo_target_property_find(mpr, "matrix");
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
}
- if (mpr->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
+ if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
/* do this to prevent clamping from changing size */
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
- mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
- mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
+ gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
}
- else if (mpr->highlight_part == ED_GIZMO_CAGE2D_PART_ROTATE) {
+ else if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_ROTATE) {
#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0}))
@@ -915,28 +915,28 @@ static int gizmo_cage2d_modal(
copy_v3_v3(pivot, data->orig_matrix_offset[3]);
- invert_m4_m4(matrix_space_inv, mpr->matrix_space);
+ invert_m4_m4(matrix_space_inv, gz->matrix_space);
unit_m4(matrix_rotate);
mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
rotate_m4(matrix_rotate, 'Z', -angle);
- mul_m4_m4m4(matrix_rotate, matrix_rotate, mpr->matrix_space);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, gz->matrix_space);
zero_v3(matrix_rotate[3]);
transform_pivot_set_m4(matrix_rotate, pivot);
- mul_m4_m4m4(mpr->matrix_offset, matrix_rotate, data->orig_matrix_offset);
+ mul_m4_m4m4(gz->matrix_offset, matrix_rotate, data->orig_matrix_offset);
#undef MUL_V2_V3_M4_FINAL
}
else {
/* scale */
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
float pivot[2];
bool constrain_axis[2] = {false};
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- gizmo_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis);
+ gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
}
else {
zero_v2(pivot);
@@ -991,11 +991,11 @@ static int gizmo_cage2d_modal(
mul_v3_fl(matrix_scale[1], scale[1]);
transform_pivot_set_m4(matrix_scale, (const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], 0.0f});
- mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
}
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
}
/* tag the region for redraw */
@@ -1005,11 +1005,11 @@ static int gizmo_cage2d_modal(
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_cage2d_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop)
+static void gizmo_cage2d_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- if (STREQ(mpr_prop->type->idname, "matrix")) {
- if (WM_gizmo_target_property_array_length(mpr, mpr_prop) == 16) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ if (STREQ(gz_prop->type->idname, "matrix")) {
+ if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
}
else {
BLI_assert(0);
@@ -1020,24 +1020,24 @@ static void gizmo_cage2d_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop
}
}
-static void gizmo_cage2d_exit(bContext *C, wmGizmo *mpr, const bool cancel)
+static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- RectTransformInteraction *data = mpr->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
MEM_SAFE_FREE(data->dial);
if (!cancel)
return;
- wmGizmoProperty *mpr_prop;
+ wmGizmoProperty *gz_prop;
/* reset properties */
- mpr_prop = WM_gizmo_target_property_find(mpr, "matrix");
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]);
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
}
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
}
@@ -1046,23 +1046,23 @@ static void gizmo_cage2d_exit(bContext *C, wmGizmo *mpr, const bool cancel)
*
* \{ */
-static void GIZMO_WT_cage_2d(wmGizmoType *wt)
+static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_cage_2d";
+ gzt->idname = "GIZMO_GT_cage_2d";
/* api callbacks */
- wt->draw = gizmo_cage2d_draw;
- wt->draw_select = gizmo_cage2d_draw_select;
- wt->test_select = gizmo_cage2d_test_select;
- wt->setup = gizmo_cage2d_setup;
- wt->invoke = gizmo_cage2d_invoke;
- wt->property_update = gizmo_cage2d_property_update;
- wt->modal = gizmo_cage2d_modal;
- wt->exit = gizmo_cage2d_exit;
- wt->cursor_get = gizmo_cage2d_get_cursor;
-
- wt->struct_size = sizeof(wmGizmo);
+ gzt->draw = gizmo_cage2d_draw;
+ gzt->draw_select = gizmo_cage2d_draw_select;
+ gzt->test_select = gizmo_cage2d_test_select;
+ gzt->setup = gizmo_cage2d_setup;
+ gzt->invoke = gizmo_cage2d_invoke;
+ gzt->property_update = gizmo_cage2d_property_update;
+ gzt->modal = gizmo_cage2d_modal;
+ gzt->exit = gizmo_cage2d_exit;
+ gzt->cursor_get = gizmo_cage2d_get_cursor;
+
+ gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
@@ -1082,19 +1082,19 @@ static void GIZMO_WT_cage_2d(wmGizmoType *wt)
{0, NULL, 0, NULL, NULL}
};
static float unit_v2[2] = {1.0f, 1.0f};
- RNA_def_float_vector(wt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
- RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
+ RNA_def_float_vector(gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
RNA_def_enum_flag(
- wt->srna, "draw_options", rna_enum_draw_options,
+ gzt->srna, "draw_options", rna_enum_draw_options,
ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
- WM_gizmotype_target_property_def(wt, "matrix", PROP_FLOAT, 16);
+ WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
}
void ED_gizmotypes_cage_2d(void)
{
- WM_gizmotype_append(GIZMO_WT_cage_2d);
+ WM_gizmotype_append(GIZMO_GT_cage_2d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
index e266514855b..0f1d309c927 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
@@ -67,7 +67,7 @@
#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
static void gizmo_calc_matrix_final_no_offset(
- const wmGizmo *mpr, float orig_matrix_final_no_offset[4][4], bool use_space)
+ const wmGizmo *gz, float orig_matrix_final_no_offset[4][4], bool use_space)
{
float mat_identity[4][4];
struct WM_GizmoMatrixParams params = {NULL};
@@ -76,11 +76,11 @@ static void gizmo_calc_matrix_final_no_offset(
params.matrix_basis = mat_identity;
}
params.matrix_offset = mat_identity;
- WM_gizmo_calc_matrix_final_params(mpr, &params, orig_matrix_final_no_offset);
+ WM_gizmo_calc_matrix_final_params(gz, &params, orig_matrix_final_no_offset);
}
static void gizmo_calc_rect_view_scale(
- const wmGizmo *mpr, const float dims[3], float scale[3])
+ const wmGizmo *gz, const float dims[3], float scale[3])
{
UNUSED_VARS(dims);
@@ -88,10 +88,10 @@ static void gizmo_calc_rect_view_scale(
float matrix_final_no_offset[4][4];
float x_axis[3], y_axis[3], z_axis[3];
- gizmo_calc_matrix_final_no_offset(mpr, matrix_final_no_offset, false);
- mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
- mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
- mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, mpr->matrix_offset[2]);
+ gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset, false);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
+ mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, gz->matrix_offset[2]);
scale[0] = 1.0f / len_v3(x_axis);
scale[1] = 1.0f / len_v3(y_axis);
@@ -99,20 +99,20 @@ static void gizmo_calc_rect_view_scale(
}
static void gizmo_calc_rect_view_margin(
- const wmGizmo *mpr, const float dims[3], float margin[3])
+ const wmGizmo *gz, const float dims[3], float margin[3])
{
float handle_size;
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
handle_size = 0.15f;
}
else {
handle_size = GIZMO_RESIZER_SIZE;
}
// XXX, the scale isn't taking offset into account, we need to calculate scale per handle!
- // handle_size *= mpr->scale_final;
+ // handle_size *= gz->scale_final;
float scale_xyz[3];
- gizmo_calc_rect_view_scale(mpr, dims, scale_xyz);
+ gizmo_calc_rect_view_scale(gz, dims, scale_xyz);
margin[0] = ((handle_size * scale_xyz[0]));
margin[1] = ((handle_size * scale_xyz[1]));
margin[2] = ((handle_size * scale_xyz[2]));
@@ -150,7 +150,7 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_con
static void cage3d_draw_box_corners(
const float r[3], const float margin[3], const float color[3])
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
UNUSED_VARS(margin);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -185,7 +185,7 @@ static void cage3d_draw_box_interaction(
const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3fv(color);
imm_draw_cube_fill_3d(pos, co, rad);
@@ -217,7 +217,7 @@ static void cage3d_draw_circle_wire(
const float r[3], const float margin[3], const float color[3],
const int transform_flag, const int draw_options)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3fv(color);
@@ -230,7 +230,7 @@ static void cage3d_draw_circle_wire(
const float rad[2] = {margin[0] / 2, margin[1] / 2};
const float center[2] = {0.0f, 0.0f};
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
@@ -251,7 +251,7 @@ static void cage3d_draw_circle_handles(
const float r[3], const float margin[3], const float color[3],
bool solid, float scale)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -281,31 +281,31 @@ static void cage3d_draw_circle_handles(
static void gizmo_cage3d_draw_intern(
RegionView3D *rv3d,
- wmGizmo *mpr, const bool select, const bool highlight, const int select_id)
+ wmGizmo *gz, const bool select, const bool highlight, const int select_id)
{
- // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
+ // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
float dims[3];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
float matrix_final[4][4];
- const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
- const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
const float size_real[3] = {dims[0] / 2.0f, dims[1] / 2.0f, dims[2] / 2.0f};
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
float margin[3];
- gizmo_calc_rect_view_margin(mpr, dims, margin);
+ gizmo_calc_rect_view_margin(gz, dims, margin);
/* Handy for quick testing draw (if it's outside bounds). */
if (false) {
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
float s = 0.5f;
@@ -338,14 +338,14 @@ static void gizmo_cage3d_draw_intern(
}
GPU_select_load_id(select_id | i);
cage3d_draw_box_interaction(
- mpr->color, i, size, margin);
+ gz->color, i, size, margin);
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
const int transform_part = ED_GIZMO_CAGE3D_PART_TRANSLATE;
GPU_select_load_id(select_id | transform_part);
cage3d_draw_box_interaction(
- mpr->color, transform_part, size, margin);
+ gz->color, transform_part, size, margin);
}
}
else {
@@ -359,17 +359,17 @@ static void gizmo_cage3d_draw_intern(
#endif
if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
/* corner gizmos */
- GPU_line_width(mpr->line_width + 3.0f);
+ GPU_line_width(gz->line_width + 3.0f);
cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
/* corner gizmos */
float color[4];
- gizmo_color_get(mpr, highlight, color);
- GPU_line_width(mpr->line_width);
+ gizmo_color_get(gz, highlight, color);
+ GPU_line_width(gz->line_width);
cage3d_draw_box_corners(size_real, margin, color);
bool show = false;
- if (mpr->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
+ if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
/* Only show if we're drawing the center handle
* otherwise the entire rectangle is the hotspot. */
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
@@ -382,20 +382,20 @@ static void gizmo_cage3d_draw_intern(
if (show) {
cage3d_draw_box_interaction(
- mpr->color, mpr->highlight_part, size_real, margin);
+ gz->color, gz->highlight_part, size_real, margin);
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
float color[4];
- gizmo_color_get(mpr, highlight, color);
+ gizmo_color_get(gz, highlight, color);
GPU_line_smooth(true);
GPU_polygon_smooth(true);
GPU_blend(true);
- GPU_line_width(mpr->line_width + 3.0f);
+ GPU_line_width(gz->line_width + 3.0f);
cage3d_draw_circle_wire(size_real, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
cage3d_draw_circle_wire(size_real, margin, color, transform_flag, draw_options);
/* corner gizmos */
@@ -412,30 +412,30 @@ static void gizmo_cage3d_draw_intern(
}
GPU_line_width(1.0);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/**
* For when we want to draw 3d cage in 3d views.
*/
-static void gizmo_cage3d_draw_select(const bContext *C, wmGizmo *mpr, int select_id)
+static void gizmo_cage3d_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- gizmo_cage3d_draw_intern(rv3d, mpr, true, false, select_id);
+ gizmo_cage3d_draw_intern(rv3d, gz, true, false, select_id);
}
-static void gizmo_cage3d_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_cage3d_draw(const bContext *C, wmGizmo *gz)
{
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
- gizmo_cage3d_draw_intern(rv3d, mpr, false, is_highlight, -1);
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ gizmo_cage3d_draw_intern(rv3d, gz, false, is_highlight, -1);
}
-static int gizmo_cage3d_get_cursor(wmGizmo *mpr)
+static int gizmo_cage3d_get_cursor(wmGizmo *gz)
{
- if (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
return BC_NSEW_SCROLLCURSOR;
}
@@ -448,33 +448,33 @@ typedef struct RectTransformInteraction {
float orig_matrix_final_no_offset[4][4];
} RectTransformInteraction;
-static void gizmo_cage3d_setup(wmGizmo *mpr)
+static void gizmo_cage3d_setup(wmGizmo *gz)
{
- mpr->flag |= /* WM_GIZMO_DRAW_MODAL | */ /* TODO */
+ gz->flag |= /* WM_GIZMO_DRAW_MODAL | */ /* TODO */
WM_GIZMO_DRAW_NO_SCALE;
}
static int gizmo_cage3d_invoke(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const wmEvent *event)
{
RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
- copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
- gizmo_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset, true);
+ copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
+ gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset, true);
if (gizmo_window_project_3d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, false, data->orig_mouse) == 0)
+ C, gz, (const float[2]){UNPACK2(event->mval)}, false, data->orig_mouse) == 0)
{
zero_v3(data->orig_mouse);
}
- mpr->interaction_data = data;
+ gz->interaction_data = data;
return OPERATOR_RUNNING_MODAL;
}
static int gizmo_cage3d_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
/* For transform logic to be managable we operate in -0.5..0.5 2D space,
@@ -484,51 +484,51 @@ static int gizmo_cage3d_modal(
* - The cursor offset are multiplied by 'dims'.
* - Matrix translation is also multiplied by 'dims'.
*/
- RectTransformInteraction *data = mpr->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
float point_local[3];
float dims[3];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
{
float matrix_back[4][4];
- copy_m4_m4(matrix_back, mpr->matrix_offset);
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(matrix_back, gz->matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
bool ok = gizmo_window_project_3d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, false, point_local);
- copy_m4_m4(mpr->matrix_offset, matrix_back);
+ C, gz, (const float[2]){UNPACK2(event->mval)}, false, point_local);
+ copy_m4_m4(gz->matrix_offset, matrix_back);
if (!ok) {
return OPERATOR_RUNNING_MODAL;
}
}
- const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
- wmGizmoProperty *mpr_prop;
+ const int transform_flag = RNA_enum_get(gz->ptr, "transform");
+ wmGizmoProperty *gz_prop;
- mpr_prop = WM_gizmo_target_property_find(mpr, "matrix");
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
}
- if (mpr->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
+ if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
/* do this to prevent clamping from changing size */
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
- mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
- mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
- mpr->matrix_offset[3][2] = data->orig_matrix_offset[3][2] + (point_local[2] - data->orig_mouse[2]);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
+ gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
+ gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
+ gz->matrix_offset[3][2] = data->orig_matrix_offset[3][2] + (point_local[2] - data->orig_mouse[2]);
}
- else if (mpr->highlight_part == ED_GIZMO_CAGE3D_PART_ROTATE) {
+ else if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_ROTATE) {
/* TODO (if needed) */
}
else {
/* scale */
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
float pivot[3];
bool constrain_axis[3] = {false};
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
- gizmo_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis);
+ gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
}
else {
zero_v3(pivot);
@@ -587,11 +587,11 @@ static int gizmo_cage3d_modal(
transform_pivot_set_m4(
matrix_scale,
(const float[3]){pivot[0] * dims[0], pivot[1] * dims[1], pivot[2] * dims[2]});
- mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ mul_m4_m4m4(gz->matrix_offset, data->orig_matrix_offset, matrix_scale);
}
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
}
/* tag the region for redraw */
@@ -601,11 +601,11 @@ static int gizmo_cage3d_modal(
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_cage3d_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop)
+static void gizmo_cage3d_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- if (STREQ(mpr_prop->type->idname, "matrix")) {
- if (WM_gizmo_target_property_array_length(mpr, mpr_prop) == 16) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ if (STREQ(gz_prop->type->idname, "matrix")) {
+ if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, &gz->matrix_offset[0][0]);
}
else {
BLI_assert(0);
@@ -616,22 +616,22 @@ static void gizmo_cage3d_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop
}
}
-static void gizmo_cage3d_exit(bContext *C, wmGizmo *mpr, const bool cancel)
+static void gizmo_cage3d_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- RectTransformInteraction *data = mpr->interaction_data;
+ RectTransformInteraction *data = gz->interaction_data;
if (!cancel)
return;
- wmGizmoProperty *mpr_prop;
+ wmGizmoProperty *gz_prop;
/* reset properties */
- mpr_prop = WM_gizmo_target_property_find(mpr, "matrix");
- if (mpr_prop->type != NULL) {
- WM_gizmo_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]);
+ gz_prop = WM_gizmo_target_property_find(gz, "matrix");
+ if (gz_prop->type != NULL) {
+ WM_gizmo_target_property_value_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
}
- copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
}
@@ -640,22 +640,22 @@ static void gizmo_cage3d_exit(bContext *C, wmGizmo *mpr, const bool cancel)
*
* \{ */
-static void GIZMO_WT_cage_3d(wmGizmoType *wt)
+static void GIZMO_GT_cage_3d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_cage_3d";
+ gzt->idname = "GIZMO_GT_cage_3d";
/* api callbacks */
- wt->draw = gizmo_cage3d_draw;
- wt->draw_select = gizmo_cage3d_draw_select;
- wt->setup = gizmo_cage3d_setup;
- wt->invoke = gizmo_cage3d_invoke;
- wt->property_update = gizmo_cage3d_property_update;
- wt->modal = gizmo_cage3d_modal;
- wt->exit = gizmo_cage3d_exit;
- wt->cursor_get = gizmo_cage3d_get_cursor;
+ gzt->draw = gizmo_cage3d_draw;
+ gzt->draw_select = gizmo_cage3d_draw_select;
+ gzt->setup = gizmo_cage3d_setup;
+ gzt->invoke = gizmo_cage3d_invoke;
+ gzt->property_update = gizmo_cage3d_property_update;
+ gzt->modal = gizmo_cage3d_modal;
+ gzt->exit = gizmo_cage3d_exit;
+ gzt->cursor_get = gizmo_cage3d_get_cursor;
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
@@ -674,19 +674,19 @@ static void GIZMO_WT_cage_3d(wmGizmoType *wt)
{0, NULL, 0, NULL, NULL}
};
static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
- RNA_def_float_vector(wt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
- RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
+ RNA_def_float_vector(gzt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
RNA_def_enum_flag(
- wt->srna, "draw_options", rna_enum_draw_options,
+ gzt->srna, "draw_options", rna_enum_draw_options,
ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
- WM_gizmotype_target_property_def(wt, "matrix", PROP_FLOAT, 16);
+ WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
}
void ED_gizmotypes_cage_3d(void)
{
- WM_gizmotype_append(GIZMO_WT_cage_3d);
+ WM_gizmotype_append(GIZMO_GT_cage_3d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
index b93b87b1efa..8e04703c14e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -71,7 +71,7 @@
// #define USE_GIZMO_CUSTOM_DIAL
static int gizmo_dial_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak tweak_flag);
typedef struct DialInteraction {
@@ -101,33 +101,33 @@ typedef struct DialInteraction {
/**
* We can't use this for the #wmGizmoType.matrix_basis_get callback, it conflicts with depth picking.
*/
-static void dial_calc_matrix(const wmGizmo *mpr, float mat[4][4])
+static void dial_calc_matrix(const wmGizmo *gz, float mat[4][4])
{
float rot[3][3];
const float up[3] = {0.0f, 0.0f, 1.0f};
- rotation_between_vecs_to_mat3(rot, up, mpr->matrix_basis[2]);
+ rotation_between_vecs_to_mat3(rot, up, gz->matrix_basis[2]);
copy_m4_m3(mat, rot);
- copy_v3_v3(mat[3], mpr->matrix_basis[3]);
+ copy_v3_v3(mat[3], gz->matrix_basis[3]);
}
/* -------------------------------------------------------------------- */
static void dial_geom_draw(
- const wmGizmo *mpr, const float color[4], const bool select,
+ const wmGizmo *gz, const float color[4], const bool select,
float axis_modal_mat[4][4], float clip_plane[4])
{
#ifdef USE_GIZMO_CUSTOM_DIAL
UNUSED_VARS(dial, col, axis_modal_mat, clip_plane);
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select);
#else
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
const bool filled = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_FILL) != 0;
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (clip_plane) {
immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR);
@@ -161,32 +161,32 @@ static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[
{
GPU_line_width(1.0f);
- gpuPushMatrix();
- gpuRotate3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
+ GPU_matrix_push();
+ GPU_matrix_rotate_3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(color);
- immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immBegin(GPU_PRIM_LINE_STRIP, 2);
immVertex3f(pos, 0.0f, 0.0f, 0.0f);
immVertex3fv(pos, co_outer);
immEnd();
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
static void dial_ghostarc_draw(
- const wmGizmo *mpr, const float angle_ofs, const float angle_delta, const float color[4])
+ const wmGizmo *gz, const float angle_ofs, const float angle_delta, const float color[4])
{
- const float width_inner = DIAL_WIDTH - mpr->line_width * 0.5f / U.gizmo_size;
+ const float width_inner = DIAL_WIDTH - gz->line_width * 0.5f / U.gizmo_size;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(color);
imm_draw_disk_partial_fill_2d(
@@ -196,24 +196,24 @@ static void dial_ghostarc_draw(
static void dial_ghostarc_get_angles(
struct Depsgraph *depsgraph,
- const wmGizmo *mpr,
+ const wmGizmo *gz,
const wmEvent *event,
const ARegion *ar, const View3D *v3d,
float mat[4][4], const float co_outer[3],
float *r_start, float *r_delta)
{
- DialInteraction *inter = mpr->interaction_data;
+ DialInteraction *inter = gz->interaction_data;
const RegionView3D *rv3d = ar->regiondata;
const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
/* we might need to invert the direction of the angles */
float view_vec[3], axis_vec[3];
- ED_view3d_global_to_vector(rv3d, mpr->matrix_basis[3], view_vec);
- normalize_v3_v3(axis_vec, mpr->matrix_basis[2]);
+ ED_view3d_global_to_vector(rv3d, gz->matrix_basis[3], view_vec);
+ normalize_v3_v3(axis_vec, gz->matrix_basis[2]);
float proj_outer_rel[3];
mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer);
- sub_v3_v3(proj_outer_rel, mpr->matrix_basis[3]);
+ sub_v3_v3(proj_outer_rel, gz->matrix_basis[3]);
float proj_mval_new_rel[3];
float proj_mval_init_rel[3];
@@ -221,7 +221,7 @@ static void dial_ghostarc_get_angles(
float ray_co[3], ray_no[3];
float ray_lambda;
- plane_from_point_normal_v3(dial_plane, mpr->matrix_basis[3], axis_vec);
+ plane_from_point_normal_v3(dial_plane, gz->matrix_basis[3], axis_vec);
if (!ED_view3d_win_to_ray(depsgraph, ar, v3d, inter->init_mval, ray_co, ray_no, false) ||
!isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
@@ -229,7 +229,7 @@ static void dial_ghostarc_get_angles(
goto fail;
}
madd_v3_v3v3fl(proj_mval_init_rel, ray_co, ray_no, ray_lambda);
- sub_v3_v3(proj_mval_init_rel, mpr->matrix_basis[3]);
+ sub_v3_v3(proj_mval_init_rel, gz->matrix_basis[3]);
if (!ED_view3d_win_to_ray(depsgraph, ar, v3d, mval, ray_co, ray_no, false) ||
!isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
@@ -237,14 +237,14 @@ static void dial_ghostarc_get_angles(
goto fail;
}
madd_v3_v3v3fl(proj_mval_new_rel, ray_co, ray_no, ray_lambda);
- sub_v3_v3(proj_mval_new_rel, mpr->matrix_basis[3]);
+ sub_v3_v3(proj_mval_new_rel, gz->matrix_basis[3]);
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
/* Start direction from mouse or set by user */
const float *proj_init_rel =
(draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y) ?
- mpr->matrix_basis[1] : proj_mval_init_rel;
+ gz->matrix_basis[1] : proj_mval_init_rel;
/* return angles */
const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec));
@@ -274,7 +274,7 @@ fail:
}
static void dial_draw_intern(
- const bContext *C, wmGizmo *mpr,
+ const bContext *C, wmGizmo *gz,
const bool select, const bool highlight, float clip_plane[4])
{
float matrix_basis_adjust[4][4];
@@ -283,30 +283,30 @@ static void dial_draw_intern(
BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
- gizmo_color_get(mpr, highlight, color);
+ gizmo_color_get(gz, highlight, color);
- dial_calc_matrix(mpr, matrix_basis_adjust);
+ dial_calc_matrix(gz, matrix_basis_adjust);
WM_gizmo_calc_matrix_final_params(
- mpr, &((struct WM_GizmoMatrixParams) {
+ gz, &((struct WM_GizmoMatrixParams) {
.matrix_basis = (void *)matrix_basis_adjust,
}), matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
/* draw rotation indicator arc first */
- if ((mpr->flag & WM_GIZMO_DRAW_VALUE) &&
- (mpr->state & WM_GIZMO_STATE_MODAL))
+ if ((gz->flag & WM_GIZMO_DRAW_VALUE) &&
+ (gz->state & WM_GIZMO_STATE_MODAL))
{
const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
- DialInteraction *inter = mpr->interaction_data;
+ DialInteraction *inter = gz->interaction_data;
/* XXX, View3D rotation gizmo doesn't call modal. */
- if (!WM_gizmo_target_property_is_valid_any(mpr)) {
+ if (!WM_gizmo_target_property_is_valid_any(gz)) {
wmWindow *win = CTX_wm_window(C);
- gizmo_dial_modal((bContext *)C, mpr, win->eventstate, 0);
+ gizmo_dial_modal((bContext *)C, gz, win->eventstate, 0);
}
float angle_ofs = inter->output.angle_ofs;
@@ -315,14 +315,14 @@ static void dial_draw_intern(
/* draw! */
for (int i = 0; i < 2; i++) {
GPU_polygon_smooth(false);
- dial_ghostarc_draw(mpr, angle_ofs, angle_delta, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
+ dial_ghostarc_draw(gz, angle_ofs, angle_delta, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
GPU_polygon_smooth(true);
dial_ghostarc_draw_helpline(angle_ofs, co_outer, color); /* starting position */
dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color); /* starting position + current value */
if (i == 0) {
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if ((draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) == 0) {
break;
}
@@ -333,15 +333,15 @@ static void dial_draw_intern(
}
/* draw actual dial gizmo */
- dial_geom_draw(mpr, color, select, matrix_basis_adjust, clip_plane);
+ dial_geom_draw(gz, color, select, matrix_basis_adjust, clip_plane);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
-static void gizmo_dial_draw_select(const bContext *C, wmGizmo *mpr, int select_id)
+static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
float clip_plane_buf[4];
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
float *clip_plane = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL;
/* enable clipping if needed */
@@ -350,25 +350,25 @@ static void gizmo_dial_draw_select(const bContext *C, wmGizmo *mpr, int select_i
RegionView3D *rv3d = ar->regiondata;
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
- clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
- clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS * gz->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
GPU_select_load_id(select_id);
- dial_draw_intern(C, mpr, true, false, clip_plane);
+ dial_draw_intern(C, gz, true, false, clip_plane);
if (clip_plane) {
glDisable(GL_CLIP_DISTANCE0);
}
}
-static void gizmo_dial_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_dial_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = mpr->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
float clip_plane_buf[4];
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
float *clip_plane = (!is_modal && (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP)) ? clip_plane_buf : NULL;
/* enable clipping if needed */
@@ -377,14 +377,14 @@ static void gizmo_dial_draw(const bContext *C, wmGizmo *mpr)
RegionView3D *rv3d = ar->regiondata;
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
- clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
- clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS * gz->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
GPU_blend(true);
- dial_draw_intern(C, mpr, false, is_highlight, clip_plane);
+ dial_draw_intern(C, gz, false, is_highlight, clip_plane);
GPU_blend(false);
if (clip_plane) {
@@ -393,7 +393,7 @@ static void gizmo_dial_draw(const bContext *C, wmGizmo *mpr)
}
static int gizmo_dial_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
@@ -401,48 +401,48 @@ static int gizmo_dial_modal(
float matrix[4][4];
- dial_calc_matrix(mpr, matrix);
+ dial_calc_matrix(gz, matrix);
dial_ghostarc_get_angles(
CTX_data_depsgraph(C),
- mpr, event, CTX_wm_region(C), CTX_wm_view3d(C), matrix, co_outer, &angle_ofs, &angle_delta);
+ gz, event, CTX_wm_region(C), CTX_wm_view3d(C), matrix, co_outer, &angle_ofs, &angle_delta);
- DialInteraction *inter = mpr->interaction_data;
+ DialInteraction *inter = gz->interaction_data;
inter->output.angle_delta = angle_delta;
inter->output.angle_ofs = angle_ofs;
/* set the property for the operator and call its modal function */
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- WM_gizmo_target_property_value_set(C, mpr, mpr_prop, inter->init_prop_angle + angle_delta);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_value_set(C, gz, gz_prop, inter->init_prop_angle + angle_delta);
}
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_dial_setup(wmGizmo *mpr)
+static void gizmo_dial_setup(wmGizmo *gz)
{
const float dir_default[3] = {0.0f, 0.0f, 1.0f};
/* defaults */
- copy_v3_v3(mpr->matrix_basis[2], dir_default);
+ copy_v3_v3(gz->matrix_basis[2], dir_default);
}
static int gizmo_dial_invoke(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
inter->init_mval[0] = event->mval[0];
inter->init_mval[1] = event->mval[1];
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- inter->init_prop_angle = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ inter->init_prop_angle = WM_gizmo_target_property_value_get(gz, gz_prop);
}
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
}
@@ -452,19 +452,19 @@ static int gizmo_dial_invoke(
*
* \{ */
-static void GIZMO_WT_dial_3d(wmGizmoType *wt)
+static void GIZMO_GT_dial_3d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_dial_3d";
+ gzt->idname = "GIZMO_GT_dial_3d";
/* api callbacks */
- wt->draw = gizmo_dial_draw;
- wt->draw_select = gizmo_dial_draw_select;
- wt->setup = gizmo_dial_setup;
- wt->invoke = gizmo_dial_invoke;
- wt->modal = gizmo_dial_modal;
+ gzt->draw = gizmo_dial_draw;
+ gzt->draw_select = gizmo_dial_draw_select;
+ gzt->setup = gizmo_dial_setup;
+ gzt->invoke = gizmo_dial_invoke;
+ gzt->modal = gizmo_dial_modal;
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_options[] = {
@@ -474,14 +474,14 @@ static void GIZMO_WT_dial_3d(wmGizmoType *wt)
{ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""},
{0, NULL, 0, NULL, NULL}
};
- RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- WM_gizmotype_target_property_def(wt, "offset", PROP_FLOAT, 1);
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
}
void ED_gizmotypes_dial_3d(void)
{
- WM_gizmotype_append(GIZMO_WT_dial_3d);
+ WM_gizmotype_append(GIZMO_GT_dial_3d);
}
/** \} */
diff --git a/source/blender/editors/gizmo_library/gizmo_types/grab3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/grab3d_gizmo.c
index 2a89c8cc4ab..fcbd333078d 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/grab3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/grab3d_gizmo.c
@@ -68,16 +68,16 @@ typedef struct GrabGizmo3D {
float prop_co[3];
} GrabGizmo3D;
-static void gizmo_grab_matrix_basis_get(const wmGizmo *mpr, float r_matrix[4][4])
+static void gizmo_grab_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4])
{
- GrabGizmo3D *grab = (GrabGizmo3D *)mpr;
+ GrabGizmo3D *grab = (GrabGizmo3D *)gz;
copy_m4_m4(r_matrix, grab->gizmo.matrix_basis);
add_v3_v3(r_matrix[3], grab->prop_co);
}
static int gizmo_grab_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak tweak_flag);
typedef struct GrabInteraction {
@@ -94,19 +94,19 @@ typedef struct GrabInteraction {
/* -------------------------------------------------------------------- */
static void grab_geom_draw(
- const wmGizmo *mpr, const float color[4], const bool select, const int draw_options)
+ const wmGizmo *gz, const float color[4], const bool select, const int draw_options)
{
#ifdef USE_GIZMO_CUSTOM_DIAL
UNUSED_VARS(grab3d, col, axis_modal_mat);
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_grab3d, select);
#else
- const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
const bool filled = (draw_options & ED_GIZMO_GRAB_DRAW_FLAG_FILL) != 0;
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -121,7 +121,7 @@ static void grab_geom_draw(
}
}
else if (draw_style == ED_GIZMO_GRAB_STYLE_CROSS_2D) {
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, 1.0f, 1.0f);
immVertex2f(pos, -1.0f, -1.0f);
@@ -140,10 +140,10 @@ static void grab_geom_draw(
}
static void grab3d_get_translate(
- const wmGizmo *mpr, const wmEvent *event, const ARegion *ar,
+ const wmGizmo *gz, const wmEvent *event, const ARegion *ar,
float co_delta[3])
{
- GrabInteraction *inter = mpr->interaction_data;
+ GrabInteraction *inter = gz->interaction_data;
const float mval_delta[2] = {
event->mval[0] - inter->init_mval[0],
event->mval[1] - inter->init_mval[1],
@@ -151,33 +151,33 @@ static void grab3d_get_translate(
RegionView3D *rv3d = ar->regiondata;
float co_ref[3];
- mul_v3_mat3_m4v3(co_ref, mpr->matrix_space, inter->init_prop_co);
+ mul_v3_mat3_m4v3(co_ref, gz->matrix_space, inter->init_prop_co);
const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
ED_view3d_win_to_delta(ar, mval_delta, co_delta, zfac);
float matrix_space_inv[3][3];
- copy_m3_m4(matrix_space_inv, mpr->matrix_space);
+ copy_m3_m4(matrix_space_inv, gz->matrix_space);
invert_m3(matrix_space_inv);
mul_m3_v3(matrix_space_inv, co_delta);
}
static void grab3d_draw_intern(
- const bContext *C, wmGizmo *mpr,
+ const bContext *C, wmGizmo *gz,
const bool select, const bool highlight)
{
- GrabInteraction *inter = mpr->interaction_data;
- const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ GrabInteraction *inter = gz->interaction_data;
+ const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
const bool align_view = (draw_options & ED_GIZMO_GRAB_DRAW_FLAG_ALIGN_VIEW) != 0;
float color[4];
float matrix_final[4][4];
float matrix_align[4][4];
- gizmo_color_get(mpr, highlight, color);
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ gizmo_color_get(gz, highlight, color);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
if (align_view) {
float matrix_final_unit[4][4];
@@ -186,65 +186,65 @@ static void grab3d_draw_intern(
mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
zero_v3(matrix_align[3]);
transpose_m4(matrix_align);
- gpuMultMatrix(matrix_align);
+ GPU_matrix_mul(matrix_align);
}
GPU_blend(true);
- grab_geom_draw(mpr, color, select, draw_options);
+ grab_geom_draw(gz, color, select, draw_options);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
- if (mpr->interaction_data) {
- gpuPushMatrix();
- gpuMultMatrix(inter->init_matrix_final);
+ if (gz->interaction_data) {
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init_matrix_final);
if (align_view) {
- gpuMultMatrix(matrix_align);
+ GPU_matrix_mul(matrix_align);
}
GPU_blend(true);
- grab_geom_draw(mpr, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
+ grab_geom_draw(gz, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
-static void gizmo_grab_draw_select(const bContext *C, wmGizmo *mpr, int select_id)
+static void gizmo_grab_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
GPU_select_load_id(select_id);
- grab3d_draw_intern(C, mpr, true, false);
+ grab3d_draw_intern(C, gz, true, false);
}
-static void gizmo_grab_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_grab_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = mpr->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
(void)is_modal;
GPU_blend(true);
- grab3d_draw_intern(C, mpr, false, is_highlight);
+ grab3d_draw_intern(C, gz, false, is_highlight);
GPU_blend(false);
}
static int gizmo_grab_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- GrabGizmo3D *grab = (GrabGizmo3D *)mpr;
- GrabInteraction *inter = mpr->interaction_data;
+ GrabGizmo3D *grab = (GrabGizmo3D *)gz;
+ GrabInteraction *inter = gz->interaction_data;
ARegion *ar = CTX_wm_region(C);
float prop_delta[3];
if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
- grab3d_get_translate(mpr, event, ar, prop_delta);
+ grab3d_get_translate(gz, event, ar, prop_delta);
}
else {
float mval_proj_init[2], mval_proj_curr[2];
if ((gizmo_window_project_2d(
- C, mpr, inter->init_mval, 2, false, mval_proj_init) == false) ||
+ C, gz, inter->init_mval, 2, false, mval_proj_init) == false) ||
(gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false))
+ C, gz, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false))
{
return OPERATOR_RUNNING_MODAL;
}
@@ -254,9 +254,9 @@ static int gizmo_grab_modal(
add_v3_v3v3(grab->prop_co, inter->init_prop_co, prop_delta);
/* set the property for the operator and call its modal function */
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- WM_gizmo_target_property_value_set_array(C, mpr, mpr_prop, grab->prop_co);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_value_set_array(C, gz, gz_prop, grab->prop_co);
}
else {
zero_v3(grab->prop_co);
@@ -268,7 +268,7 @@ static int gizmo_grab_modal(
}
static int gizmo_grab_invoke(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
GrabInteraction *inter = MEM_callocN(sizeof(GrabInteraction), __func__);
@@ -278,32 +278,32 @@ static int gizmo_grab_invoke(
#if 0
copy_v3_v3(inter->init_prop_co, grab->prop_co);
#else
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_find(mpr, "offset");
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, inter->init_prop_co);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, inter->init_prop_co);
}
#endif
- WM_gizmo_calc_matrix_final(mpr, inter->init_matrix_final);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
}
static int gizmo_grab_test_select(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const int mval[2])
{
float point_local[2];
if (gizmo_window_project_2d(
- C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+ C, gz, (const float[2]){UNPACK2(mval)}, 2, true, point_local) == false)
{
return -1;
}
- /* The 'mpr->scale_final' is already applied when projecting. */
+ /* The 'gz->scale_final' is already applied when projecting. */
if (len_squared_v2(point_local) < 1.0f) {
return 0;
}
@@ -311,18 +311,18 @@ static int gizmo_grab_test_select(
return -1;
}
-static void gizmo_grab_property_update(wmGizmo *mpr, wmGizmoProperty *mpr_prop)
+static void gizmo_grab_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- GrabGizmo3D *grab = (GrabGizmo3D *)mpr;
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, grab->prop_co);
+ GrabGizmo3D *grab = (GrabGizmo3D *)gz;
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, grab->prop_co);
}
else {
zero_v3(grab->prop_co);
}
}
-static int gizmo_grab_cursor_get(wmGizmo *UNUSED(mpr))
+static int gizmo_grab_cursor_get(wmGizmo *UNUSED(gz))
{
return BC_NSEW_SCROLLCURSOR;
}
@@ -332,22 +332,22 @@ static int gizmo_grab_cursor_get(wmGizmo *UNUSED(mpr))
*
* \{ */
-static void GIZMO_WT_grab_3d(wmGizmoType *wt)
+static void GIZMO_GT_grab_3d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_grab_3d";
+ gzt->idname = "GIZMO_GT_grab_3d";
/* api callbacks */
- wt->draw = gizmo_grab_draw;
- wt->draw_select = gizmo_grab_draw_select;
- wt->test_select = gizmo_grab_test_select;
- wt->matrix_basis_get = gizmo_grab_matrix_basis_get;
- wt->invoke = gizmo_grab_invoke;
- wt->property_update = gizmo_grab_property_update;
- wt->modal = gizmo_grab_modal;
- wt->cursor_get = gizmo_grab_cursor_get;
+ gzt->draw = gizmo_grab_draw;
+ gzt->draw_select = gizmo_grab_draw_select;
+ gzt->test_select = gizmo_grab_test_select;
+ gzt->matrix_basis_get = gizmo_grab_matrix_basis_get;
+ gzt->invoke = gizmo_grab_invoke;
+ gzt->property_update = gizmo_grab_property_update;
+ gzt->modal = gizmo_grab_modal;
+ gzt->cursor_get = gizmo_grab_cursor_get;
- wt->struct_size = sizeof(GrabGizmo3D);
+ gzt->struct_size = sizeof(GrabGizmo3D);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
@@ -361,15 +361,15 @@ static void GIZMO_WT_grab_3d(wmGizmoType *wt)
{0, NULL, 0, NULL, NULL}
};
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_GRAB_STYLE_RING_2D, "Draw Style", "");
- RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_GRAB_STYLE_RING_2D, "Draw Style", "");
+ RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
- WM_gizmotype_target_property_def(wt, "offset", PROP_FLOAT, 3);
+ WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 3);
}
void ED_gizmotypes_grab_3d(void)
{
- WM_gizmotype_append(GIZMO_WT_grab_3d);
+ WM_gizmotype_append(GIZMO_GT_grab_3d);
}
/** \} */ // Grab Gizmo API
diff --git a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
index ff02517dafa..6443a6bf038 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c
@@ -77,83 +77,83 @@ static void gizmo_primitive_draw_geom(
}
if (vert_count > 0) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GWN_PRIM_TRI_FAN);
- wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GWN_PRIM_LINE_LOOP);
+ wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN);
+ wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP);
immUnbindProgram();
}
}
static void gizmo_primitive_draw_intern(
- wmGizmo *mpr, const bool UNUSED(select),
+ wmGizmo *gz, const bool UNUSED(select),
const bool highlight)
{
float color_inner[4], color_outer[4];
float matrix_final[4][4];
- const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+ const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
- gizmo_color_get(mpr, highlight, color_outer);
+ gizmo_color_get(gz, highlight, color_outer);
copy_v4_v4(color_inner, color_outer);
color_inner[3] *= 0.5f;
- WM_gizmo_calc_matrix_final(mpr, matrix_final);
+ WM_gizmo_calc_matrix_final(gz, matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
GPU_blend(true);
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
- if (mpr->interaction_data) {
- GizmoInteraction *inter = mpr->interaction_data;
+ if (gz->interaction_data) {
+ GizmoInteraction *inter = gz->interaction_data;
copy_v4_fl(color_inner, 0.5f);
copy_v3_fl(color_outer, 0.5f);
color_outer[3] = 0.8f;
- gpuPushMatrix();
- gpuMultMatrix(inter->init_matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(inter->init_matrix_final);
GPU_blend(true);
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
static void gizmo_primitive_draw_select(
- const bContext *UNUSED(C), wmGizmo *mpr,
+ const bContext *UNUSED(C), wmGizmo *gz,
int select_id)
{
GPU_select_load_id(select_id);
- gizmo_primitive_draw_intern(mpr, true, false);
+ gizmo_primitive_draw_intern(gz, true, false);
}
-static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *mpr)
+static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *gz)
{
gizmo_primitive_draw_intern(
- mpr, false,
- (mpr->state & WM_GIZMO_STATE_HIGHLIGHT));
+ gz, false,
+ (gz->state & WM_GIZMO_STATE_HIGHLIGHT));
}
-static void gizmo_primitive_setup(wmGizmo *mpr)
+static void gizmo_primitive_setup(wmGizmo *gz)
{
- mpr->flag |= WM_GIZMO_DRAW_MODAL;
+ gz->flag |= WM_GIZMO_DRAW_MODAL;
}
static int gizmo_primitive_invoke(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *UNUSED(event))
+ bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
{
GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
- WM_gizmo_calc_matrix_final(mpr, inter->init_matrix_final);
+ WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
}
@@ -163,29 +163,29 @@ static int gizmo_primitive_invoke(
*
* \{ */
-static void GIZMO_WT_primitive_3d(wmGizmoType *wt)
+static void GIZMO_GT_primitive_3d(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "GIZMO_WT_primitive_3d";
+ gzt->idname = "GIZMO_GT_primitive_3d";
/* api callbacks */
- wt->draw = gizmo_primitive_draw;
- wt->draw_select = gizmo_primitive_draw_select;
- wt->setup = gizmo_primitive_setup;
- wt->invoke = gizmo_primitive_invoke;
+ gzt->draw = gizmo_primitive_draw;
+ gzt->draw_select = gizmo_primitive_draw_select;
+ gzt->setup = gizmo_primitive_setup;
+ gzt->invoke = gizmo_primitive_invoke;
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
static EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
{0, NULL, 0, NULL, NULL}
};
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_PRIMITIVE_STYLE_PLANE, "Draw Style", "");
+ RNA_def_enum(gzt->srna, "draw_style", rna_enum_draw_style, ED_GIZMO_PRIMITIVE_STYLE_PLANE, "Draw Style", "");
}
void ED_gizmotypes_primitive_3d(void)
{
- WM_gizmotype_append(GIZMO_WT_primitive_3d);
+ WM_gizmotype_append(GIZMO_GT_primitive_3d);
}
/** \} */
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 587c25031ab..114e55c5704 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -39,18 +39,25 @@ set(INC_SYS
)
set(SRC
+ annotate_draw.c
+ annotate_paint.c
drawgpencil.c
editaction_gpencil.c
+ gpencil_add_monkey.c
+ gpencil_add_stroke.c
gpencil_brush.c
gpencil_convert.c
gpencil_data.c
gpencil_edit.c
gpencil_interpolate.c
+ gpencil_primitive.c
gpencil_ops.c
gpencil_paint.c
+ gpencil_fill.c
gpencil_select.c
gpencil_undo.c
gpencil_utils.c
+ gpencil_old.c
gpencil_intern.h
)
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
new file mode 100644
index 00000000000..4f6e2004197
--- /dev/null
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -0,0 +1,1066 @@
+/*
+ * ***** 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) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung, Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/annotate_draw.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_sys_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_polyfill_2d.h"
+
+#include "BLF_api.h"
+#include "BLT_translation.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+
+#include "WM_api.h"
+
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+#include "GPU_state.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_space_api.h"
+
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+
+/* ************************************************** */
+/* GREASE PENCIL DRAWING */
+
+/* ----- General Defines ------ */
+/* flags for sflag */
+typedef enum eDrawStrokeFlags {
+ GP_DRAWDATA_NOSTATUS = (1 << 0), /* don't draw status info */
+ GP_DRAWDATA_ONLY3D = (1 << 1), /* only draw 3d-strokes */
+ GP_DRAWDATA_ONLYV2D = (1 << 2), /* only draw 'canvas' strokes */
+ GP_DRAWDATA_ONLYI2D = (1 << 3), /* only draw 'image' strokes */
+ GP_DRAWDATA_IEDITHACK = (1 << 4), /* special hack for drawing strokes in Image Editor (weird coordinates) */
+ GP_DRAWDATA_NO_XRAY = (1 << 5), /* don't draw xray in 3D view (which is default) */
+ GP_DRAWDATA_NO_ONIONS = (1 << 6), /* no onionskins should be drawn (for animation playback) */
+} eDrawStrokeFlags;
+
+
+/* ----- Tool Buffer Drawing ------ */
+
+/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
+static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short thickness,
+ short dflag, short sflag, float ink[4])
+{
+ int draw_points = 0;
+
+ /* error checking */
+ if ((points == NULL) || (totpoints <= 0))
+ return;
+
+ /* check if buffer can be drawn */
+ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
+ return;
+
+ if (sflag & GP_STROKE_ERASER) {
+ /* don't draw stroke at all! */
+ return;
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+
+ const tGPspoint *pt = points;
+
+ if (totpoints == 1) {
+ /* if drawing a single point, draw it larger */
+ GPU_point_size((float)(thickness + 2) * points->pressure);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immUniformColor3fvAlpha(ink, ink[3]);
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex2iv(pos, &pt->x);
+ }
+ else {
+ float oldpressure = points[0].pressure;
+
+ /* draw stroke curve */
+ GPU_line_width(max_ff(oldpressure * thickness, 1.0));
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(ink, ink[3]);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
+
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
+ * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
+ */
+ if (fabsf(pt->pressure - oldpressure) > 0.2f) {
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ immVertex2iv(pos, &(pt - 1)->x);
+ }
+
+ immEnd();
+ draw_points = 0;
+
+ GPU_line_width(max_ff(pt->pressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
+
+ /* need to roll-back one point to ensure that there are no gaps in the stroke */
+ if (i != 0) {
+ immVertex2iv(pos, &(pt - 1)->x);
+ draw_points++;
+ }
+
+ oldpressure = pt->pressure; /* reset our threshold */
+ }
+
+ /* now the point we want */
+ immVertex2iv(pos, &pt->x);
+ draw_points++;
+ }
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ immVertex2iv(pos, &(pt - 1)->x);
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
+}
+
+/* --------- 2D Stroke Drawing Helpers --------- */
+/* change in parameter list */
+static void gp_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+{
+ if (sflag & GP_STROKE_2DSPACE) {
+ r_co[0] = pt[0];
+ r_co[1] = pt[1];
+ }
+ else if (sflag & GP_STROKE_2DIMAGE) {
+ const float x = (float)((pt[0] * winx) + offsx);
+ const float y = (float)((pt[1] * winy) + offsy);
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+ else {
+ const float x = (float)(pt[0] / 100 * winx) + offsx;
+ const float y = (float)(pt[1] / 100 * winy) + offsy;
+
+ r_co[0] = x;
+ r_co[1] = y;
+ }
+}
+
+/* ----- Existing Strokes Drawing (3D and Point) ------ */
+
+/* draw a given stroke - just a single dot (only one point) */
+static void gp_draw_stroke_point(
+ const bGPDspoint *points, short thickness, short UNUSED(dflag), short sflag,
+ int offsx, int offsy, int winx, int winy, const float ink[4])
+{
+ const bGPDspoint *pt = points;
+
+ /* get final position using parent matrix */
+ float fpt[3];
+ copy_v3_v3(fpt, &pt->x);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ if (sflag & GP_STROKE_3DSPACE) {
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ /* get 2D coordinates of point */
+ float co[3] = { 0.0f };
+ gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
+ copy_v3_v3(fpt, co);
+ }
+
+ /* set color */
+ immUniformColor3fvAlpha(ink, ink[3]);
+
+ /* set point thickness (since there's only one of these) */
+ immUniform1f("size", (float)(thickness + 2) * pt->pressure);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, fpt);
+ immEnd();
+
+ immUnbindProgram();
+}
+
+/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
+static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug),
+ short UNUSED(sflag), const float ink[4], bool cyclic)
+{
+ float curpressure = points[0].pressure;
+ float cyclic_fpt[3];
+ int draw_points = 0;
+
+ /* if cyclic needs one vertex more */
+ int cyclic_add = 0;
+ if (cyclic) {
+ cyclic_add++;
+ }
+
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(ink, ink[3]);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+
+ /* draw stroke curve */
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
+ * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
+ * Note: we want more visible levels of pressures when thickness is bigger.
+ */
+ if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
+ /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ }
+ immEnd();
+ draw_points = 0;
+
+ curpressure = pt->pressure;
+ GPU_line_width(max_ff(curpressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
+
+ /* need to roll-back one point to ensure that there are no gaps in the stroke */
+ if (i != 0) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ draw_points++;
+ }
+ }
+
+ /* now the point we want */
+ immVertex3fv(pos, &pt->x);
+ draw_points++;
+
+ if (cyclic && i == 0) {
+ /* save first point to use in cyclic */
+ copy_v3_v3(cyclic_fpt, &pt->x);
+ }
+ }
+
+ if (cyclic) {
+ /* draw line to first point to complete the cycle */
+ immVertex3fv(pos, cyclic_fpt);
+ draw_points++;
+ }
+
+ /* if less of two points, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ immVertex3fv(pos, &pt2->x);
+ }
+
+ immEnd();
+ immUnbindProgram();
+}
+
+/* ----- 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 UNUSED(debug), int offsx, int offsy, int winx, int winy, const float ink[4])
+{
+ /* otherwise thickness is twice that of the 3D view */
+ float thickness = (float)thickness_s * 0.5f;
+
+ /* strokes in Image Editor need a scale factor, since units there are not pixels! */
+ float scalefac = 1.0f;
+ if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
+ scalefac = 0.001f;
+ }
+
+ /* TODO: fancy++ with the magic of shaders */
+
+ /* tessellation code - draw stroke as series of connected quads (triangle strips in fact) with connection
+ * edges rotated to minimize shrinking artifacts, and rounded endcaps
+ */
+ {
+ const bGPDspoint *pt1, *pt2;
+ float s0[2], s1[2]; /* segment 'center' points */
+ float pm[2]; /* normal from previous segment. */
+ int i;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(ink, ink[3]);
+ immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4);
+
+ /* get x and y coordinates from first point */
+ gp_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, s0);
+
+ for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
+ float t0[2], t1[2]; /* tessellated coordinates */
+ float m1[2], m2[2]; /* gradient and normal */
+ float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
+ float pthick; /* thickness at segment point */
+
+ /* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */
+ gp_calc_2d_stroke_fxy(&pt2->x, sflag, offsx, offsy, winx, winy, s1);
+
+ /* calculate gradient and normal - 'angle'=(ny/nx) */
+ m1[1] = s1[1] - s0[1];
+ m1[0] = s1[0] - s0[0];
+ normalize_v2(m1);
+ m2[1] = -m1[0];
+ m2[0] = m1[1];
+
+ /* always use pressure from first point here */
+ pthick = (pt1->pressure * thickness * scalefac);
+
+ /* if the first segment, start of segment is segment's normal */
+ if (i == 0) {
+ /* draw start cap first
+ * - make points slightly closer to center (about halfway across)
+ */
+ mt[0] = m2[0] * pthick * 0.5f;
+ mt[1] = m2[1] * pthick * 0.5f;
+ sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
+ sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
+
+ t0[0] = sc[0] - mt[0];
+ t0[1] = sc[1] - mt[1];
+ t1[0] = sc[0] + mt[0];
+ t1[1] = sc[1] + mt[1];
+
+ /* First two points of cap. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
+ /* calculate points for start of segment */
+ mt[0] = m2[0] * pthick;
+ mt[1] = m2[1] * pthick;
+
+ t0[0] = s0[0] - mt[0];
+ t0[1] = s0[1] - mt[1];
+ t1[0] = s0[0] + mt[0];
+ t1[1] = s0[1] + mt[1];
+
+ /* Last two points of start cap (and first two points of first segment). */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+ }
+ /* if not the first segment, use bisector of angle between segments */
+ else {
+ float mb[2]; /* bisector normal */
+ float athick, dfac; /* actual thickness, difference between thicknesses */
+
+ /* calculate gradient of bisector (as average of normals) */
+ mb[0] = (pm[0] + m2[0]) / 2;
+ mb[1] = (pm[1] + m2[1]) / 2;
+ normalize_v2(mb);
+
+ /* calculate gradient to apply
+ * - as basis, use just pthick * bisector gradient
+ * - if cross-section not as thick as it should be, add extra padding to fix it
+ */
+ mt[0] = mb[0] * pthick;
+ mt[1] = mb[1] * pthick;
+ athick = len_v2(mt);
+ dfac = pthick - (athick * 2);
+
+ if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
+ mt[0] += (mb[0] * dfac);
+ mt[1] += (mb[1] * dfac);
+ }
+
+ /* calculate points for start of segment */
+ t0[0] = s0[0] - mt[0];
+ t0[1] = s0[1] - mt[1];
+ t1[0] = s0[0] + mt[0];
+ t1[1] = s0[1] + mt[1];
+
+ /* Last two points of previous segment, and first two points of current segment. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+ }
+
+ /* if last segment, also draw end of segment (defined as segment's normal) */
+ if (i == totpoints - 2) {
+ /* for once, we use second point's pressure (otherwise it won't be drawn) */
+ pthick = (pt2->pressure * thickness * scalefac);
+
+ /* calculate points for end of segment */
+ mt[0] = m2[0] * pthick;
+ mt[1] = m2[1] * pthick;
+
+ t0[0] = s1[0] - mt[0];
+ t0[1] = s1[1] - mt[1];
+ t1[0] = s1[0] + mt[0];
+ t1[1] = s1[1] + mt[1];
+
+ /* Last two points of last segment (and first two points of end cap). */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
+ /* draw end cap as last step
+ * - make points slightly closer to center (about halfway across)
+ */
+ mt[0] = m2[0] * pthick * 0.5f;
+ mt[1] = m2[1] * pthick * 0.5f;
+ sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
+ sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
+
+ t0[0] = sc[0] - mt[0];
+ t0[1] = sc[1] - mt[1];
+ t1[0] = sc[0] + mt[0];
+ t1[1] = sc[1] + mt[1];
+
+ /* Last two points of end cap. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+ }
+
+ /* store computed point2 coordinates as point1 ones of next segment. */
+ copy_v2_v2(s0, s1);
+ /* store stroke's 'natural' normal for next stroke to use */
+ copy_v2_v2(pm, m2);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+}
+
+/* ----- Strokes Drawing ------ */
+
+/* Helper for doing all the checks on whether a stroke can be drawn */
+static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
+{
+ /* skip stroke if it isn't in the right display space for this drawing context */
+ /* 1) 3D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
+ return false;
+
+ /* 2) Screen Space 2D Strokes */
+ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
+ return false;
+
+ /* 3) Image Space (2D) */
+ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+ if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
+ return false;
+
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1))
+ return false;
+
+ /* stroke can be drawn */
+ return true;
+}
+
+/* draw a set of strokes */
+static void gp_draw_strokes(
+ bGPdata *UNUSED(gpd), bGPDlayer *UNUSED(gpl), const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+ int dflag, bool debug, short lthick, const float color[4])
+{
+ GPU_enable_program_point_size();
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false) {
+ continue;
+ }
+
+ /* check which stroke-drawer to use */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
+ int mask_orig = 0;
+
+ if (no_xray) {
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ glDepthMask(0);
+ GPU_depth_test(true);
+
+ /* first arg is normally rv3d->dist, but this isn't
+ * available here and seems to work quite well without */
+ bglPolygonOffset(1.0f, 1.0f);
+ }
+
+ /* 3D Lines - OpenGL primitives-based */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
+ }
+ else {
+ gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug, gps->flag,
+ color, gps->flag & GP_STROKE_CYCLIC);
+ }
+
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ GPU_depth_test(false);
+
+ bglPolygonOffset(0.0, 0.0);
+ }
+ }
+ else {
+ /* 2D Strokes... */
+ if (gps->totpoints == 1) {
+ gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
+ }
+ else {
+ gp_draw_stroke_2d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug,
+ offsx, offsy, winx, winy, color);
+ }
+ }
+ }
+
+ GPU_disable_program_point_size();
+}
+
+/* Draw selected verts for strokes being edited */
+static void gp_draw_strokes_edit(
+ bGPdata *gpd, bGPDlayer *gpl, const bGPDframe *gpf,
+ int offsx, int offsy, int winx, int winy,
+ short dflag, short UNUSED(lflag), float alpha)
+{
+ /* if alpha 0 do not draw */
+ if (alpha == 0.0f)
+ return;
+
+ const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0;
+ int mask_orig = 0;
+
+ /* set up depth masks... */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ glDepthMask(0);
+ GPU_depth_test(true);
+
+ /* first arg is normally rv3d->dist, but this isn't
+ * available here and seems to work quite well without */
+ bglPolygonOffset(1.0f, 1.0f);
+ }
+ }
+
+ GPU_enable_program_point_size();
+
+ /* draw stroke verts */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if (gp_can_draw_stroke(gps, dflag) == false)
+ continue;
+
+ /* Optimisation: only draw points for selected strokes
+ * We assume that selected points can only occur in
+ * strokes that are selected too.
+ */
+ if ((gps->flag & GP_STROKE_SELECT) == 0)
+ continue;
+
+ /* Get size of verts:
+ * - The selected state needs to be larger than the unselected state so that
+ * they stand out more.
+ * - We use the theme setting for size of the unselected verts
+ */
+ float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float vsize;
+ if ((int)bsize > 8) {
+ vsize = 10.0f;
+ bsize = 8.0f;
+ }
+ else {
+ vsize = bsize + 2;
+ }
+
+ float selectColor[4];
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+ selectColor[3] = alpha;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos; /* specified later */
+ uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+ else {
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+
+ immBegin(GPU_PRIM_POINTS, gps->totpoints);
+
+ /* Draw start and end point differently if enabled stroke direction hint */
+ bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
+
+ /* Draw all the stroke points (selected or not) */
+ bGPDspoint *pt = gps->points;
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
+ /* size and color first */
+ if (show_direction_hint && i == 0) {
+ /* start point in green bigger */
+ immAttrib3f(color, 0.0f, 1.0f, 0.0f);
+ immAttrib1f(size, vsize + 4);
+ }
+ else if (show_direction_hint && (i == gps->totpoints - 1)) {
+ /* end point in red smaller */
+ immAttrib3f(color, 1.0f, 0.0f, 0.0f);
+ immAttrib1f(size, vsize + 1);
+ }
+ else if (pt->flag & GP_SPOINT_SELECT) {
+ immAttrib3fv(color, selectColor);
+ immAttrib1f(size, vsize);
+ }
+ else {
+ immAttrib3fv(color, gpl->color);
+ immAttrib1f(size, bsize);
+ }
+
+ /* then position */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ immVertex3fv(pos, &pt->x);
+ }
+ else {
+ float co[2];
+ gp_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
+ GPU_disable_program_point_size();
+
+ /* clear depth mask */
+ if (dflag & GP_DRAWDATA_ONLY3D) {
+ if (no_xray) {
+ glDepthMask(mask_orig);
+ GPU_depth_test(false);
+
+ bglPolygonOffset(0.0, 0.0);
+#if 0
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(0, 0);
+#endif
+ }
+ }
+}
+
+/* ----- General Drawing ------ */
+
+/* loop over gpencil data layers, drawing them */
+static void gp_draw_data_layers(
+ bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, float alpha)
+{
+ float ink[4];
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG);
+ short lthick = gpl->thickness;
+
+ /* apply layer opacity */
+ copy_v3_v3(ink, gpl->color);
+ ink[3] = gpl->opacity;
+
+ /* don't draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* get frame to draw */
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
+ if (gpf == NULL)
+ continue;
+
+ /* set basic stroke thickness */
+ GPU_line_width(lthick);
+
+ /* Add layer drawing settings to the set of "draw flags"
+ * NOTE: If the setting doesn't apply, it *must* be cleared,
+ * as dflag's carry over from the previous layer
+ */
+#define GP_DRAWFLAG_APPLY(condition, draw_flag_value) { \
+ if (condition) dflag |= (draw_flag_value); \
+ else dflag &= ~(draw_flag_value); \
+ } (void)0
+
+ /* xray... */
+ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
+
+#undef GP_DRAWFLAG_APPLY
+
+
+ /* draw the strokes already in active frame */
+ gp_draw_strokes(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, debug, lthick, ink);
+
+ /* Draw verts of selected strokes
+ * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
+ * - locked layers can't be edited, so there's no point showing these verts
+ * as they will have no bearings on what gets edited
+ * - only show when in editmode, since operators shouldn't work otherwise
+ * (NOTE: doing it this way means that the toggling editmode shows visible change immediately)
+ */
+ /* XXX: perhaps we don't want to show these when users are drawing... */
+ if ((G.f & G_RENDER_OGL) == 0 &&
+ (gpl->flag & GP_LAYER_LOCKED) == 0 &&
+ (gpd->flag & GP_DATA_STROKE_EDITMODE))
+ {
+ gp_draw_strokes_edit(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, alpha);
+ }
+
+ /* Check if may need to draw the active stroke cache, only if this layer is the active layer
+ * that is being edited. (Stroke buffer is currently stored in gp-data)
+ */
+ if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
+ (gpf->flag & GP_FRAME_PAINT))
+ {
+ /* Buffer stroke needs to be drawn with a different linestyle
+ * to help differentiate them from normal strokes.
+ *
+ * It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ gp_draw_stroke_buffer(
+ gpd->runtime.sbuffer,
+ gpd->runtime.sbuffer_size, lthick,
+ dflag, gpd->runtime.sbuffer_sflag, ink);
+ }
+ }
+}
+
+/* draw a short status message in the top-right corner */
+static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
+{
+ rcti rect;
+
+ /* Cannot draw any status text when drawing OpenGL Renders */
+ if (G.f & G_RENDER_OGL)
+ return;
+
+ /* Get bounds of region - Necessary to avoid problems with region overlap */
+ ED_region_visible_rect(ar, &rect);
+
+ /* for now, this should only be used to indicate when we are in stroke editmode */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ const char *printable = IFACE_("GPencil Stroke Editing");
+ float printable_size[2];
+
+ int font_id = BLF_default();
+
+ BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+
+ int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ int yco = (rect.ymax - U.widget_unit);
+
+ /* text label */
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+#else
+ BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+#endif
+
+ /* grease pencil icon... */
+ // XXX: is this too intrusive?
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
+
+ UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
+
+ GPU_blend(false);
+ }
+}
+
+/* draw grease-pencil datablock */
+static void gp_draw_data(
+ bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, float alpha)
+{
+ /* turn on smooth lines (i.e. anti-aliasing) */
+ GPU_line_smooth(true);
+
+ /* turn on alpha-blending */
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+
+ /* draw! */
+ gp_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+
+ /* turn off alpha blending, then smooth lines */
+ GPU_blend(false); // alpha blending
+ GPU_line_smooth(false); // smooth lines
+}
+
+/* if we have strokes for scenes (3d view)/clips (movie clip editor)
+ * and objects/tracks, multiple data blocks have to be drawn */
+static void gp_draw_data_all(
+ Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, const char spacetype)
+{
+ bGPdata *gpd_source = NULL;
+ float alpha = 1.0f;
+
+ if (scene) {
+ if (spacetype == SPACE_VIEW3D) {
+ gpd_source = (scene->gpd ? scene->gpd : NULL);
+ }
+ else if (spacetype == SPACE_CLIP && scene->clip) {
+ /* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
+ gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
+ }
+
+ if (gpd_source) {
+ gp_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ }
+ }
+
+ /* scene/clip data has already been drawn, only object/track data is drawn here
+ * if gpd_source == gpd, we don't have any object/track data and we can skip */
+ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
+ gp_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ }
+}
+
+/* ----- Grease Pencil Sketches Drawing API ------ */
+
+/* ............................
+ * XXX
+ * We need to review the calls below, since they may be/are not that suitable for
+ * the new ways that we intend to be drawing data...
+ * ............................ */
+
+/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
+void ED_gpencil_draw_2dimage(const bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+
+ int offsx, offsy, sizex, sizey;
+ int dflag = GP_DRAWDATA_NOSTATUS;
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
+ if (gpd == NULL) return;
+
+ /* calculate rect */
+ switch (sa->spacetype) {
+ case SPACE_IMAGE: /* image */
+ case SPACE_CLIP: /* clip */
+ {
+ /* just draw using standard scaling (settings here are currently ignored anyways) */
+ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+
+ dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
+ break;
+ }
+ case SPACE_SEQ: /* sequence */
+ {
+ /* just draw using standard scaling (settings here are currently ignored anyways) */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
+ * and everything moved to standard View2d
+ */
+ dflag |= GP_DRAWDATA_ONLYV2D;
+ break;
+ }
+ default: /* for spacetype not yet handled */
+ offsx = 0;
+ offsy = 0;
+ sizex = ar->winx;
+ sizey = ar->winy;
+
+ dflag |= GP_DRAWDATA_ONLYI2D;
+ break;
+ }
+
+ if (ED_screen_animation_playing(wm)) {
+ /* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
+ * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
+ */
+ dflag |= GP_DRAWDATA_NO_ONIONS;
+ }
+
+ /* draw it! */
+ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
+}
+
+/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
+ * Note: this gets called twice - first time with onlyv2d=true to draw 'canvas' strokes,
+ * second time with onlyv2d=false for screen-aligned strokes */
+void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ int dflag = 0;
+
+ /* check that we have grease-pencil stuff to draw */
+ if (sa == NULL) return;
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
+ if (gpd == NULL) return;
+
+ /* special hack for Image Editor */
+ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
+ if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP))
+ dflag |= GP_DRAWDATA_IEDITHACK;
+
+ /* draw it! */
+ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
+ if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS;
+
+ gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
+
+ /* draw status text (if in screen/pixel-space) */
+ if (!onlyv2d) {
+ gp_draw_status_text(gpd, ar);
+ }
+}
+
+
+/* draw annotations sketches to specified 3d-view assuming that matrices are already set correctly
+ * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+ * second time with only3d=false for screen-aligned strokes */
+void ED_gpencil_draw_view3d_annotations(
+ Scene *scene, struct Depsgraph *depsgraph,
+ View3D *v3d, ARegion *ar,
+ bool only3d)
+{
+ int dflag = 0;
+ RegionView3D *rv3d = ar->regiondata;
+ int offsx, offsy, winx, winy;
+
+ /* check that we have grease-pencil stuff to draw */
+ /* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data */
+ bGPdata *gpd = scene->gpd;
+ if (gpd == NULL) return;
+
+ /* when rendering to the offscreen buffer we don't want to
+ * deal with the camera border, otherwise map the coords to the camera border. */
+ if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
+ rctf rectf;
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &rectf, true); /* no shift */
+
+ offsx = round_fl_to_int(rectf.xmin);
+ offsy = round_fl_to_int(rectf.ymin);
+ winx = round_fl_to_int(rectf.xmax - rectf.xmin);
+ winy = round_fl_to_int(rectf.ymax - rectf.ymin);
+ }
+ else {
+ offsx = 0;
+ offsy = 0;
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ /* set flags */
+ if (only3d) {
+ /* 3D strokes/3D space:
+ * - only 3D space points
+ * - don't status text either (as it's the wrong space)
+ */
+ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
+ }
+
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ /* don't draw status text when "only render" flag is set */
+ dflag |= GP_DRAWDATA_NOSTATUS;
+ }
+
+ /* draw it! */
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+}
+
+#if 0 // XXX: Reinstate, after renaming the functions
+
+void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
+{
+ int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
+
+ gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
+}
+
+#endif
+
+/* ************************************************** */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
new file mode 100644
index 00000000000..b551f3d630b
--- /dev/null
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -0,0 +1,2393 @@
+/*
+ * ***** 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) 2008/2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/annotate_paint.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_geom.h"
+
+#include "BLT_translation.h"
+
+#include "PIL_time.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+#include "BKE_tracking.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_clip.h"
+
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_state.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "DEG_depsgraph.h"
+
+#include "gpencil_intern.h"
+
+/* ******************************************* */
+/* 'Globals' and Defines */
+
+/* values for tGPsdata->status */
+typedef enum eGPencil_PaintStatus {
+ GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */
+ GP_STATUS_PAINTING, /* a stroke is in progress */
+ GP_STATUS_ERROR, /* something wasn't correctly set up */
+ GP_STATUS_DONE /* painting done */
+} eGPencil_PaintStatus;
+
+/* Return flags for adding points to stroke buffer */
+typedef enum eGP_StrokeAdd_Result {
+ GP_STROKEADD_INVALID = -2, /* error occurred - insufficient info to do so */
+ GP_STROKEADD_OVERFLOW = -1, /* error occurred - cannot fit any more points */
+ GP_STROKEADD_NORMAL, /* point was successfully added */
+ GP_STROKEADD_FULL /* cannot add any more points to buffer */
+} eGP_StrokeAdd_Result;
+
+/* Runtime flags */
+typedef enum eGPencil_PaintFlags {
+ GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
+ GP_PAINTFLAG_STROKEADDED = (1 << 1),
+ GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
+ GP_PAINTFLAG_SELECTMASK = (1 << 3),
+} eGPencil_PaintFlags;
+
+
+/* Temporary 'Stroke' Operation data
+ * "p" = op->customdata
+ */
+typedef struct tGPsdata {
+ Main *bmain;
+ Scene *scene; /* current scene from context */
+ struct Depsgraph *depsgraph;
+
+ wmWindow *win; /* window where painting originated */
+ ScrArea *sa; /* area where painting originated */
+ ARegion *ar; /* region where painting originated */
+ View2D *v2d; /* needed for GP_STROKE_2DSPACE */
+ rctf *subrect; /* for using the camera rect within the 3d view */
+ rctf subrect_data;
+
+ GP_SpaceConversion gsc; /* settings to pass to gp_points_to_xy() */
+
+ PointerRNA ownerPtr; /* pointer to owner of gp-datablock */
+ bGPdata *gpd; /* gp-datablock layer comes from */
+ bGPDlayer *gpl; /* layer we're working on */
+ bGPDframe *gpf; /* frame we're working on */
+
+ char *align_flag; /* projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
+
+ eGPencil_PaintStatus status; /* current status of painting */
+ eGPencil_PaintModes paintmode; /* mode for painting */
+ eGPencil_PaintFlags flags; /* flags that can get set during runtime (eGPencil_PaintFlags) */
+
+ short radius; /* radius of influence for eraser */
+
+ int mval[2]; /* current mouse-position */
+ int mvalo[2]; /* previous recorded mouse-position */
+
+ float pressure; /* current stylus pressure */
+ float opressure; /* previous stylus pressure */
+
+ /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
+ * float (and its 7 digits precision) is definitively not enough here!
+ * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
+ */
+ double inittime; /* Used when converting to path */
+ double curtime; /* Used when converting to path */
+ double ocurtime; /* Used when converting to path */
+
+ float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space
+ * to region space */
+ float mat[4][4];
+
+ float custom_color[4]; /* custom color - hack for enforcing a particular color for track/mask editing */
+
+ void *erasercursor; /* radial cursor data for drawing eraser */
+
+ short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
+ int lock_axis; /* lock drawing to one axis */
+
+ short keymodifier; /* key used for invoking the operator */
+} tGPsdata;
+
+/* ------ */
+
+/* Macros for accessing sensitivity thresholds... */
+/* minimum number of pixels mouse should move before new point created */
+#define MIN_MANHATTEN_PX (U.gp_manhattendist)
+/* minimum length of new segment before new point can be added */
+#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
+
+static bool gp_stroke_added_check(tGPsdata *p)
+{
+ return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
+}
+
+static void gp_stroke_added_enable(tGPsdata *p)
+{
+ BLI_assert(p->gpf->strokes.last != NULL);
+ p->flags |= GP_PAINTFLAG_STROKEADDED;
+}
+
+/* ------ */
+/* Forward defines for some functions... */
+
+static void gp_session_validatebuffer(tGPsdata *p);
+
+/* ******************************************* */
+/* Context Wrangling... */
+
+/* check if context is suitable for drawing */
+static bool gpencil_draw_poll(bContext *C)
+{
+ if (ED_operator_regionactive(C)) {
+ /* check if current context can support GPencil data */
+ if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
+ /* check if Grease Pencil isn't already running */
+ if (ED_gpencil_session_active() == 0)
+ return 1;
+ else
+ CTX_wm_operator_poll_msg_set(C, "Annotation operator is already active");
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
+ }
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ }
+
+ return 0;
+}
+
+/* check if projecting strokes into 3d-geometry in the 3D-View */
+static bool gpencil_project_check(tGPsdata *p)
+{
+ bGPdata *gpd = p->gpd;
+ return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
+}
+
+/* ******************************************* */
+/* Calculations/Conversions */
+
+/* Utilities --------------------------------- */
+
+/* get the reference point for stroke-point conversions */
+static void gp_get_3d_reference(tGPsdata *p, float vec[3])
+{
+ View3D *v3d = p->sa->spacedata.first;
+ const float *fp = ED_view3d_cursor3d_get(p->scene, v3d)->location;
+
+ /* use 3D-cursor */
+ copy_v3_v3(vec, fp);
+}
+
+/* Stroke Editing ---------------------------- */
+
+/* check if the current mouse position is suitable for adding a new point */
+static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
+{
+ int dx = abs(mval[0] - pmval[0]);
+ int dy = abs(mval[1] - pmval[1]);
+
+ /* if buffer is empty, just let this go through (i.e. so that dots will work) */
+ if (p->gpd->runtime.sbuffer_size == 0)
+ return true;
+
+ /* check if mouse moved at least certain distance on both axes (best case)
+ * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
+ */
+ else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
+ return true;
+
+ /* check if the distance since the last point is significant enough
+ * - prevents points being added too densely
+ * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
+ */
+ else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
+ return true;
+
+ /* mouse 'didn't move' */
+ else
+ return false;
+}
+
+/* reproject the points of the stroke to a plane locked to axis to avoid stroke offset */
+static void gp_project_points_to_plane(RegionView3D *rv3d, bGPDstroke *gps, const float origin[3], const int axis)
+{
+ float plane_normal[3];
+ float vn[3];
+
+ float ray[3];
+ float rpoint[3];
+
+ /* normal vector for a plane locked to axis */
+ zero_v3(plane_normal);
+ plane_normal[axis] = 1.0f;
+
+ /* Reproject the points in the plane */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+
+ /* get a vector from the point with the current view direction of the viewport */
+ ED_view3d_global_to_vector(rv3d, &pt->x, vn);
+
+ /* calculate line extrem point to create a ray that cross the plane */
+ mul_v3_fl(vn, -50.0f);
+ add_v3_v3v3(ray, &pt->x, vn);
+
+ /* if the line never intersect, the point is not changed */
+ if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
+ copy_v3_v3(&pt->x, rpoint);
+ }
+ }
+}
+
+/* reproject stroke to plane locked to axis in 3d cursor location */
+static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
+{
+ bGPdata *gpd = p->gpd;
+ float origin[3];
+ float cursor[3];
+ RegionView3D *rv3d = p->ar->regiondata;
+
+ /* verify the stroke mode is CURSOR 3d space mode */
+ if ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
+ return;
+ }
+ if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
+ return;
+ }
+ if ((*p->align_flag & GP_PROJECT_DEPTH_VIEW) || (*p->align_flag & GP_PROJECT_DEPTH_STROKE)) {
+ return;
+ }
+
+ /* get 3d cursor and set origin for locked axis only. Uses axis-1 because the enum for XYZ start with 1 */
+ gp_get_3d_reference(p, cursor);
+ zero_v3(origin);
+ origin[p->lock_axis - 1] = cursor[p->lock_axis - 1];
+
+ gp_project_points_to_plane(rv3d, gps, origin, p->lock_axis - 1);
+}
+
+/* convert screen-coordinates to buffer-coordinates */
+/* XXX this method needs a total overhaul! */
+static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth)
+{
+ bGPdata *gpd = p->gpd;
+
+ /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
+ if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval, out, 0, depth))) {
+ /* projecting onto 3D-Geometry
+ * - nothing more needs to be done here, since view_autodist_simple() has already done it
+ */
+ }
+ else {
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float mval_f[2] = {UNPACK2(mval)};
+ float zfac;
+
+ /* Current method just converts each point in screen-coordinates to
+ * 3D-coordinates using the 3D-cursor as reference. In general, this
+ * works OK, but it could of course be improved.
+ *
+ * TODO:
+ * - investigate using nearest point(s) on a previous stroke as
+ * reference point instead or as offset, for easier stroke matching
+ */
+
+ gp_get_3d_reference(p, rvec);
+ zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
+
+ if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ sub_v2_v2v2(mval_f, mval_prj, mval_f);
+ ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(out, rvec, dvec);
+ }
+ else {
+ zero_v3(out);
+ }
+ }
+ }
+
+ /* 2d - on 'canvas' (assume that p->v2d is set) */
+ else if ((gpd->runtime.sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
+ UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]);
+ mul_v3_m4v3(out, p->imat, out);
+ }
+
+ /* 2d - relative to screen (viewport area) */
+ else {
+ if (p->subrect == NULL) { /* normal 3D view */
+ out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
+ out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
+ }
+ else { /* camera view, use subrect */
+ out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
+ out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
+ }
+ }
+}
+
+/* add current stroke-point to buffer (returns whether point was successfully added) */
+static short gp_stroke_addpoint(
+ tGPsdata *p, const int mval[2], float pressure, double curtime)
+{
+ bGPdata *gpd = p->gpd;
+ tGPspoint *pt;
+ ToolSettings *ts = p->scene->toolsettings;
+
+ /* check painting mode */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only - i.e. only store start and end point in buffer */
+ if (gpd->runtime.sbuffer_size == 0) {
+ /* first point in buffer (start point) */
+ pt = (tGPspoint *)(gpd->runtime.sbuffer);
+
+ /* store settings */
+ copy_v2_v2_int(&pt->x, mval);
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
+ pt->strength = 1.0f;
+ pt->time = (float)(curtime - p->inittime);
+
+ /* increment buffer size */
+ gpd->runtime.sbuffer_size++;
+ }
+ else {
+ /* just reset the endpoint to the latest value
+ * - assume that pointers for this are always valid...
+ */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
+
+ /* store settings */
+ copy_v2_v2_int(&pt->x, mval);
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
+ pt->strength = 1.0f;
+ pt->time = (float)(curtime - p->inittime);
+
+ /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
+ gpd->runtime.sbuffer_size = 2;
+ }
+
+ /* can keep carrying on this way :) */
+ return GP_STROKEADD_NORMAL;
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
+ /* check if still room in buffer */
+ if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_OVERFLOW;
+
+ /* get pointer to destination point */
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+
+ /* store settings */
+ copy_v2_v2_int(&pt->x, mval);
+ pt->pressure = pressure;
+ pt->strength = 1.0f; /* unused for annotations, but initialise for easier conversions to GP Object */
+
+ /* point time */
+ pt->time = (float)(curtime - p->inittime);
+
+ /* increment counters */
+ gpd->runtime.sbuffer_size++;
+
+ /* check if another operation can still occur */
+ if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
+ return GP_STROKEADD_FULL;
+ else
+ return GP_STROKEADD_NORMAL;
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+ /* get pointer to destination point */
+ pt = (tGPspoint *)(gpd->runtime.sbuffer);
+
+ /* store settings */
+ copy_v2_v2_int(&pt->x, mval);
+ pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */
+ pt->strength = 1.0f;
+ pt->time = (float)(curtime - p->inittime);
+
+ /* if there's stroke for this poly line session add (or replace last) point
+ * to stroke. This allows to draw lines more interactively (see new segment
+ * during mouse slide, e.g.)
+ */
+ if (gp_stroke_added_check(p)) {
+ bGPDstroke *gps = p->gpf->strokes.last;
+ bGPDspoint *pts;
+
+ /* first time point is adding to temporary buffer -- need to allocate new point in stroke */
+ if (gpd->runtime.sbuffer_size == 0) {
+ gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
+ gps->totpoints++;
+ }
+
+ pts = &gps->points[gps->totpoints - 1];
+
+ /* special case for poly lines: normally,
+ * depth is needed only when creating new stroke from buffer,
+ * but poly lines are converting to stroke instantly,
+ * so initialize depth buffer before converting coordinates
+ */
+ if (gpencil_project_check(p)) {
+ View3D *v3d = p->sa->spacedata.first;
+
+ view3d_region_operator_needs_opengl(p->win, p->ar);
+ ED_view3d_autodist_init(
+ p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ }
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
+ /* if axis locked, reproject to plane locked (only in 3d space) */
+ if (p->lock_axis > GP_LOCKAXIS_NONE) {
+ gp_reproject_toplane(p, gps);
+ }
+
+ /* copy pressure and time */
+ pts->pressure = pt->pressure;
+ pts->strength = pt->strength;
+ pts->time = pt->time;
+
+ /* force fill recalc */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ }
+
+ /* increment counters */
+ if (gpd->runtime.sbuffer_size == 0)
+ gpd->runtime.sbuffer_size++;
+
+ return GP_STROKEADD_NORMAL;
+ }
+
+ /* return invalid state for now... */
+ return GP_STROKEADD_INVALID;
+}
+
+/* simplify a stroke (in buffer) before storing it
+ * - applies a reverse Chaikin filter
+ * - code adapted from etch-a-ton branch
+ */
+static void gp_stroke_simplify(tGPsdata *p)
+{
+ bGPdata *gpd = p->gpd;
+ tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
+ short num_points = gpd->runtime.sbuffer_size;
+ short flag = gpd->runtime.sbuffer_sflag;
+ short i, j;
+
+ /* only simplify if simplification is enabled, and we're not doing a straight line */
+ if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
+ return;
+
+ /* don't simplify if less than 4 points in buffer */
+ if ((num_points <= 4) || (old_points == NULL))
+ return;
+
+ /* clear buffer (but don't free mem yet) so that we can write to it
+ * - firstly set sbuffer to NULL, so a new one is allocated
+ * - secondly, reset flag after, as it gets cleared auto
+ */
+ gpd->runtime.sbuffer = NULL;
+ gp_session_validatebuffer(p);
+ gpd->runtime.sbuffer_sflag = flag;
+
+/* macro used in loop to get position of new point
+ * - used due to the mixture of datatypes in use here
+ */
+#define GP_SIMPLIFY_AVPOINT(offs, sfac) \
+ { \
+ co[0] += (float)(old_points[offs].x * sfac); \
+ co[1] += (float)(old_points[offs].y * sfac); \
+ pressure += old_points[offs].pressure * sfac; \
+ time += old_points[offs].time * sfac; \
+ } (void)0
+
+ /* XXX Here too, do not lose start and end points! */
+ gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time);
+ for (i = 0, j = 0; i < num_points; i++) {
+ if (i - j == 3) {
+ float co[2], pressure, time;
+ int mco[2];
+
+ /* initialize values */
+ co[0] = 0.0f;
+ co[1] = 0.0f;
+ pressure = 0.0f;
+ time = 0.0f;
+
+ /* using macro, calculate new point */
+ GP_SIMPLIFY_AVPOINT(j, -0.25f);
+ GP_SIMPLIFY_AVPOINT(j + 1, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j + 2, 0.75f);
+ GP_SIMPLIFY_AVPOINT(j + 3, -0.25f);
+
+ /* set values for adding */
+ mco[0] = (int)co[0];
+ mco[1] = (int)co[1];
+
+ /* ignore return values on this... assume to be ok for now */
+ gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
+
+ j += 2;
+ }
+ }
+ gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure,
+ p->inittime + (double)old_points[num_points - 1].time);
+
+ /* free old buffer */
+ MEM_freeN(old_points);
+}
+
+/* make a new stroke from the buffer data */
+static void gp_stroke_newfrombuffer(tGPsdata *p)
+{
+ bGPdata *gpd = p->gpd;
+ bGPDlayer *gpl = p->gpl;
+ bGPDstroke *gps;
+ bGPDspoint *pt;
+ tGPspoint *ptc;
+ ToolSettings *ts = p->scene->toolsettings;
+
+ int i, totelem;
+ /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+ int depth_margin = (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
+
+ /* get total number of points to allocate space for
+ * - drawing straight-lines only requires the endpoints
+ */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
+ totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
+ else
+ totelem = gpd->runtime.sbuffer_size;
+
+ /* exit with error if no valid points from this stroke */
+ if (totelem == 0) {
+ if (G.debug & G_DEBUG)
+ printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->runtime.sbuffer_size);
+ return;
+ }
+
+ /* special case for poly line -- for already added stroke during session
+ * coordinates are getting added to stroke immediately to allow more
+ * interactive behavior
+ */
+ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+ if (gp_stroke_added_check(p)) {
+ return;
+ }
+ }
+
+ /* allocate memory for a new stroke */
+ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+
+ /* copy appropriate settings for stroke */
+ gps->totpoints = totelem;
+ gps->thickness = gpl->thickness;
+ gps->flag = gpd->runtime.sbuffer_sflag;
+ gps->inittime = p->inittime;
+
+ /* enable recalculation flag by default (only used if hq fill) */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* allocate enough memory for a continuous array for storage points */
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->tot_triangles = 0;
+
+ /* set pointer to first non-initialized point */
+ pt = gps->points + (gps->totpoints - totelem);
+
+ /* copy points from the buffer to the stroke */
+ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ /* straight lines only -> only endpoints */
+ {
+ /* first point */
+ ptc = gpd->runtime.sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ /* if axis locked, reproject to plane locked (only in 3d space) */
+ if (p->lock_axis > GP_LOCKAXIS_NONE) {
+ gp_reproject_toplane(p, gps);
+ }
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+
+ pt++;
+ }
+
+ if (totelem == 2) {
+ /* last point if applicable */
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ /* if axis locked, reproject to plane locked (only in 3d space) */
+ if (p->lock_axis > GP_LOCKAXIS_NONE) {
+ gp_reproject_toplane(p, gps);
+ }
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+ }
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+ /* first point */
+ ptc = gpd->runtime.sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ /* if axis locked, reproject to plane locked (only in 3d space) */
+ if (p->lock_axis > GP_LOCKAXIS_NONE) {
+ gp_reproject_toplane(p, gps);
+ }
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ pt->time = ptc->time;
+ }
+ else {
+ float *depth_arr = NULL;
+
+ /* get an array of depths, far depths are blended */
+ if (gpencil_project_check(p)) {
+ int mval[2], mval_prev[2] = { 0 };
+ int interp_depth = 0;
+ int found_depth = 0;
+
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
+
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) {
+ copy_v2_v2_int(mval, &ptc->x);
+
+ if ((ED_view3d_autodist_depth(p->ar, mval, depth_margin, depth_arr + i) == 0) &&
+ (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
+ {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+
+ copy_v2_v2_int(mval_prev, mval);
+ }
+
+ if (found_depth == false) {
+ /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
+ depth_arr[i] = 0.9999f;
+ }
+ else {
+ if (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
+ /* remove all info between the valid endpoints */
+ int first_valid = 0;
+ int last_valid = 0;
+
+ for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ first_valid = i;
+
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ if (depth_arr[i] != FLT_MAX)
+ break;
+ }
+ last_valid = i;
+
+ /* invalidate non-endpoints, so only blend between first and last */
+ for (i = first_valid + 1; i < last_valid; i++)
+ depth_arr[i] = FLT_MAX;
+
+ interp_depth = true;
+ }
+
+ if (interp_depth) {
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
+ }
+ }
+ }
+
+
+ pt = gps->points;
+
+ /* convert all points (normal behavior) */
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; i++, ptc++, pt++) {
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
+
+ /* copy pressure and time */
+ pt->pressure = ptc->pressure;
+ pt->strength = ptc->strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt->time = ptc->time;
+ }
+
+ /* if axis locked, reproject to plane locked (only in 3d space) */
+ if (p->lock_axis > GP_LOCKAXIS_NONE) {
+ gp_reproject_toplane(p, gps);
+ }
+
+ if (depth_arr)
+ MEM_freeN(depth_arr);
+ }
+
+ /* add stroke to frame */
+ BLI_addtail(&p->gpf->strokes, gps);
+ gp_stroke_added_enable(p);
+}
+
+/* --- 'Eraser' for 'Paint' Tool ------ */
+
+/* helper to free a stroke
+ * NOTE: gps->dvert and gps->triangles should be NULL, but check anyway for good measure
+ */
+static void gp_free_stroke(bGPdata *UNUSED(gpd), bGPDframe *gpf, bGPDstroke *gps)
+{
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ if (gps->triangles) {
+ MEM_freeN(gps->triangles);
+ }
+
+ BLI_freelinkN(&gpf->strokes, gps);
+}
+
+
+/* which which point is infront (result should only be used for comparison) */
+static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
+{
+ if (rv3d->is_persp) {
+ return ED_view3d_calc_zfac(rv3d, co, NULL);
+ }
+ else {
+ return -dot_v3v3(rv3d->viewinv[2], co);
+ }
+}
+
+/* only erase stroke points that are visible (3d view) */
+static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
+{
+ if ((p->sa->spacetype == SPACE_VIEW3D) &&
+ (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
+ {
+ RegionView3D *rv3d = p->ar->regiondata;
+ const int mval[2] = {x, y};
+ float mval_3d[3];
+
+ if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) {
+ const float depth_mval = view3d_point_depth(rv3d, mval_3d);
+ const float depth_pt = view3d_point_depth(rv3d, &pt->x);
+
+ if (depth_pt > depth_mval) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/* eraser tool - evaluation per stroke */
+/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
+static void gp_stroke_eraser_dostroke(tGPsdata *p,
+ bGPDframe *gpf, bGPDstroke *gps,
+ const int mval[2], const int mvalo[2],
+ const int radius, const rcti *rect)
+{
+ bGPDspoint *pt1, *pt2;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ int i;
+
+ if (gps->totpoints == 0) {
+ /* just free stroke */
+ gp_free_stroke(p->gpd, gpf, gps);
+ }
+ else if (gps->totpoints == 1) {
+ /* only process if it hasn't been masked out... */
+ if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
+ gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]);
+
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval, pc1) <= radius) {
+ /* free stroke */
+ gp_free_stroke(p->gpd, gpf, gps);
+ }
+ }
+ }
+ }
+ else {
+ /* Perform culling? */
+ bool do_cull = false;
+
+ /* Clear Tags
+ *
+ * Note: It's better this way, as we are sure that
+ * we don't miss anything, though things will be
+ * slightly slower as a result
+ */
+ for (i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+
+ /* First Pass: Loop over the points in the stroke
+ * 1) Thin out parts of the stroke under the brush
+ * 2) Tag "too thin" parts for removal (in second pass)
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
+ gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
+
+ /* Check that point segment of the boundbox of the eraser stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
+ ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1])))
+ {
+ /* Check if point segment of stroke had anything to do with
+ * eraser region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_inside_circle(mval, mvalo, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+ if ((gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
+ (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false))
+ {
+ /* Edge is affected - Check individual points now */
+ if (len_v2v2_int(mval, pc1) <= radius) {
+ pt1->flag |= GP_SPOINT_TAG;
+ }
+ if (len_v2v2_int(mval, pc2) <= radius) {
+ pt2->flag |= GP_SPOINT_TAG;
+ }
+ do_cull = true;
+ }
+ }
+ }
+ }
+
+ /* Second Pass: Remove any points that are tagged */
+ if (do_cull) {
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false);
+ }
+ }
+}
+
+/* erase strokes which fall under the eraser strokes */
+static void gp_stroke_doeraser(tGPsdata *p)
+{
+ bGPDframe *gpf = p->gpf;
+ bGPDstroke *gps, *gpn;
+ rcti rect;
+
+ /* rect is rectangle of eraser */
+ rect.xmin = p->mval[0] - p->radius;
+ rect.ymin = p->mval[1] - p->radius;
+ rect.xmax = p->mval[0] + p->radius;
+ rect.ymax = p->mval[1] + p->radius;
+
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
+ View3D *v3d = p->sa->spacedata.first;
+ view3d_region_operator_needs_opengl(p->win, p->ar);
+ ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
+ }
+ }
+
+ /* loop over strokes of active layer only (session init already took care of ensuring validity),
+ * checking segments for intersections to remove
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpn) {
+ gpn = gps->next;
+ /* Not all strokes in the datablock may be valid in the current editor/context
+ * (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
+ */
+ if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) {
+ gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->mvalo, p->radius, &rect);
+ }
+ }
+}
+
+/* ******************************************* */
+/* Sketching Operator */
+
+/* clear the session buffers (call this before AND after a paint operation) */
+static void gp_session_validatebuffer(tGPsdata *p)
+{
+ bGPdata *gpd = p->gpd;
+
+ /* clear memory of buffer (or allocate it if starting a new session) */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - reset sbuffer\n"); */
+ memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
+ }
+ else {
+ /* printf("\t\tGP - allocate sbuffer\n"); */
+ gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
+ }
+
+ /* reset indices */
+ gpd->runtime.sbuffer_size = 0;
+
+ /* reset flags */
+ gpd->runtime.sbuffer_sflag = 0;
+
+ /* reset inittime */
+ p->inittime = 0.0;
+}
+
+/* (re)init new painting data */
+static bool gp_session_initdata(bContext *C, tGPsdata *p)
+{
+ Main *bmain = CTX_data_main(C);
+ bGPdata **gpd_ptr = NULL;
+ ScrArea *curarea = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ /* make sure the active view (at the starting time) is a 3d-view */
+ if (curarea == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No active view for painting\n");
+ return 0;
+ }
+
+ /* pass on current scene and window */
+ p->bmain = CTX_data_main(C);
+ p->scene = CTX_data_scene(C);
+ p->depsgraph = CTX_data_depsgraph(C);
+ p->win = CTX_wm_window(C);
+
+ unit_m4(p->imat);
+ unit_m4(p->mat);
+
+ switch (curarea->spacetype) {
+ /* supported views first */
+ case SPACE_VIEW3D:
+ {
+ /* View3D *v3d = curarea->spacedata.first; */
+ /* RegionView3D *rv3d = ar->regiondata; */
+
+ /* set current area
+ * - must verify that region data is 3D-view (and not something else)
+ */
+ /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
+ p->sa = curarea;
+ p->ar = ar;
+ p->align_flag = &ts->annotate_v3d_align;
+
+ if (ar->regiondata == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable\n");
+ return 0;
+ }
+ break;
+ }
+ case SPACE_NODE:
+ {
+ /* SpaceNode *snode = curarea->spacedata.first; */
+
+ /* set current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_v2d_align;
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = curarea->spacedata.first;
+
+ /* set current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_seq_align;
+
+ /* check that gpencil data is allowed to be drawn */
+ if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil\n");
+ return 0;
+ }
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ /* SpaceImage *sima = curarea->spacedata.first; */
+
+ /* set the current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_ima_align;
+ break;
+ }
+ case SPACE_CLIP:
+ {
+ SpaceClip *sc = curarea->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip == NULL) {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+
+ /* set the current area */
+ p->sa = curarea;
+ p->ar = ar;
+ p->v2d = &ar->v2d;
+ p->align_flag = &ts->gpencil_v2d_align;
+
+ invert_m4_m4(p->imat, sc->unistabmat);
+
+ /* custom color for new layer */
+ p->custom_color[0] = 1.0f;
+ p->custom_color[1] = 0.0f;
+ p->custom_color[2] = 0.5f;
+ p->custom_color[3] = 0.9f;
+
+ if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
+ MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
+
+ if (marker) {
+ p->imat[3][0] -= marker->pos[0];
+ p->imat[3][1] -= marker->pos[1];
+ }
+ else {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+ }
+
+ invert_m4_m4(p->mat, p->imat);
+ copy_m4_m4(p->gsc.mat, p->mat);
+ break;
+ }
+ /* unsupported views */
+ default:
+ {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Annotations are not supported in this editor\n");
+ return 0;
+ }
+ }
+
+ /* get gp-data */
+ gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
+ if ((gpd_ptr == NULL) || !ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Current context doesn't allow for any Annotation data\n");
+ return 0;
+ }
+ else {
+ /* if no existing GPencil block exists, add one */
+ if (*gpd_ptr == NULL) {
+ bGPdata *gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
+ *gpd_ptr = gpd;
+
+ /* mark datablock as being used for annotations */
+ gpd->flag |= GP_DATA_ANNOTATIONS;
+
+ /* annotations always in front of all objects */
+ gpd->xray_mode = GP_XRAY_FRONT;
+ }
+ p->gpd = *gpd_ptr;
+ }
+
+ if (ED_gpencil_session_active() == 0) {
+ /* initialize undo stack,
+ * also, existing undo stack would make buffer drawn
+ */
+ gpencil_undo_init(p->gpd);
+ }
+
+ /* clear out buffer (stored in gp-data), in case something contaminated it */
+ gp_session_validatebuffer(p);
+
+ /* lock axis */
+ p->lock_axis = ts->gp_sculpt.lock_axis;
+
+ return 1;
+}
+
+/* init new painting session */
+static tGPsdata *gp_session_initpaint(bContext *C)
+{
+ tGPsdata *p = NULL;
+
+ /* create new context data */
+ p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data");
+
+ /* Try to initialise context data
+ * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
+ */
+ if (gp_session_initdata(C, p) == 0) {
+ /* Invalid state - Exit
+ * NOTE: It should be safe to just free the data, since failing context checks should
+ * only happen when no data has been allocated.
+ */
+ MEM_freeN(p);
+ return NULL;
+ }
+
+ /* Radius for eraser circle is defined in userprefs */
+ /* NOTE: we do this here, so that if we exit immediately,
+ * erase size won't get lost
+ */
+ p->radius = U.gp_eraser;
+
+ /* return context data for running paint operator */
+ return p;
+}
+
+/* cleanup after a painting session */
+static void gp_session_cleanup(tGPsdata *p)
+{
+ bGPdata *gpd = (p) ? p->gpd : NULL;
+
+ /* error checking */
+ if (gpd == NULL)
+ return;
+
+ /* free stroke buffer */
+ if (gpd->runtime.sbuffer) {
+ /* printf("\t\tGP - free sbuffer\n"); */
+ MEM_freeN(gpd->runtime.sbuffer);
+ gpd->runtime.sbuffer = NULL;
+ }
+
+ /* clear flags */
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer_sflag = 0;
+ p->inittime = 0.0;
+}
+
+static void gp_session_free(tGPsdata *p)
+{
+ MEM_freeN(p);
+}
+
+
+/* init new stroke */
+static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
+{
+ Scene *scene = p->scene;
+ ToolSettings *ts = scene->toolsettings;
+
+ /* get active layer (or add a new one if non-existent) */
+ p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ if (p->gpl == NULL) {
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true);
+
+ if (p->custom_color[3])
+ copy_v3_v3(p->gpl->color, p->custom_color);
+ }
+ if (p->gpl->flag & GP_LAYER_LOCKED) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: Cannot paint on locked layer\n");
+ return;
+ }
+
+ /* get active frame (add a new one if not matching frame) */
+ if (paintmode == GP_PAINTMODE_ERASER) {
+ /* Eraser mode:
+ * 1) Only allow erasing on the active layer (unlike for 3d-art Grease Pencil),
+ * since we won't be exposing layer locking in the UI
+ * 2) Ensure that p->gpf refers to the frame used for the active layer
+ * (to avoid problems with other tools which expect it to exist)
+ */
+ bool has_layer_to_erase = false;
+
+ if (gpencil_layer_is_editable(p->gpl)) {
+ /* Ensure that there's stuff to erase here (not including selection mask below)... */
+ if (p->gpl->actframe && p->gpl->actframe->strokes.first) {
+ has_layer_to_erase = true;
+ }
+ }
+
+ /* Ensure active frame is set correctly... */
+ p->gpf = p->gpl->actframe;
+
+ /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
+ * (though this is only available in editmode)
+ */
+ if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_SELECT_MASK) {
+ p->flags |= GP_PAINTFLAG_SELECTMASK;
+ }
+ }
+
+ if (has_layer_to_erase == false) {
+ p->status = GP_STATUS_ERROR;
+ //if (G.debug & G_DEBUG)
+ printf("Error: Eraser will not be affecting anything (gpencil_paint_init)\n");
+ return;
+ }
+ }
+ else {
+ /* Drawing Modes - Add a new frame if needed on the active layer */
+ short add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ else
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+
+ p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+
+ if (p->gpf == NULL) {
+ p->status = GP_STATUS_ERROR;
+ if (G.debug & G_DEBUG)
+ printf("Error: No frame created (gpencil_paint_init)\n");
+ return;
+ }
+ else {
+ p->gpf->flag |= GP_FRAME_PAINT;
+ }
+ }
+
+ /* set 'eraser' for this stroke if using eraser */
+ p->paintmode = paintmode;
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
+
+ /* check if we should respect depth while erasing */
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->gpl->flag & GP_LAYER_NO_XRAY) {
+ p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH;
+ }
+ }
+ }
+ else {
+ /* disable eraser flags - so that we can switch modes during a session */
+ p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
+
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->gpl->flag & GP_LAYER_NO_XRAY) {
+ p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
+ }
+ }
+ }
+
+ /* set 'initial run' flag, which is only used to denote when a new stroke is starting */
+ p->flags |= GP_PAINTFLAG_FIRSTRUN;
+
+
+ /* when drawing in the camera view, in 2D space, set the subrect */
+ p->subrect = NULL;
+ if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = p->sa->spacedata.first;
+ RegionView3D *rv3d = p->ar->regiondata;
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
+ p->subrect = &p->subrect_data;
+ }
+ }
+ }
+
+ /* init stroke point space-conversion settings... */
+ p->gsc.gpd = p->gpd;
+ p->gsc.gpl = p->gpl;
+
+ p->gsc.sa = p->sa;
+ p->gsc.ar = p->ar;
+ p->gsc.v2d = p->v2d;
+
+ p->gsc.subrect_data = p->subrect_data;
+ p->gsc.subrect = p->subrect;
+
+ copy_m4_m4(p->gsc.mat, p->mat);
+
+
+ /* check if points will need to be made in view-aligned space */
+ if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
+ switch (p->sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+ break;
+ }
+ case SPACE_NODE:
+ {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *)p->sa->spacedata.first;
+
+ /* only set these flags if the image editor doesn't have an image active,
+ * otherwise user will be confused by strokes not appearing after they're drawn
+ *
+ * Admittedly, this is a bit hacky, but it works much nicer from an ergonomic standpoint!
+ */
+ if (ELEM(NULL, sima, sima->image)) {
+ /* make strokes be drawn in screen space */
+ p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_2DSPACE;
+ *(p->align_flag) &= ~GP_PROJECT_VIEWSPACE;
+ }
+ else {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
+ }
+ break;
+ }
+ case SPACE_CLIP:
+ {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
+ break;
+ }
+ }
+ }
+}
+
+/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
+static void gp_paint_strokeend(tGPsdata *p)
+{
+ ToolSettings *ts = p->scene->toolsettings;
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ if (gpencil_project_check(p)) {
+ View3D *v3d = p->sa->spacedata.first;
+
+ /* need to restore the original projection settings before packing up */
+ view3d_region_operator_needs_opengl(p->win, p->ar);
+ ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ }
+
+ /* check if doing eraser or not */
+ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* simplify stroke before transferring? */
+ gp_stroke_simplify(p);
+
+ /* transfer stroke to frame */
+ gp_stroke_newfrombuffer(p);
+ }
+
+ /* clean up buffer now */
+ gp_session_validatebuffer(p);
+}
+
+/* finish off stroke painting operation */
+static void gp_paint_cleanup(tGPsdata *p)
+{
+ /* p->gpd==NULL happens when stroke failed to initialize,
+ * for example when GP is hidden in current space (sergey)
+ */
+ if (p->gpd) {
+ /* finish off a stroke */
+ gp_paint_strokeend(p);
+ }
+
+ /* "unlock" frame */
+ if (p->gpf)
+ p->gpf->flag &= ~GP_FRAME_PAINT;
+}
+
+/* ------------------------------- */
+
+/* Helper callback for drawing the cursor itself */
+static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
+{
+ tGPsdata *p = (tGPsdata *)p_ptr;
+
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ imm_draw_circle_wire_2d(shdr_pos, x, y, p->radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, p->radius / 2)); /* was fixed 40 */
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+ }
+}
+
+/* Turn brush cursor in 3D view on/off */
+static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
+{
+ if (p->erasercursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ p->erasercursor = NULL;
+ }
+ else if (enable && !p->erasercursor) {
+ /* enable cursor */
+ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ NULL, /* XXX */
+ gpencil_draw_eraser, p);
+ }
+}
+
+/* Check if tablet eraser is being used (when processing events) */
+static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
+{
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ return (wmtab->Active == EVT_TABLET_ERASER);
+ }
+
+ return false;
+}
+
+/* ------------------------------- */
+
+static void gpencil_draw_exit(bContext *C, wmOperator *op)
+{
+ tGPsdata *p = op->customdata;
+
+ /* restore cursor to indicate end of drawing */
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ /* don't assume that operator data exists at all */
+ if (p) {
+ /* check size of buffer before cleanup, to determine if anything happened here */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* turn off radial brush cursor */
+ gpencil_draw_toggle_eraser_cursor(C, p, false);
+ }
+
+ /* always store the new eraser size to be used again next time
+ * NOTE: Do this even when not in eraser mode, as eraser may
+ * have been toggled at some point.
+ */
+ U.gp_eraser = p->radius;
+
+ /* clear undo stack */
+ gpencil_undo_finish();
+
+ /* cleanup */
+ gp_paint_cleanup(p);
+ gp_session_cleanup(p);
+ gp_session_free(p);
+ p = NULL;
+ }
+
+ op->customdata = NULL;
+}
+
+static void gpencil_draw_cancel(bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ gpencil_draw_exit(C, op);
+}
+
+/* ------------------------------- */
+
+
+static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGPsdata *p;
+ eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
+
+ /* check context */
+ p = op->customdata = gp_session_initpaint(C);
+ if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
+ /* something wasn't set correctly in context */
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ /* init painting data */
+ gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
+ if (p->status == GP_STATUS_ERROR) {
+ gpencil_draw_exit(C, op);
+ return 0;
+ }
+
+ if (event != NULL) {
+ p->keymodifier = event->keymodifier;
+ }
+ else {
+ p->keymodifier = -1;
+ }
+
+ /* everything is now setup ok */
+ return 1;
+}
+
+
+/* ------------------------------- */
+
+/* ensure that the correct cursor icon is set */
+static void gpencil_draw_cursor_set(tGPsdata *p)
+{
+ if (p->paintmode == GP_PAINTMODE_ERASER)
+ WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
+ else
+ WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
+}
+
+/* update UI indicators of status, including cursor and header prints */
+static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
+{
+ /* header prints */
+ switch (p->status) {
+ case GP_STATUS_PAINTING:
+ switch (p->paintmode) {
+ case GP_PAINTMODE_DRAW_POLY:
+ /* Provide usage tips, since this is modal, and unintuitive without hints */
+ ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ default:
+ /* Do nothing - the others are self explanatory, exit quickly once the mouse is released
+ * Showing any text would just be annoying as it would flicker.
+ */
+ break;
+ }
+ break;
+
+ case GP_STATUS_IDLING:
+ /* print status info */
+ switch (p->paintmode) {
+ case GP_PAINTMODE_ERASER:
+ ED_workspace_status_text(C, IFACE_("Annotation Eraser: Hold and drag LMB or RMB to erase | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW_STRAIGHT:
+ ED_workspace_status_text(C, IFACE_("Annotation Line Draw: Hold and drag LMB to draw | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW:
+ ED_workspace_status_text(C, IFACE_("Annotation Freehand Draw: Hold and drag LMB to draw | "
+ "E/ESC/Enter to end (or click outside this area)"));
+ break;
+ case GP_PAINTMODE_DRAW_POLY:
+ ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
+ "ESC/Enter to end (or click outside this area)"));
+ break;
+
+ default: /* unhandled future cases */
+ ED_workspace_status_text(C, IFACE_("Annotation Session: ESC/Enter to end (or click outside this area)"));
+ break;
+ }
+ break;
+
+ case GP_STATUS_ERROR:
+ case GP_STATUS_DONE:
+ /* clear status string */
+ ED_workspace_status_text(C, NULL);
+ break;
+ }
+}
+
+/* ------------------------------- */
+
+/* create a new stroke point at the point indicated by the painting context */
+static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
+{
+ /* handle drawing/erasing -> test for erasing first */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* do 'live' erasing now */
+ gp_stroke_doeraser(p);
+
+ /* store used values */
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ }
+ /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */
+ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
+ /* try to add point */
+ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
+
+ /* handle errors while adding point */
+ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
+ /* finish off old stroke */
+ gp_paint_strokeend(p);
+ /* And start a new one!!! Else, projection errors! */
+ gp_paint_initstroke(p, p->paintmode, depsgraph);
+
+ /* start a new stroke, starting from previous point */
+ /* XXX Must manually reset inittime... */
+ /* XXX We only need to reuse previous point if overflow! */
+ if (ok == GP_STROKEADD_OVERFLOW) {
+ p->inittime = p->ocurtime;
+ gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime);
+ }
+ else {
+ p->inittime = p->curtime;
+ }
+ gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
+ }
+ else if (ok == GP_STROKEADD_INVALID) {
+ /* the painting operation cannot continue... */
+ BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke");
+ p->status = GP_STATUS_ERROR;
+
+ if (G.debug & G_DEBUG)
+ printf("Error: Grease-Pencil Paint - Add Point Invalid\n");
+ return;
+ }
+
+ /* store used values */
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+ }
+}
+
+/* handle draw event */
+static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsgraph *depsgraph)
+{
+ tGPsdata *p = op->customdata;
+ PointerRNA itemptr;
+ float mousef[2];
+ int tablet = 0;
+
+ /* convert from window-space to area-space mouse coordinates
+ * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding...
+ */
+ p->mval[0] = event->mval[0] + 1;
+ p->mval[1] = event->mval[1] + 1;
+
+ /* verify key status for straight lines */
+ if ((event->ctrl > 0) || (event->alt > 0)) {
+ if (p->straight[0] == 0) {
+ int dx = abs(p->mval[0] - p->mvalo[0]);
+ int dy = abs(p->mval[1] - p->mvalo[1]);
+ if ((dx > 0) || (dy > 0)) {
+ /* check mouse direction to replace the other coordinate with previous values */
+ if (dx >= dy) {
+ /* horizontal */
+ p->straight[0] = 1;
+ p->straight[1] = p->mval[1]; /* save y */
+ }
+ else {
+ /* vertical */
+ p->straight[0] = 2;
+ p->straight[1] = p->mval[0]; /* save x */
+ }
+ }
+ }
+ }
+ else {
+ p->straight[0] = 0;
+ }
+
+ p->curtime = PIL_check_seconds_timer();
+
+ /* handle pressure sensitivity (which is supplied by tablets) */
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+
+ tablet = (wmtab->Active != EVT_TABLET_NONE);
+ p->pressure = wmtab->Pressure;
+
+ /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
+ * The pen has to float over the tablet surface, resulting in
+ * zero pressure (T47101). Ignore pressure values if floating
+ * (i.e. "effectively zero" pressure), and only when the "active"
+ * end is the stylus (i.e. the default when not eraser)
+ */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
+ p->pressure = 1.0f;
+ }
+ }
+ }
+ else {
+ /* No tablet data -> No pressure info is available */
+ p->pressure = 1.0f;
+ }
+
+ /* special exception for start of strokes (i.e. maybe for just a dot) */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
+
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->inittime = p->ocurtime = p->curtime;
+ p->straight[0] = 0;
+ p->straight[1] = 0;
+
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch...
+ */
+ if (tablet && (p->pressure >= 0.99f))
+ return;
+ }
+
+ /* check if alt key is pressed and limit to straight lines */
+ if (p->straight[0] != 0) {
+ if (p->straight[0] == 1) {
+ /* horizontal */
+ p->mval[1] = p->straight[1]; /* replace y */
+ }
+ else {
+ /* vertical */
+ p->mval[0] = p->straight[1]; /* replace x */
+ }
+ }
+
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0] = p->mval[0];
+ mousef[1] = p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
+
+ RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
+
+ /* apply the current latest drawing point */
+ gpencil_draw_apply(op, p, depsgraph);
+
+ /* force refresh */
+ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
+}
+
+/* ------------------------------- */
+
+/* operator 'redo' (i.e. after changing some properties, but also for repeat last) */
+static int gpencil_draw_exec(bContext *C, wmOperator *op)
+{
+ tGPsdata *p = NULL;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* printf("GPencil - Starting Re-Drawing\n"); */
+
+ /* try to initialize context data needed while drawing */
+ if (!gpencil_draw_init(C, op, NULL)) {
+ if (op->customdata) MEM_freeN(op->customdata);
+ /* printf("\tGP - no valid data\n"); */
+ return OPERATOR_CANCELLED;
+ }
+ else
+ p = op->customdata;
+
+ /* printf("\tGP - Start redrawing stroke\n"); */
+
+ /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
+ * setting the relevant values in context at each step, then applying
+ */
+ RNA_BEGIN (op->ptr, itemptr, "stroke")
+ {
+ float mousef[2];
+
+ /* printf("\t\tGP - stroke elem\n"); */
+
+ /* get relevant data for this point from stroke */
+ RNA_float_get_array(&itemptr, "mouse", mousef);
+ p->mval[0] = (int)mousef[0];
+ p->mval[1] = (int)mousef[1];
+ p->pressure = RNA_float_get(&itemptr, "pressure");
+ p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
+
+ if (RNA_boolean_get(&itemptr, "is_start")) {
+ /* if first-run flag isn't set already (i.e. not true first stroke),
+ * then we must terminate the previous one first before continuing
+ */
+ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
+ /* TODO: both of these ops can set error-status, but we probably don't need to worry */
+ gp_paint_strokeend(p);
+ gp_paint_initstroke(p, p->paintmode, depsgraph);
+ }
+ }
+
+ /* if first run, set previous data too */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
+
+ p->mvalo[0] = p->mval[0];
+ p->mvalo[1] = p->mval[1];
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+ }
+
+ /* apply this data as necessary now (as per usual) */
+ gpencil_draw_apply(op, p, depsgraph);
+ }
+ RNA_END;
+
+ /* printf("\tGP - done\n"); */
+
+ /* cleanup */
+ gpencil_draw_exit(C, op);
+
+ /* refreshes */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+/* ------------------------------- */
+
+/* start of interactive drawing part of operator */
+static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ tGPsdata *p = NULL;
+
+ /* GPXX Need a better solution */
+ if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot draw annotation with a Grease Pencil object active");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (G.debug & G_DEBUG)
+ printf("GPencil - Starting Drawing\n");
+
+ /* try to initialize context data needed while drawing */
+ if (!gpencil_draw_init(C, op, event)) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ if (G.debug & G_DEBUG)
+ printf("\tGP - no valid data\n");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ p = op->customdata;
+
+ /* TODO: set any additional settings that we can take from the events?
+ * TODO? if tablet is erasing, force eraser to be on? */
+
+ /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */
+
+ /* if eraser is on, draw radial aid */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ gpencil_draw_toggle_eraser_cursor(C, p, true);
+ }
+ /* set cursor
+ * NOTE: This may change later (i.e. intentionally via brush toggle,
+ * or unintentionally if the user scrolls outside the area)...
+ */
+ gpencil_draw_cursor_set(p);
+
+ /* only start drawing immediately if we're allowed to do so... */
+ if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
+ /* hotkey invoked - start drawing */
+ /* printf("\tGP - set first spot\n"); */
+ p->status = GP_STATUS_PAINTING;
+
+ /* handle the initial drawing - i.e. for just doing a simple dot */
+ gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ /* toolbar invoked - don't start drawing yet... */
+ /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ /* add a modal handler for this operator, so that we can then draw continuous strokes */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
+static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
+{
+ bScreen *sc = CTX_wm_screen(C);
+ return (BLI_findindex(&sc->areabase, sa_test) != -1);
+}
+
+static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
+{
+ tGPsdata *p = op->customdata;
+
+ /* we must check that we're still within the area that we're set up to work from
+ * otherwise we could crash (see bug #20586)
+ */
+ if (CTX_wm_area(C) != p->sa) {
+ printf("\t\t\tGP - wrong area execution abort!\n");
+ p->status = GP_STATUS_ERROR;
+ }
+
+ /* printf("\t\tGP - start stroke\n"); */
+
+ /* we may need to set up paint env again if we're resuming */
+ /* XXX: watch it with the paintmode! in future,
+ * it'd be nice to allow changing paint-mode when in sketching-sessions */
+
+ if (gp_session_initdata(C, p))
+ gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
+
+ if (p->status != GP_STATUS_ERROR) {
+ p->status = GP_STATUS_PAINTING;
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+
+ return op->customdata;
+}
+
+static void gpencil_stroke_end(wmOperator *op)
+{
+ tGPsdata *p = op->customdata;
+
+ gp_paint_cleanup(p);
+
+ gpencil_undo_push(p->gpd);
+
+ gp_session_cleanup(p);
+
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
+ p->gpd = NULL;
+ p->gpl = NULL;
+ p->gpf = NULL;
+}
+
+/* events handling during interactive drawing part of operator */
+static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGPsdata *p = op->customdata;
+ int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */
+
+ /* if (event->type == NDOF_MOTION)
+ * return OPERATOR_PASS_THROUGH;
+ * -------------------------------
+ * [mce] Not quite what I was looking
+ * for, but a good start! GP continues to
+ * draw on the screen while the 3D mouse
+ * moves the viewpoint. Problem is that
+ * the stroke is converted to 3D only after
+ * it is finished. This approach should work
+ * better in tools that immediately apply
+ * in 3D space.
+ */
+
+ if (p->status == GP_STATUS_IDLING) {
+ ARegion *ar = CTX_wm_region(C);
+ p->ar = ar;
+ }
+
+ /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
+ if (ISKEYBOARD(event->type)) {
+ if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
+ /* allow some keys:
+ * - for frame changing [#33412]
+ * - for undo (during sketching sessions)
+ */
+ }
+ else if (ELEM(event->type, PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9)) {
+ /* allow numpad keys so that camera/view manipulations can still take place
+ * - PAD0 in particular is really important for Grease Pencil drawing,
+ * as animators may be working "to camera", so having this working
+ * is essential for ensuring that they can quickly return to that view
+ */
+ }
+ else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
+ /* Add Blank Frame
+ * - Since this operator is non-modal, we can just call it here, and keep going...
+ * - This operator is especially useful when animating
+ */
+ WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ //printf("\tGP - handle modal event...\n");
+
+ /* exit painting mode (and/or end current stroke)
+ * NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
+ */
+ if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) {
+ /* exit() ends the current stroke before cleaning up */
+ /* printf("\t\tGP - end of paint op + end of stroke\n"); */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+
+ /* toggle painting mode upon mouse-button movement
+ * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only)
+ * - RIGHTMOUSE = polyline (hotkey) / eraser (all)
+ * (Disabling RIGHTMOUSE case here results in bugs like [#32647])
+ * also making sure we have a valid event value, to not exit too early
+ */
+ if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && (ELEM(event->val, KM_PRESS, KM_RELEASE))) {
+ /* if painting, end stroke */
+ if (p->status == GP_STATUS_PAINTING) {
+ int sketch = 0;
+
+ /* basically, this should be mouse-button up = end stroke
+ * BUT, polyline drawing is an exception -- all knots should be added during one session
+ */
+ sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY);
+
+ if (sketch) {
+ /* end stroke only, and then wait to resume painting soon */
+ /* printf("\t\tGP - end stroke only\n"); */
+ gpencil_stroke_end(op);
+
+ /* If eraser mode is on, turn it off after the stroke finishes
+ * NOTE: This just makes it nicer to work with drawing sessions
+ */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+
+ /* if the original mode was *still* eraser,
+ * we'll let it say for now, since this gives
+ * users an opportunity to have visual feedback
+ * when adjusting eraser size
+ */
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ /* turn off cursor...
+ * NOTE: this should be enough for now
+ * Just hiding this makes it seem like
+ * you can paint again...
+ */
+ gpencil_draw_toggle_eraser_cursor(C, p, false);
+ }
+ }
+
+ /* we've just entered idling state, so this event was processed (but no others yet) */
+ estate = OPERATOR_RUNNING_MODAL;
+
+ /* stroke could be smoothed, send notifier to refresh screen */
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ else {
+ /* printf("\t\tGP - end of stroke + op\n"); */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+ }
+ else if (event->val == KM_PRESS) {
+ bool in_bounds = false;
+
+ /* Check if we're outside the bounds of the active region
+ * NOTE: An exception here is that if launched from the toolbar,
+ * whatever region we're now in should become the new region
+ */
+ if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
+ /* Change to whatever region is now under the mouse */
+ ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
+
+ if (G.debug & G_DEBUG) {
+ printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ current_region, p->ar, event->x, event->y,
+ p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax);
+ }
+
+ if (current_region) {
+ /* Assume that since we found the cursor in here, it is in bounds
+ * and that this should be the region that we begin drawing in
+ */
+ p->ar = current_region;
+ in_bounds = true;
+ }
+ else {
+ /* Out of bounds, or invalid in some other way */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
+ }
+ }
+ else if (p->ar) {
+ rcti region_rect;
+
+ /* Perform bounds check using */
+ ED_region_visible_rect(p->ar, &region_rect);
+ in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
+ }
+ else {
+ /* No region */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: No active region found in GP Paint session data\n", __func__);
+ }
+
+ if (in_bounds) {
+ /* Switch paintmode (temporarily if need be) based on which button was used
+ * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ */
+ if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
+ /* turn on eraser */
+ p->paintmode = GP_PAINTMODE_ERASER;
+ }
+ else if (event->type == LEFTMOUSE) {
+ /* restore drawmode to default */
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+ }
+
+ gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+
+ /* not painting, so start stroke (this should be mouse-button down) */
+ p = gpencil_stroke_begin(C, op);
+
+ if (p->status == GP_STATUS_ERROR) {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else if (p->status != GP_STATUS_ERROR) {
+ /* User clicked outside bounds of window while idling, so exit paintmode
+ * NOTE: Don't enter this case if an error occurred while finding the
+ * region (as above)
+ */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+ }
+ else if (event->val == KM_RELEASE) {
+ p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+ }
+
+ /* handle mode-specific events */
+ if (p->status == GP_STATUS_PAINTING) {
+ /* handle painting mouse-movements? */
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
+ /* handle drawing event */
+ /* printf("\t\tGP - add point\n"); */
+ gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
+
+ /* finish painting operation if anything went wrong just now */
+ if (p->status == GP_STATUS_ERROR) {
+ printf("\t\t\t\tGP - add error done!\n");
+ estate = OPERATOR_CANCELLED;
+ }
+ else {
+ /* event handled, so just tag as running modal */
+ /* printf("\t\t\t\tGP - add point handled!\n"); */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+ /* eraser size */
+ else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
+ {
+ /* just resize the brush (local version)
+ * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
+ */
+ /* printf("\t\tGP - resize eraser\n"); */
+ switch (event->type) {
+ case WHEELDOWNMOUSE: /* larger */
+ case PADPLUSKEY:
+ p->radius += 5;
+ break;
+
+ case WHEELUPMOUSE: /* smaller */
+ case PADMINUS:
+ p->radius -= 5;
+
+ if (p->radius <= 0)
+ p->radius = 1;
+ break;
+ }
+
+ /* force refresh */
+ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
+
+ /* event handled, so just tag as running modal */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
+ * (i.e. to prevent problems with undo)
+ */
+ else {
+ /* swallow event to save ourselves trouble */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
+ if (0 == gpencil_area_exists(C, p->sa))
+ estate = OPERATOR_CANCELLED;
+ else {
+ /* update status indicators - cursor, header, etc. */
+ gpencil_draw_status_indicators(C, p);
+ gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */
+ }
+
+ /* process last operations before exiting */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ /* one last flush before we're done */
+ gpencil_draw_exit(C, op);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ break;
+
+ case OPERATOR_CANCELLED:
+ gpencil_draw_exit(C, op);
+ break;
+
+ case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
+ /* event doesn't need to be handled */
+#if 0
+ printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n",
+ event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE);
+#endif
+ break;
+ }
+
+ /* return status code */
+ return estate;
+}
+
+/* ------------------------------- */
+
+static const EnumPropertyItem prop_gpencil_drawmodes[] = {
+ {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
+ {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", "Draw straight line segment(s)"},
+ {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", "Click to place endpoints of straight line segments (connected)"},
+ {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", "Erase Annotation strokes"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+void GPENCIL_OT_annotate(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Annotation Draw";
+ ot->idname = "GPENCIL_OT_annotate";
+ ot->description = "Make annotations on the active data";
+
+ /* api callbacks */
+ ot->exec = gpencil_draw_exec;
+ ot->invoke = gpencil_draw_invoke;
+ ot->modal = gpencil_draw_modal;
+ ot->cancel = gpencil_draw_cancel;
+ ot->poll = gpencil_draw_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* settings for drawing */
+ ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
+
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index ec4310213ef..180fb65e743 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -46,6 +46,7 @@
#include "BLF_api.h"
#include "BLT_translation.h"
+#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -55,8 +56,13 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
+#include "BKE_brush.h"
#include "BKE_global.h"
+#include "BKE_paint.h"
#include "BKE_gpencil.h"
+#include "BKE_image.h"
+
+#include "DEG_depsgraph.h"
#include "WM_api.h"
@@ -74,6 +80,10 @@
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "IMB_imbuf_types.h"
+
+#include "gpencil_intern.h"
+
/* ************************************************** */
/* GREASE PENCIL DRAWING */
@@ -88,8 +98,7 @@ typedef enum eDrawStrokeFlags {
GP_DRAWDATA_NO_XRAY = (1 << 5), /* don't draw xray in 3D view (which is default) */
GP_DRAWDATA_NO_ONIONS = (1 << 6), /* no onionskins should be drawn (for animation playback) */
GP_DRAWDATA_VOLUMETRIC = (1 << 7), /* draw strokes as "volumetric" circular billboards */
- GP_DRAWDATA_FILL = (1 << 8), /* fill insides/bounded-regions of strokes */
- GP_DRAWDATA_HQ_FILL = (1 << 9) /* Use high quality fill */
+ GP_DRAWDATA_FILL = (1 << 8) /* fill insides/bounded-regions of strokes */
} eDrawStrokeFlags;
@@ -100,12 +109,12 @@ typedef enum eDrawStrokeFlags {
#endif
/* conversion utility (float --> normalized unsigned byte) */
-#define F2UB(x) (unsigned char)(255.0f * x)
+#define F2UB(x) (uchar)(255.0f * x)
/* ----- Tool Buffer Drawing ------ */
/* helper functions to set color of buffer point */
-static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], unsigned attrib_id)
+static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], uint attrib_id)
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
@@ -119,7 +128,7 @@ static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4])
immUniformColor3fvAlpha(ink, alpha);
}
-static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], unsigned attrib_id)
+static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], uint attrib_id)
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
@@ -134,7 +143,7 @@ static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, f
}
int tot_triangles = totpoints - 2;
/* allocate memory for temporary areas */
- unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation");
+ uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation");
float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke buffer temp 2d points");
/* Convert points to array and triangulate
@@ -146,18 +155,18 @@ static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, f
points2d[i][0] = pt->x;
points2d[i][1] = pt->y;
}
- BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)totpoints, 0, (unsigned int(*)[3])tmp_triangles);
+ BLI_polyfill_calc((const float(*)[2])points2d, (uint)totpoints, 0, (uint(*)[3])tmp_triangles);
/* draw triangulation data */
if (tot_triangles > 0) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* Draw all triangles for filling the polygon */
- immBegin(GWN_PRIM_TRIS, tot_triangles * 3);
+ immBegin(GPU_PRIM_TRIS, tot_triangles * 3);
/* TODO: use batch instead of immediate mode, to share vertices */
const tGPspoint *pt;
@@ -208,9 +217,9 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
return;
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
const tGPspoint *pt = points;
@@ -218,7 +227,7 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
/* if drawing a single point, draw it larger */
GPU_point_size((float)(thickness + 2) * points->pressure);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
gp_set_tpoint_varying_color(pt, ink, color);
immVertex2iv(pos, &pt->x);
}
@@ -228,7 +237,7 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
/* draw stroke curve */
GPU_line_width(max_ff(oldpressure * thickness, 1.0));
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
/* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
@@ -247,13 +256,13 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
draw_points = 0;
GPU_line_width(max_ff(pt->pressure * thickness, 1.0f));
- immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
gp_set_tpoint_varying_color(pt - 1, ink, color);
immVertex2iv(pos, &(pt - 1)->x);
- ++draw_points;
+ draw_points++;
}
oldpressure = pt->pressure; /* reset our threshold */
@@ -262,7 +271,7 @@ static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short
/* now the point we want */
gp_set_tpoint_varying_color(pt, ink, color);
immVertex2iv(pos, &pt->x);
- ++draw_points;
+ draw_points++;
}
/* need to have 2 points to avoid immEnd assert error */
if (draw_points < 2) {
@@ -319,14 +328,14 @@ static void gp_draw_stroke_volumetric_buffer(const tGPspoint *points, int totpoi
if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
return;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, totpoints);
+ immBegin(GPU_PRIM_POINTS, totpoints);
const tGPspoint *pt = points;
for (int i = 0; i < totpoints; i++, pt++) {
@@ -346,14 +355,14 @@ static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, int totpoints
int offsx, int offsy, int winx, int winy,
const float diff_mat[4][4], const float ink[4])
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, totpoints);
+ immBegin(GPU_PRIM_POINTS, totpoints);
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints; i++, pt++) {
@@ -379,14 +388,14 @@ static void gp_draw_stroke_volumetric_3d(
const bGPDspoint *points, int totpoints, short thickness,
const float ink[4])
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- uint size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, totpoints);
+ immBegin(GPU_PRIM_POINTS, totpoints);
const bGPDspoint *pt = points;
for (int i = 0; i < totpoints && pt; i++, pt++) {
@@ -402,6 +411,50 @@ static void gp_draw_stroke_volumetric_3d(
/* --------------- Stroke Fills ----------------- */
+/* calc bounding box in 2d using flat projection data */
+static void gp_calc_2d_bounding_box(const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], bool expand)
+{
+ copy_v2_v2(minv, points2d[0]);
+ copy_v2_v2(maxv, points2d[0]);
+
+ for (int i = 1; i < totpoints; i++) {
+ /* min */
+ if (points2d[i][0] < minv[0]) {
+ minv[0] = points2d[i][0];
+ }
+ if (points2d[i][1] < minv[1]) {
+ minv[1] = points2d[i][1];
+ }
+ /* max */
+ if (points2d[i][0] > maxv[0]) {
+ maxv[0] = points2d[i][0];
+ }
+ if (points2d[i][1] > maxv[1]) {
+ maxv[1] = points2d[i][1];
+ }
+ }
+ /* If not expanded, use a perfect square */
+ if (expand == false) {
+ if (maxv[0] > maxv[1]) {
+ maxv[1] = maxv[0];
+ }
+ else {
+ maxv[0] = maxv[1];
+ }
+ }
+}
+
+/* calc texture coordinates using flat projected points */
+static void gp_calc_stroke_text_coordinates(const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], float(*r_uv)[2])
+{
+ float d[2];
+ d[0] = maxv[0] - minv[0];
+ d[1] = maxv[1] - minv[1];
+ for (int i = 0; i < totpoints; i++) {
+ r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
+ r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
+ }
+}
/* Get points of stroke always flat to view not affected by camera view or view position */
static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
@@ -447,7 +500,6 @@ static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*po
*r_direction = (int)locy[2];
}
-
/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
static void gp_triangulate_stroke_fill(bGPDstroke *gps)
{
@@ -455,14 +507,23 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
/* allocate memory for temporary areas */
gps->tot_triangles = gps->totpoints - 2;
- unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
+ uint (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
+ float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
int direction = 0;
/* convert to 2d and triangulate */
gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
- BLI_polyfill_calc(points2d, (unsigned int)gps->totpoints, direction, tmp_triangles);
+ BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
+
+ /* calc texture coordinates automatically */
+ float minv[2];
+ float maxv[2];
+ /* first needs bounding box data */
+ gp_calc_2d_bounding_box((const float(*)[2])points2d, gps->totpoints, minv, maxv, false);
+ /* calc uv data */
+ gp_calc_stroke_text_coordinates((const float(*)[2])points2d, gps->totpoints, minv, maxv, uv);
/* Number of triangles */
gps->tot_triangles = gps->totpoints - 2;
@@ -476,7 +537,12 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
}
for (int i = 0; i < gps->tot_triangles; i++) {
- memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
+ bGPDtriangle *stroke_triangle = &gps->triangles[i];
+ memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3]));
+ /* copy texture coordinates */
+ copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
+ copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
+ copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
}
}
else {
@@ -493,73 +559,128 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
}
/* clear memory */
- if (tmp_triangles) MEM_freeN(tmp_triangles);
- if (points2d) MEM_freeN(points2d);
+ MEM_SAFE_FREE(tmp_triangles);
+ MEM_SAFE_FREE(points2d);
+ MEM_SAFE_FREE(uv);
}
-
-/* draw fills for shapes */
-static void gp_draw_stroke_fill(
- bGPdata *gpd, bGPDstroke *gps,
- int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4])
+/* add a new fill point and texture coordinates to vertex buffer */
+static void gp_add_filldata_tobuffer(
+ const bGPDspoint *pt, const float uv[2], uint pos, uint texcoord, short flag,
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4])
{
float fpt[3];
+ float co[2];
- BLI_assert(gps->totpoints >= 3);
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* if 2d, need conversion */
+ if (!(flag & GP_STROKE_3DSPACE)) {
+ gp_calc_2d_stroke_fxy(fpt, flag, offsx, offsy, winx, winy, co);
+ copy_v2_v2(fpt, co);
+ fpt[2] = 0.0f; /* 2d always is z=0.0f */
+ }
- bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
+ immAttrib2f(texcoord, uv[0], uv[1]); /* texture coordinates */
+ immVertex3fv(pos, fpt); /* position */
+}
- /* Triangulation fill if high quality flag is enabled */
- if (palcolor->flag & PC_COLOR_HQ_FILL) {
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
- gp_triangulate_stroke_fill(gps);
- }
- BLI_assert(gps->tot_triangles >= 1);
+#if 0 /* GPXX disabled, not used in annotations */
+/* assign image texture for filling stroke */
+static int gp_set_filling_texture(Image *image, short flag)
+{
+ ImBuf *ibuf;
+ uint *bind = &image->bindcode[TEXTARGET_TEXTURE_2D];
+ int error = GL_NO_ERROR;
+ ImageUser iuser = { NULL };
+ void *lock;
- uint pos;
- if (gps->flag & GP_STROKE_3DSPACE) {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- }
- else {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- }
+ iuser.ok = true;
- immUniformColor4fv(color);
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
- immBegin(GWN_PRIM_TRIS, gps->tot_triangles * 3);
- /* TODO: use batch instead of immediate mode, to share vertices */
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ return (int)GL_INVALID_OPERATION;
+ }
- bGPDtriangle *stroke_triangle = gps->triangles;
- bGPDspoint *pt;
+ GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, GL_TEXTURE_2D,
+ false, false, image);
- if (gps->flag & GP_STROKE_3DSPACE) {
- for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
- for (int j = 0; j < 3; j++) {
- pt = &gps->points[stroke_triangle->verts[j]];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- immVertex3fv(pos, fpt);
- }
- }
- }
- else {
- for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
- for (int j = 0; j < 3; j++) {
- float co[2];
- pt = &gps->points[stroke_triangle->verts[j]];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- immVertex3fv(pos, fpt);
- }
- }
- }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ if (flag & GP_STYLE_COLOR_TEX_CLAMP) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ }
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ BKE_image_release_ibuf(image, ibuf, NULL);
- immEnd();
- immUnbindProgram();
+ return error;
+}
+#endif
+
+/* draw fills for shapes */
+static void gp_draw_stroke_fill(
+ bGPdata *gpd, bGPDstroke *gps,
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4])
+{
+ BLI_assert(gps->totpoints >= 3);
+ Material *ma = gpd->mat[gps->mat_nr];
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ /* Calculate triangles cache for filling area (must be done only after changes) */
+ if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
+ gp_triangulate_stroke_fill(gps);
+ }
+ BLI_assert(gps->tot_triangles >= 1);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_GPENCIL_FILL);
+
+ immUniformColor4fv(color);
+ immUniform4fv("color2", gp_style->mix_rgba);
+ immUniform1i("fill_type", gp_style->fill_style);
+ immUniform1f("mix_factor", gp_style->mix_factor);
+
+ immUniform1f("gradient_angle", gp_style->gradient_angle);
+ immUniform1f("gradient_radius", gp_style->gradient_radius);
+ immUniform1f("pattern_gridsize", gp_style->pattern_gridsize);
+ immUniform2fv("gradient_scale", gp_style->gradient_scale);
+ immUniform2fv("gradient_shift", gp_style->gradient_shift);
+
+ immUniform1f("texture_angle", gp_style->texture_angle);
+ immUniform2fv("texture_scale", gp_style->texture_scale);
+ immUniform2fv("texture_offset", gp_style->texture_offset);
+ immUniform1f("texture_opacity", gp_style->texture_opacity);
+ immUniform1i("t_mix", gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0);
+ immUniform1i("t_flip", gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0);
+#if 0 /* GPXX disabled, not used in annotations */
+ /* image texture */
+ if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_TEXTURE) || (gp_style->flag & GP_STYLE_COLOR_TEX_MIX)) {
+ gp_set_filling_texture(gp_style->ima, gp_style->flag);
}
+#endif
+ /* Draw all triangles for filling the polygon (cache must be calculated before) */
+ immBegin(GPU_PRIM_TRIS, gps->tot_triangles * 3);
+ /* TODO: use batch instead of immediate mode, to share vertices */
+
+ const bGPDtriangle *stroke_triangle = gps->triangles;
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
+ for (int j = 0; j < 3; j++) {
+ gp_add_filldata_tobuffer(
+ &gps->points[stroke_triangle->verts[j]], stroke_triangle->uv[j],
+ pos, texcoord, gps->flag,
+ offsx, offsy, winx, winy, diff_mat);
+ }
+ }
+
+ immEnd();
+ immUnbindProgram();
}
/* ----- Existing Strokes Drawing (3D and Point) ------ */
@@ -575,8 +696,8 @@ static void gp_draw_stroke_point(
float fpt[3];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
if (sflag & GP_STROKE_3DSPACE) {
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
@@ -594,94 +715,88 @@ static void gp_draw_stroke_point(
/* set point thickness (since there's only one of these) */
immUniform1f("size", (float)(thickness + 2) * pt->pressure);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(pos, fpt);
immEnd();
immUnbindProgram();
}
-/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug),
- short UNUSED(sflag), const float diff_mat[4][4], const float ink[4], bool cyclic)
+/* draw a given stroke in 3d (i.e. in 3d-space) */
+static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4], bool cyclic)
{
+ bGPDspoint *points = tgpw->gps->points;
+ int totpoints = tgpw->gps->totpoints;
+
+ const float viewport[2] = { (float)tgpw->winx, (float)tgpw->winy };
float curpressure = points[0].pressure;
float fpt[3];
- float cyclic_fpt[3];
- int draw_points = 0;
-
- /* if cyclic needs one vertex more */
- int cyclic_add = 0;
- if (cyclic) {
- ++cyclic_add;
- }
+ /* if cyclic needs more vertex */
+ int cyclic_add = (cyclic) ? 1 : 0;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint thickattrib = GPU_vertformat_attr_add(format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_GPENCIL_STROKE);
+ immUniform2fv("Viewport", viewport);
+ immUniform1f("pixsize", tgpw->rv3d->pixsize);
+ immUniform1f("pixelsize", U.pixelsize);
+ float obj_scale = (tgpw->ob->size[0] + tgpw->ob->size[1] + tgpw->ob->size[2]) / 3.0f;
- /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+ immUniform1f("objscale", obj_scale);
+ int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
+ immUniform1i("keep_size", keep_size);
+ immUniform1i("pixfactor", tgpw->gpd->pixfactor);
+ immUniform1i("xraymode", tgpw->gpd->xray_mode);
/* draw stroke curve */
GPU_line_width(max_ff(curpressure * thickness, 1.0f));
- immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2);
const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints; i++, pt++) {
- gp_set_point_varying_color(pt, ink, color);
- /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
- * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
- * Note: we want more visible levels of pressures when thickness is bigger.
- */
- if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
- /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
- if (draw_points < 2) {
- const bGPDspoint *pt2 = pt - 1;
- mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- immVertex3fv(pos, fpt);
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* first point for adjacency (not drawn) */
+ if (i == 0) {
+ gp_set_point_varying_color(points, ink, color);
+ immAttrib1f(thickattrib, max_ff(curpressure * thickness, 1.0f));
+ if ((cyclic) && (totpoints > 2)) {
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x);
}
- immEnd();
- draw_points = 0;
-
- curpressure = pt->pressure;
- GPU_line_width(max_ff(curpressure * thickness, 1.0f));
- immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
-
- /* need to roll-back one point to ensure that there are no gaps in the stroke */
- if (i != 0) {
- const bGPDspoint *pt2 = pt - 1;
- mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- gp_set_point_varying_color(pt2, ink, color);
- immVertex3fv(pos, fpt);
- ++draw_points;
+ else {
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
}
+ mul_v3_fl(fpt, -1.0f);
+ immVertex3fv(pos, fpt);
}
-
- /* now the point we want */
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* set point */
+ gp_set_point_varying_color(pt, ink, color);
+ immAttrib1f(thickattrib, max_ff(curpressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x);
immVertex3fv(pos, fpt);
- ++draw_points;
- if (cyclic && i == 0) {
- /* save first point to use in cyclic */
- copy_v3_v3(cyclic_fpt, fpt);
- }
+ curpressure = pt->pressure;
}
- if (cyclic) {
+ if (cyclic && totpoints > 2) {
/* draw line to first point to complete the cycle */
- immVertex3fv(pos, cyclic_fpt);
- ++draw_points;
- }
+ immAttrib1f(thickattrib, max_ff(points->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &points->x);
+ immVertex3fv(pos, fpt);
- /* if less of two points, need to repeat last point to avoid assert in immEnd() */
- if (draw_points < 2) {
- const bGPDspoint *pt2 = pt - 1;
- mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- gp_set_point_varying_color(pt2, ink, color);
+ /* now add adjacency point (not drawn) */
+ immAttrib1f(thickattrib, max_ff((points + 1)->pressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
+ immVertex3fv(pos, fpt);
+ }
+ /* last adjacency point (not drawn) */
+ else {
+ gp_set_point_varying_color(points + totpoints - 1, ink, color);
+ immAttrib1f(thickattrib, max_ff(curpressure * thickness, 1.0f));
+ mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 2)->x);
+ mul_v3_fl(fpt, -1.0f);
immVertex3fv(pos, fpt);
}
@@ -692,8 +807,9 @@ static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thi
/* ----- 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 UNUSED(debug), int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
+static void gp_draw_stroke_2d(
+ const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+ 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;
@@ -716,12 +832,12 @@ static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thi
int i;
float fpt[3];
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_TRI_STRIP, totpoints * 2 + 4);
+ immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4);
/* get x and y coordinates from first point */
mul_v3_m4v3(fpt, diff_mat, &points->x);
@@ -900,10 +1016,7 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
}
/* draw a set of strokes */
-static void gp_draw_strokes(
- bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
- bool debug, short lthick, const float opacity, const float tintcolor[4],
- const bool onion, const bool custonion, const float diff_mat[4][4])
+static void gp_draw_strokes(tGPDdraw *tgpw)
{
float tcolor[4];
float tfill[4];
@@ -912,31 +1025,41 @@ static void gp_draw_strokes(
GPU_enable_program_point_size();
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (bGPDstroke *gps = tgpw->t_gpf->strokes.first; gps; gps = gps->next) {
/* check if stroke can be drawn */
- if (gp_can_draw_stroke(gps, dflag) == false) {
+ if (gp_can_draw_stroke(gps, tgpw->dflag) == false) {
continue;
}
/* check if the color is visible */
- bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
- if ((palcolor == NULL) ||
- (palcolor->flag & PC_COLOR_HIDE) ||
+ Material *ma = tgpw->gpd->mat[gps->mat_nr];
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ if ((gp_style == NULL) ||
+ (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
/* if onion and ghost flag do not draw*/
- (onion && (palcolor->flag & PC_COLOR_ONIONSKIN)))
+ (tgpw->onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN)))
+ {
+ continue;
+ }
+
+ /* if disable fill, the colors with fill must be omitted too except fill boundary strokes */
+ if ((tgpw->disable_fill == 1) &&
+ (gp_style->fill_rgba[3] > 0.0f) &&
+ ((gps->flag & GP_STROKE_NOFILL) == 0))
{
continue;
}
/* calculate thickness */
- sthickness = gps->thickness + lthick;
+ sthickness = gps->thickness + tgpw->lthick;
if (sthickness <= 0) {
continue;
}
/* check which stroke-drawer to use */
- if (dflag & GP_DRAWDATA_ONLY3D) {
- const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
+ if (tgpw->dflag & GP_DRAWDATA_ONLY3D) {
+ const int no_xray = (tgpw->dflag & GP_DRAWDATA_NO_XRAY);
int mask_orig = 0;
if (no_xray) {
@@ -951,57 +1074,64 @@ static void gp_draw_strokes(
/* 3D Fill */
//if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
- if (gps->totpoints >= 3) {
- /* set color using palette, tint color and opacity */
- interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
- tfill[3] = palcolor->fill[3] * opacity;
- if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ if ((gps->totpoints >= 3) && (tgpw->disable_fill != 1)) {
+ /* set color using material, tint color and opacity */
+ interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
+ tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity;
+ if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
const float *color;
- if (!onion) {
+ if (!tgpw->onion) {
color = tfill;
}
else {
- if (custonion) {
- color = tintcolor;
+ if (tgpw->custonion) {
+ color = tgpw->tintcolor;
}
else {
- ARRAY_SET_ITEMS(tfill, UNPACK3(palcolor->fill), tintcolor[3]);
+ ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]);
color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
+ gp_draw_stroke_fill(
+ tgpw->gpd, gps,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy, tgpw->diff_mat, color);
}
}
/* 3D Stroke */
- /* set color using palette, tint color and opacity */
- if (!onion) {
- interp_v3_v3v3(tcolor, palcolor->color, tintcolor, tintcolor[3]);
- tcolor[3] = palcolor->color[3] * opacity;
+ /* set color using material tint color and opacity */
+ if (!tgpw->onion) {
+ interp_v3_v3v3(tcolor, gp_style->stroke_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
+ tcolor[3] = gp_style->stroke_rgba[3] * tgpw->opacity;
copy_v4_v4(ink, tcolor);
}
else {
- if (custonion) {
- copy_v4_v4(ink, tintcolor);
+ if (tgpw->custonion) {
+ copy_v4_v4(ink, tgpw->tintcolor);
}
else {
- ARRAY_SET_ITEMS(tcolor, palcolor->color[0], palcolor->color[1], palcolor->color[2], opacity);
+ ARRAY_SET_ITEMS(tcolor, UNPACK3(gp_style->stroke_rgba), tgpw->opacity);
copy_v4_v4(ink, tcolor);
}
}
- if (palcolor->flag & PC_COLOR_VOLUMETRIC) {
+ if (gp_style->mode == GP_STYLE_MODE_DOTS) {
/* volumetric stroke drawing */
- gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
+ if (tgpw->disable_fill != 1) {
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
+ }
}
else {
/* 3D Lines - OpenGL primitives-based */
if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, sthickness, dflag, gps->flag, offsx, offsy, winx, winy,
- diff_mat, ink);
+ if (tgpw->disable_fill != 1) {
+ gp_draw_stroke_point(gps->points, sthickness, tgpw->dflag, gps->flag,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy,
+ tgpw->diff_mat, ink);
+ }
}
else {
- gp_draw_stroke_3d(gps->points, gps->totpoints, sthickness, debug, gps->flag,
- diff_mat, ink, gps->flag & GP_STROKE_CYCLIC);
+ tgpw->gps = gps;
+ gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC);
}
}
if (no_xray) {
@@ -1014,58 +1144,63 @@ static void gp_draw_strokes(
else {
/* 2D - Fill */
if (gps->totpoints >= 3) {
- /* set color using palette, tint color and opacity */
- interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
- tfill[3] = palcolor->fill[3] * opacity;
- if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ /* set color using material, tint color and opacity */
+ interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
+ tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity;
+ if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
const float *color;
- if (!onion) {
+ if (!tgpw->onion) {
color = tfill;
}
else {
- if (custonion) {
- color = tintcolor;
+ if (tgpw->custonion) {
+ color = tgpw->tintcolor;
}
else {
- ARRAY_SET_ITEMS(tfill, palcolor->fill[0], palcolor->fill[1], palcolor->fill[2],
- tintcolor[3]);
+ ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]);
color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
+ gp_draw_stroke_fill(
+ tgpw->gpd, gps,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy, tgpw->diff_mat, color);
}
}
/* 2D Strokes... */
- /* set color using palette, tint color and opacity */
- if (!onion) {
- interp_v3_v3v3(tcolor, palcolor->color, tintcolor, tintcolor[3]);
- tcolor[3] = palcolor->color[3] * opacity;
+ /* set color using material, tint color and opacity */
+ if (!tgpw->onion) {
+ interp_v3_v3v3(tcolor, gp_style->stroke_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
+ tcolor[3] = gp_style->stroke_rgba[3] * tgpw->opacity;
copy_v4_v4(ink, tcolor);
}
else {
- if (custonion) {
- copy_v4_v4(ink, tintcolor);
+ if (tgpw->custonion) {
+ copy_v4_v4(ink, tgpw->tintcolor);
}
else {
- ARRAY_SET_ITEMS(tcolor, palcolor->color[0], palcolor->color[1], palcolor->color[2], opacity);
+ ARRAY_SET_ITEMS(tcolor, UNPACK3(gp_style->stroke_rgba), tgpw->opacity);
copy_v4_v4(ink, tcolor);
}
}
- if (palcolor->flag & PC_COLOR_VOLUMETRIC) {
+ if (gp_style->mode == GP_STYLE_MODE_DOTS) {
/* blob/disk-based "volumetric" drawing */
- gp_draw_stroke_volumetric_2d(gps->points, gps->totpoints, sthickness, dflag, gps->flag,
- offsx, offsy, winx, winy, diff_mat, ink);
+ gp_draw_stroke_volumetric_2d(
+ gps->points, gps->totpoints, sthickness, tgpw->dflag, gps->flag,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy, tgpw->diff_mat, ink);
}
else {
/* normal 2D strokes */
if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points, sthickness, dflag, gps->flag, offsx, offsy, winx, winy,
- diff_mat, ink);
+ gp_draw_stroke_point(
+ gps->points, sthickness, tgpw->dflag, gps->flag,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy,
+ tgpw->diff_mat, ink);
}
else {
- gp_draw_stroke_2d(gps->points, gps->totpoints, sthickness, dflag, gps->flag, debug,
- offsx, offsy, winx, winy, diff_mat, ink);
+ gp_draw_stroke_2d(
+ gps->points, gps->totpoints, sthickness, tgpw->dflag, gps->flag, false,
+ tgpw->offsx, tgpw->offsy, tgpw->winx, tgpw->winy, tgpw->diff_mat, ink);
}
}
}
@@ -1114,14 +1249,16 @@ static void gp_draw_strokes_edit(
if ((gps->flag & GP_STROKE_SELECT) == 0)
continue;
- /* verify palette color lock */
+ /* verify color lock */
{
- bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
- if (palcolor != NULL) {
- if (palcolor->flag & PC_COLOR_HIDE) {
+ Material *ma = gpd->mat[gps->mat_nr];
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ if (gp_style != NULL) {
+ if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
continue;
}
- if (((lflag & GP_LAYER_UNLOCK_COLOR) == 0) && (palcolor->flag & PC_COLOR_LOCKED)) {
+ if (((lflag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
continue;
}
}
@@ -1143,28 +1280,29 @@ static void gp_draw_strokes_edit(
}
/* for now, we assume that the base color of the points is not too close to the real color */
- /* set color using palette */
- bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
+ /* set color using material */
+ Material *ma = gpd->mat[gps->mat_nr];
+ MaterialGPencilStyle *gp_style = ma->gp_style;
float selectColor[4];
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
selectColor[3] = alpha;
- Gwn_VertFormat *format = immVertexFormat();
+ GPUVertFormat *format = immVertexFormat();
uint pos; /* specified later */
- uint size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
if (gps->flag & GP_STROKE_3DSPACE) {
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
}
else {
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
}
- immBegin(GWN_PRIM_POINTS, gps->totpoints);
+ immBegin(GPU_PRIM_POINTS, gps->totpoints);
/* Draw start and end point differently if enabled stroke direction hint */
bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
@@ -1189,7 +1327,7 @@ static void gp_draw_strokes_edit(
immAttrib1f(size, vsize);
}
else {
- immAttrib3fv(color, palcolor->color);
+ immAttrib3fv(color, gp_style->stroke_rgba);
immAttrib1f(size, bsize);
}
@@ -1229,98 +1367,75 @@ static void gp_draw_strokes_edit(
/* ----- General Drawing ------ */
-/* draw onion-skinning for a layer */
-static void gp_draw_onionskins(
- bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
- int UNUSED(cfra), int dflag, bool debug, const float diff_mat[4][4])
+
+/* draw interpolate strokes (used only while operator is running) */
+void ED_gp_draw_interpolation(const bContext *C, tGPDinterpolate *tgpi, const int type)
{
- const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)};
- const float alpha = 1.0f;
+ tGPDdraw tgpw;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ tGPDinterpolate_layer *tgpil;
+ Object *obact = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
float color[4];
- /* 1) Draw Previous Frames First */
- if (gpl->flag & GP_LAYER_GHOST_PREVCOL) {
- copy_v3_v3(color, gpl->gcolor_prev);
- }
- else {
- copy_v3_v3(color, default_color);
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
+ color[3] = 0.6f;
+ int dflag = 0;
+ /* if 3d stuff, enable flags */
+ if (type == REGION_DRAW_POST_VIEW) {
+ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
- if (gpl->gstep > 0) {
- /* draw previous frames first */
- for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
- /* check if frame is drawable */
- if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
- /* alpha decreases with distance from curframe index */
- float fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
- color[3] = alpha * fac * 0.66f;
- gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
- true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat);
- }
- else
- break;
- }
- }
- else if (gpl->gstep == 0) {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->prev) {
- color[3] = (alpha / 7);
- gp_draw_strokes(gpd, gpf->prev, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
- true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat);
- }
- }
- else {
- /* don't draw - disabled */
- }
+ tgpw.rv3d = rv3d;
+ tgpw.depsgraph = depsgraph;
+ tgpw.ob = obact;
+ tgpw.gpd = tgpi->gpd;
+ tgpw.offsx = 0;
+ tgpw.offsy = 0;
+ tgpw.winx = tgpi->ar->winx;
+ tgpw.winy = tgpi->ar->winy;
+ tgpw.dflag = dflag;
- /* 2) Now draw next frames */
- if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
- copy_v3_v3(color, gpl->gcolor_next);
- }
- else {
- copy_v3_v3(color, default_color);
- }
+ /* turn on alpha-blending */
+ glEnable(GL_BLEND);
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ /* calculate parent position */
+ ED_gpencil_parent_location(depsgraph, obact, tgpi->gpd, tgpil->gpl, tgpw.diff_mat);
+ if (tgpil->interFrame) {
+ tgpw.gpl = tgpil->gpl;
+ tgpw.gpf = tgpil->interFrame;
+ tgpw.t_gpf = tgpil->interFrame;
- if (gpl->gstep_next > 0) {
- /* now draw next frames */
- for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
- /* check if frame is drawable */
- if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
- /* alpha decreases with distance from curframe index */
- float fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
- color[3] = alpha * fac * 0.66f;
- gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
- true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat);
- }
- else
- break;
- }
- }
- else if (gpl->gstep_next == 0) {
- /* draw the strokes for the ghost frames (at half of the alpha set by user) */
- if (gpf->next) {
- color[3] = (alpha / 4);
- gp_draw_strokes(gpd, gpf->next, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
- true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat);
+ tgpw.lthick = tgpil->gpl->line_change;
+ tgpw.opacity = 1.0;
+ copy_v4_v4(tgpw.tintcolor, color);
+ tgpw.onion = true;
+ tgpw.custonion = true;
+
+ gp_draw_strokes(&tgpw);
}
}
- else {
- /* don't draw - disabled */
- }
+ glDisable(GL_BLEND);
}
/* draw interpolate strokes (used only while operator is running) */
-void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
+void ED_gp_draw_primitives(const bContext *C, tGPDprimitive *tgpi, const int type)
{
- tGPDinterpolate_layer *tgpil;
- float diff_mat[4][4];
- float color[4];
+ tGPDdraw tgpw;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
- int offsx = 0;
- int offsy = 0;
- int winx = tgpi->ar->winx;
- int winy = tgpi->ar->winy;
+ /* if idle, do not draw */
+ if (tgpi->flag == 0) {
+ return;
+ }
+ Object *obact = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+
+ float color[4];
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
color[3] = 0.6f;
int dflag = 0;
@@ -1329,32 +1444,71 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
+ tgpw.rv3d = rv3d;
+ tgpw.depsgraph = depsgraph;
+ tgpw.ob = obact;
+ tgpw.gpd = tgpi->gpd;
+ tgpw.offsx = 0;
+ tgpw.offsy = 0;
+ tgpw.winx = tgpi->ar->winx;
+ tgpw.winy = tgpi->ar->winy;
+ tgpw.dflag = dflag;
+
/* turn on alpha-blending */
GPU_blend(true);
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- /* calculate parent position */
- ED_gpencil_parent_location(tgpil->gpl, diff_mat);
- if (tgpil->interFrame) {
- gp_draw_strokes(tgpi->gpd, tgpil->interFrame, offsx, offsy, winx, winy, dflag, false,
- tgpil->gpl->thickness, 1.0f, color, true, true, diff_mat);
+ /* calculate parent position */
+ ED_gpencil_parent_location(depsgraph, obact, tgpi->gpd, tgpi->gpl, tgpw.diff_mat);
+ if (tgpi->gpf) {
+ tgpw.gps = tgpi->gpf->strokes.first;
+ if (tgpw.gps->totpoints > 0) {
+ tgpw.gpl = tgpi->gpl;
+ tgpw.gpf = tgpi->gpf;
+ tgpw.t_gpf = tgpi->gpf;
+
+ tgpw.lthick = tgpi->gpl->line_change;
+ tgpw.opacity = 1.0;
+ copy_v4_v4(tgpw.tintcolor, color);
+ tgpw.onion = true;
+ tgpw.custonion = true;
+
+ gp_draw_strokes(&tgpw);
}
}
GPU_blend(false);
}
+/* wrapper to draw strokes for filling operator */
+void ED_gp_draw_fill(tGPDdraw *tgpw)
+{
+ gp_draw_strokes(tgpw);
+}
+
/* loop over gpencil data layers, drawing them */
-static void gp_draw_data_layers(
- const bGPDbrush *brush, float alpha, bGPdata *gpd,
+static void gp_draw_data_layers(RegionView3D *rv3d,
+ const Brush *brush, float alpha, Object *ob, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
float diff_mat[4][4];
+ tGPDdraw tgpw;
+
+ tgpw.rv3d = rv3d;
+ tgpw.depsgraph = NULL; /* XXX: This is not used here */
+ tgpw.ob = ob;
+ tgpw.gpd = gpd;
+ tgpw.gpl = NULL;
+ tgpw.gpf = NULL;
+ tgpw.t_gpf = NULL;
+ tgpw.offsx = offsx;
+ tgpw.offsy = offsy;
+ tgpw.winx = winx;
+ tgpw.winy = winy;
+ tgpw.dflag = dflag;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* calculate parent position */
- ED_gpencil_parent_location(gpl, diff_mat);
+ ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, diff_mat);
- bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG);
- short lthick = brush->thickness + gpl->thickness;
+ short lthick = brush->size + gpl->line_change;
/* don't draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE)
@@ -1383,30 +1537,20 @@ static void gp_draw_data_layers(
/* volumetric strokes... */
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
- /* HQ fills... */
- GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_HQ_FILL), GP_DRAWDATA_HQ_FILL);
-
#undef GP_DRAWFLAG_APPLY
- /* Draw 'onionskins' (frame left + right)
- * - It is only possible to show these if the option is enabled
- * - The "no onions" flag prevents ghosts from appearing during animation playback/scrubbing
- * and in renders
- * - The per-layer "always show" flag however overrides the playback/render restriction,
- * allowing artists to selectively turn onionskins on/off during playback
- */
- if ((gpl->flag & GP_LAYER_ONIONSKIN) &&
- ((dflag & GP_DRAWDATA_NO_ONIONS) == 0 || (gpl->flag & GP_LAYER_GHOST_ALWAYS)))
- {
- /* Drawing method - only immediately surrounding (gstep = 0),
- * or within a frame range on either side (gstep > 0)
- */
- gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat);
- }
+ tgpw.gpl = gpl;
+ tgpw.gpf = gpf;
+ tgpw.t_gpf = gpf; // XXX?
+ tgpw.lthick = gpl->line_change;
+ tgpw.opacity = gpl->opacity;
+ copy_v4_v4(tgpw.tintcolor, gpl->tintcolor);
+ tgpw.onion = false;
+ tgpw.custonion = false;
+ copy_m4_m4(tgpw.diff_mat, diff_mat);
/* draw the strokes already in active frame */
- gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness,
- gpl->opacity, gpl->tintcolor, false, false, diff_mat);
+ gp_draw_strokes(&tgpw);
/* Draw verts of selected strokes
* - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
@@ -1435,19 +1579,25 @@ static void gp_draw_data_layers(
* It should also be noted that sbuffer contains temporary point types
* i.e. tGPspoints NOT bGPDspoints
*/
- if (gpd->sflag & PC_COLOR_VOLUMETRIC) {
- gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick,
- dflag, gpd->scolor);
+ if (gpd->runtime.mode == GP_STYLE_MODE_DOTS) {
+ gp_draw_stroke_volumetric_buffer(
+ gpd->runtime.sbuffer,
+ gpd->runtime.sbuffer_size, lthick,
+ dflag, gpd->runtime.scolor);
}
else {
- gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor, gpd->sfill);
+ gp_draw_stroke_buffer(
+ gpd->runtime.sbuffer,
+ gpd->runtime.sbuffer_size, lthick,
+ dflag, gpd->runtime.sbuffer_sflag,
+ gpd->runtime.scolor, gpd->runtime.sfill);
}
}
}
}
/* draw a short status message in the top-right corner */
-static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
+static void UNUSED_FUNCTION(gp_draw_status_text)(const bGPdata *gpd, ARegion *ar)
{
rcti rect;
@@ -1493,8 +1643,8 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
}
/* draw grease-pencil datablock */
-static void gp_draw_data(
- const bGPDbrush *brush, float alpha, bGPdata *gpd,
+static void gp_draw_data(RegionView3D *rv3d,
+ const Brush *brush, float alpha, Object *ob, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
/* turn on smooth lines (i.e. anti-aliasing) */
@@ -1510,7 +1660,7 @@ static void gp_draw_data(
GPU_blend(true);
/* draw! */
- gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag);
+ gp_draw_data_layers(rv3d, brush, alpha, ob, gpd, offsx, offsy, winx, winy, cfra, dflag);
/* turn off alpha blending, then smooth lines */
GPU_blend(false); // alpha blending
@@ -1519,33 +1669,22 @@ static void gp_draw_data(
/* if we have strokes for scenes (3d view)/clips (movie clip editor)
* and objects/tracks, multiple data blocks have to be drawn */
-static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
- int cfra, int dflag, const char spacetype)
+static void gp_draw_data_all(
+ RegionView3D *rv3d, Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy,
+ int cfra, int dflag, const char UNUSED(spacetype))
{
bGPdata *gpd_source = NULL;
- ToolSettings *ts;
- bGPDbrush *brush = NULL;
+ ToolSettings *ts = NULL;
+ Brush *brush = NULL;
if (scene) {
ts = scene->toolsettings;
- brush = BKE_gpencil_brush_getactive(ts);
- /* if no brushes, create default set */
- if (brush == NULL) {
- BKE_gpencil_brush_init_presets(ts);
- brush = BKE_gpencil_brush_getactive(ts);
- }
-
- if (spacetype == SPACE_VIEW3D) {
- gpd_source = (scene->gpd ? scene->gpd : NULL);
- }
- else if (spacetype == SPACE_CLIP && scene->clip) {
- /* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
- gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
- }
+ brush = BKE_brush_getactive_gpencil(ts);
if (gpd_source) {
if (brush != NULL) {
- gp_draw_data(brush, ts->gp_sculpt.alpha, gpd_source,
- offsx, offsy, winx, winy, cfra, dflag);
+ gp_draw_data(
+ rv3d, brush, 1.0f, NULL, gpd_source,
+ offsx, offsy, winx, winy, cfra, dflag);
}
}
}
@@ -1554,76 +1693,70 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
* if gpd_source == gpd, we don't have any object/track data and we can skip */
if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
if (brush != NULL) {
- gp_draw_data(brush, ts->gp_sculpt.alpha, gpd,
- offsx, offsy, winx, winy, cfra, dflag);
+ gp_draw_data(
+ rv3d, brush, 1.0f, NULL, gpd,
+ offsx, offsy, winx, winy, cfra, dflag);
}
}
}
/* ----- Grease Pencil Sketches Drawing API ------ */
-/* ............................
- * XXX
- * We need to review the calls below, since they may be/are not that suitable for
- * the new ways that we intend to be drawing data...
- * ............................ */
-/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
-void ED_gpencil_draw_2dimage(const bContext *C)
+/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
+ * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+ * second time with only3d=false for screen-aligned strokes */
+void ED_gpencil_draw_view3d(
+ wmWindowManager *wm,
+ Scene *scene,
+ ViewLayer *view_layer,
+ struct Depsgraph *depsgraph,
+ View3D *v3d,
+ ARegion *ar,
+ bool only3d)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
-
- int offsx, offsy, sizex, sizey;
- int dflag = GP_DRAWDATA_NOSTATUS;
+ int dflag = 0;
+ RegionView3D *rv3d = ar->regiondata;
+ int offsx, offsy, winx, winy;
- bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
+ /* check that we have grease-pencil stuff to draw */
+ // XXX: This is the only place that still uses this function
+ bGPdata *gpd = ED_gpencil_data_get_active_v3d(view_layer);
if (gpd == NULL) return;
- /* calculate rect */
- switch (sa->spacetype) {
- case SPACE_IMAGE: /* image */
- case SPACE_CLIP: /* clip */
- {
- /* just draw using standard scaling (settings here are currently ignored anyways) */
- /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
+ /* when rendering to the offscreen buffer we don't want to
+ * deal with the camera border, otherwise map the coords to the camera border. */
+ if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
+ rctf rectf;
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &rectf, true); /* no shift */
+
+ offsx = round_fl_to_int(rectf.xmin);
+ offsy = round_fl_to_int(rectf.ymin);
+ winx = round_fl_to_int(rectf.xmax - rectf.xmin);
+ winy = round_fl_to_int(rectf.ymax - rectf.ymin);
+ }
+ else {
+ offsx = 0;
+ offsy = 0;
+ winx = ar->winx;
+ winy = ar->winy;
+ }
- wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+ /* set flags */
+ if (only3d) {
+ /* 3D strokes/3D space:
+ * - only 3D space points
+ * - don't status text either (as it's the wrong space)
+ */
+ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
+ }
- dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
- break;
- }
- case SPACE_SEQ: /* sequence */
- {
- /* just draw using standard scaling (settings here are currently ignored anyways) */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
-
- /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
- * and everything moved to standard View2d
- */
- dflag |= GP_DRAWDATA_ONLYV2D;
- break;
- }
- default: /* for spacetype not yet handled */
- offsx = 0;
- offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
-
- dflag |= GP_DRAWDATA_ONLYI2D;
- break;
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ /* don't draw status text when "only render" flag is set */
+ dflag |= GP_DRAWDATA_NOSTATUS;
}
- if (ED_screen_animation_playing(wm)) {
+ if ((wm == NULL) || ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
* OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
*/
@@ -1631,85 +1764,46 @@ void ED_gpencil_draw_2dimage(const bContext *C)
}
/* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
+ gp_draw_data_all(rv3d, scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
-/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with onlyv2d=true to draw 'canvas' strokes,
- * second time with onlyv2d=false for screen-aligned strokes */
-void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int dflag = 0;
-
- /* check that we have grease-pencil stuff to draw */
- if (sa == NULL) return;
- bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
- if (gpd == NULL) return;
-
- /* special hack for Image Editor */
- /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
- if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP))
- dflag |= GP_DRAWDATA_IEDITHACK;
-
- /* draw it! */
- if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
- if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS;
-
- gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
-
- /* draw status text (if in screen/pixel-space) */
- if (!onlyv2d) {
- gp_draw_status_text(gpd, ar);
- }
-}
-
-/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
- * second time with only3d=false for screen-aligned strokes */
-void ED_gpencil_draw_view3d(wmWindowManager *wm,
- Scene *scene,
- ViewLayer *view_layer,
- struct Depsgraph *depsgraph,
- View3D *v3d,
- ARegion *ar,
- bool only3d)
+/* draw grease-pencil sketches to specified 3d-view for gp object
+ * assuming that matrices are already set correctly
+ */
+void ED_gpencil_draw_view3d_object(wmWindowManager *wm, Scene *scene, Depsgraph *depsgraph, Object *ob, View3D *v3d, ARegion *ar, bool only3d)
{
int dflag = 0;
RegionView3D *rv3d = ar->regiondata;
- int offsx, offsy, winx, winy;
+ int offsx, offsy, winx, winy;
/* check that we have grease-pencil stuff to draw */
- bGPdata *gpd = ED_gpencil_data_get_active_v3d(scene, view_layer);
+ bGPdata *gpd = ob->data;
if (gpd == NULL) return;
/* when rendering to the offscreen buffer we don't want to
- * deal with the camera border, otherwise map the coords to the camera border. */
+ * deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
rctf rectf;
ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &rectf, true); /* no shift */
offsx = round_fl_to_int(rectf.xmin);
offsy = round_fl_to_int(rectf.ymin);
- winx = round_fl_to_int(rectf.xmax - rectf.xmin);
- winy = round_fl_to_int(rectf.ymax - rectf.ymin);
+ winx = round_fl_to_int(rectf.xmax - rectf.xmin);
+ winy = round_fl_to_int(rectf.ymax - rectf.ymin);
}
else {
offsx = 0;
offsy = 0;
- winx = ar->winx;
- winy = ar->winy;
+ winx = ar->winx;
+ winy = ar->winy;
}
/* set flags */
if (only3d) {
/* 3D strokes/3D space:
- * - only 3D space points
- * - don't status text either (as it's the wrong space)
- */
+ * - only 3D space points
+ * - don't status text either (as it's the wrong space)
+ */
dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
@@ -1720,20 +1814,23 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm,
if ((wm == NULL) || ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
- * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
- */
+ * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
+ */
dflag |= GP_DRAWDATA_NO_ONIONS;
}
/* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+ ToolSettings *ts = scene->toolsettings;
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ if (brush != NULL) {
+ gp_draw_data(rv3d, brush, 1.0f, ob, gpd,
+ offsx, offsy, winx, winy, CFRA, dflag);
+ }
}
-void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
+void ED_gpencil_draw_ex(RegionView3D *rv3d, Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
- gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
+ gp_draw_data_all(rv3d, scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
-
-/* ************************************************** */
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 5e62a87caf3..88f935eb8bf 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -492,6 +492,8 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* make a copy of stroke, then of its points array */
gpsn = MEM_dupallocN(gps);
gpsn->points = MEM_dupallocN(gps->points);
+ gpsn->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, gpsn);
/* duplicate triangle information */
gpsn->triangles = MEM_dupallocN(gps->triangles);
/* append stroke to frame */
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
new file mode 100644
index 00000000000..78286e3f672
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -0,0 +1,1566 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Matias Mendiola
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_add_monkey.c
+ * \ingroup edgpencil
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+
+/* Definition of the most important info from a color */
+typedef struct ColorTemplate {
+ const char *name;
+ float line[4];
+ float fill[4];
+} ColorTemplate;
+
+/* Add color an ensure duplications (matched by name) */
+static int gpencil_monkey_color(Main *bmain, Object *ob, const ColorTemplate *pct)
+{
+ short *totcol = give_totcolp(ob);
+ Material *ma = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (STREQ(ma->id.name, pct->name)) {
+ return i;
+ }
+ }
+
+ /* create a new one */
+ BKE_object_material_slot_add(bmain, ob);
+ ma = BKE_material_add_gpencil(bmain, pct->name);
+ assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+
+ copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+
+ return BKE_gpencil_get_material_index(ob, ma) - 1;
+}
+
+/* ***************************************************************** */
+/* Monkey Geometry */
+
+static const float data0[538 * GP_PRIM_DATABUF_SIZE] = {
+ -0.509f, 0.0f, -0.156f, 0.267f, 0.362f, -0.522f, 0.0f, -0.159f, 0.31f, 0.407f, -0.531f, 0.0f, -0.16f, 0.347f, 0.426f, -0.543f, -0.0f, -0.162f, 0.38f, 0.439f,
+ -0.554f, -0.0f, -0.163f, 0.409f, 0.448f, -0.566f, -0.0f, -0.165f, 0.433f, 0.458f, -0.578f, -0.0f, -0.167f, 0.454f, 0.478f, -0.591f, -0.0f, -0.168f, 0.471f, 0.5f,
+ -0.604f, -0.0f, -0.169f, 0.485f, 0.51f, -0.619f, -0.0f, -0.171f, 0.496f, 0.516f, -0.634f, -0.0f, -0.171f, 0.504f, 0.519f, -0.649f, -0.0f, -0.171f, 0.511f, 0.519f,
+ -0.665f, -0.0f, -0.17f, 0.516f, 0.521f, -0.681f, -0.0f, -0.17f, 0.521f, 0.53f, -0.697f, -0.0f, -0.169f, 0.524f, 0.533f, -0.713f, -0.0f, -0.167f, 0.527f, 0.533f,
+ -0.729f, 0.0f, -0.165f, 0.53f, 0.534f, -0.745f, 0.0f, -0.161f, 0.531f, 0.534f, -0.761f, 0.0f, -0.157f, 0.533f, 0.535f, -0.777f, 0.0f, -0.153f, 0.534f, 0.535f,
+ -0.792f, 0.0f, -0.148f, 0.535f, 0.536f, -0.808f, 0.0f, -0.144f, 0.535f, 0.535f, -0.822f, 0.0f, -0.139f, 0.536f, 0.537f, -0.837f, 0.0f, -0.133f, 0.536f, 0.537f,
+ -0.852f, 0.0f, -0.128f, 0.536f, 0.537f, -0.866f, 0.0f, -0.122f, 0.536f, 0.537f, -0.88f, 0.0f, -0.115f, 0.536f, 0.537f, -0.894f, 0.0f, -0.109f, 0.536f, 0.537f,
+ -0.908f, 0.0f, -0.101f, 0.535f, 0.535f, -0.922f, 0.0f, -0.092f, 0.535f, 0.535f, -0.936f, 0.0f, -0.082f, 0.534f, 0.534f, -0.949f, 0.0f, -0.072f, 0.534f, 0.534f,
+ -0.963f, 0.0f, -0.061f, 0.534f, 0.534f, -0.976f, 0.0f, -0.05f, 0.534f, 0.534f, -0.988f, 0.0f, -0.039f, 0.534f, 0.534f, -1.0f, 0.0f, -0.028f, 0.533f, 0.534f,
+ -1.011f, 0.0f, -0.017f, 0.533f, 0.533f, -1.022f, 0.0f, -0.007f, 0.533f, 0.534f, -1.033f, 0.0f, 0.004f, 0.533f, 0.533f, -1.043f, 0.0f, 0.014f, 0.532f, 0.532f,
+ -1.053f, 0.0f, 0.025f, 0.532f, 0.532f, -1.062f, 0.0f, 0.036f, 0.531f, 0.531f, -1.071f, 0.0f, 0.046f, 0.531f, 0.531f, -1.078f, 0.0f, 0.057f, 0.531f, 0.531f,
+ -1.085f, 0.0f, 0.068f, 0.531f, 0.531f, -1.092f, 0.0f, 0.08f, 0.532f, 0.532f, -1.098f, 0.0f, 0.091f, 0.533f, 0.533f, -1.104f, 0.0f, 0.105f, 0.535f, 0.535f,
+ -1.11f, 0.0f, 0.119f, 0.539f, 0.539f, -1.115f, 0.0f, 0.133f, 0.54f, 0.54f, -1.118f, 0.0f, 0.148f, 0.541f, 0.541f, -1.121f, 0.0f, 0.162f, 0.542f, 0.542f,
+ -1.123f, 0.0f, 0.177f, 0.542f, 0.542f, -1.125f, 0.0f, 0.193f, 0.543f, 0.543f, -1.125f, 0.0f, 0.208f, 0.543f, 0.543f, -1.125f, 0.0f, 0.225f, 0.543f, 0.543f,
+ -1.124f, 0.0f, 0.241f, 0.545f, 0.545f, -1.122f, 0.0f, 0.258f, 0.546f, 0.546f, -1.119f, 0.0f, 0.274f, 0.548f, 0.548f, -1.116f, 0.0f, 0.29f, 0.549f, 0.549f,
+ -1.111f, 0.0f, 0.305f, 0.549f, 0.549f, -1.106f, 0.0f, 0.318f, 0.549f, 0.549f, -1.1f, 0.0f, 0.33f, 0.549f, 0.549f, -1.094f, 0.0f, 0.34f, 0.549f, 0.549f,
+ -1.087f, 0.0f, 0.349f, 0.55f, 0.55f, -1.08f, 0.0f, 0.357f, 0.549f, 0.549f, -1.072f, 0.0f, 0.365f, 0.55f, 0.55f, -1.063f, 0.0f, 0.372f, 0.551f, 0.551f,
+ -1.054f, 0.0f, 0.379f, 0.552f, 0.552f, -1.044f, 0.0f, 0.385f, 0.553f, 0.553f, -1.034f, 0.0f, 0.391f, 0.553f, 0.553f, -1.024f, 0.0f, 0.396f, 0.554f, 0.554f,
+ -1.013f, 0.0f, 0.401f, 0.554f, 0.554f, -1.003f, 0.0f, 0.405f, 0.554f, 0.554f, -0.991f, 0.0f, 0.409f, 0.554f, 0.554f, -0.978f, 0.0f, 0.412f, 0.555f, 0.555f,
+ -0.964f, -0.0f, 0.414f, 0.555f, 0.555f, -0.949f, -0.0f, 0.414f, 0.556f, 0.556f, -0.934f, -0.0f, 0.413f, 0.556f, 0.556f, -0.919f, -0.0f, 0.412f, 0.557f, 0.557f,
+ -0.905f, -0.0f, 0.41f, 0.557f, 0.557f, -0.892f, -0.0f, 0.406f, 0.557f, 0.557f, -0.879f, -0.0f, 0.402f, 0.557f, 0.558f, -0.867f, -0.0f, 0.398f, 0.557f, 0.557f,
+ -0.855f, -0.0f, 0.394f, 0.557f, 0.557f, -0.843f, -0.0f, 0.388f, 0.557f, 0.557f, -0.831f, -0.0f, 0.381f, 0.558f, 0.557f, -0.82f, -0.0f, 0.375f, 0.558f, 0.557f,
+ -0.81f, -0.0f, 0.368f, 0.558f, 0.558f, -0.801f, -0.0f, 0.362f, 0.558f, 0.558f, -0.793f, -0.0f, 0.357f, 0.557f, 0.559f, -0.784f, 0.0f, 0.353f, 0.557f, 0.559f,
+ -0.776f, 0.0f, 0.35f, 0.556f, 0.559f, -0.768f, 0.0f, 0.348f, 0.556f, 0.559f, -0.76f, 0.0f, 0.346f, 0.555f, 0.559f, -0.752f, 0.0f, 0.346f, 0.554f, 0.559f,
+ -0.744f, 0.0f, 0.347f, 0.553f, 0.554f, -0.737f, 0.0f, 0.348f, 0.552f, 0.548f, -0.729f, 0.0f, 0.351f, 0.551f, 0.544f, -0.723f, 0.0f, 0.355f, 0.551f, 0.546f,
+ -0.716f, 0.0f, 0.36f, 0.55f, 0.546f, -0.709f, 0.0f, 0.366f, 0.55f, 0.547f, -0.702f, 0.0f, 0.372f, 0.549f, 0.547f, -0.696f, 0.0f, 0.379f, 0.549f, 0.547f,
+ -0.689f, 0.0f, 0.386f, 0.549f, 0.548f, -0.683f, 0.0f, 0.394f, 0.549f, 0.548f, -0.676f, 0.0f, 0.403f, 0.549f, 0.549f, -0.67f, 0.0f, 0.413f, 0.549f, 0.548f,
+ -0.664f, 0.0f, 0.422f, 0.549f, 0.549f, -0.658f, 0.0f, 0.432f, 0.55f, 0.549f, -0.652f, 0.0f, 0.441f, 0.551f, 0.548f, -0.646f, 0.0f, 0.451f, 0.552f, 0.548f,
+ -0.639f, 0.0f, 0.46f, 0.554f, 0.548f, -0.632f, 0.0f, 0.469f, 0.556f, 0.549f, -0.624f, 0.0f, 0.478f, 0.559f, 0.549f, -0.616f, 0.0f, 0.487f, 0.563f, 0.549f,
+ -0.609f, 0.0f, 0.497f, 0.567f, 0.549f, -0.6f, 0.0f, 0.507f, 0.572f, 0.558f, -0.592f, 0.0f, 0.518f, 0.577f, 0.574f, -0.584f, 0.0f, 0.528f, 0.582f, 0.587f,
+ -0.575f, 0.0f, 0.538f, 0.586f, 0.592f, -0.566f, 0.0f, 0.548f, 0.591f, 0.595f, -0.556f, 0.0f, 0.557f, 0.594f, 0.597f, -0.546f, 0.0f, 0.567f, 0.597f, 0.598f,
+ -0.536f, 0.0f, 0.577f, 0.6f, 0.6f, -0.525f, 0.0f, 0.586f, 0.602f, 0.603f, -0.514f, 0.0f, 0.596f, 0.604f, 0.605f, -0.503f, 0.0f, 0.606f, 0.605f, 0.606f,
+ -0.492f, 0.0f, 0.615f, 0.606f, 0.607f, -0.482f, 0.0f, 0.624f, 0.607f, 0.607f, -0.471f, 0.0f, 0.632f, 0.608f, 0.607f, -0.462f, 0.0f, 0.64f, 0.609f, 0.607f,
+ -0.453f, 0.0f, 0.647f, 0.61f, 0.61f, -0.444f, 0.0f, 0.654f, 0.612f, 0.611f, -0.435f, 0.0f, 0.66f, 0.614f, 0.613f, -0.427f, 0.0f, 0.666f, 0.616f, 0.615f,
+ -0.418f, 0.0f, 0.672f, 0.617f, 0.618f, -0.409f, 0.0f, 0.677f, 0.619f, 0.621f, -0.399f, 0.0f, 0.683f, 0.621f, 0.622f, -0.389f, 0.0f, 0.69f, 0.623f, 0.623f,
+ -0.379f, 0.0f, 0.696f, 0.624f, 0.624f, -0.368f, 0.0f, 0.702f, 0.626f, 0.626f, -0.356f, 0.0f, 0.708f, 0.628f, 0.628f, -0.345f, 0.0f, 0.713f, 0.63f, 0.63f,
+ -0.333f, 0.0f, 0.719f, 0.633f, 0.631f, -0.32f, 0.0f, 0.724f, 0.637f, 0.632f, -0.307f, 0.0f, 0.729f, 0.641f, 0.64f, -0.294f, 0.0f, 0.732f, 0.646f, 0.644f,
+ -0.281f, 0.0f, 0.736f, 0.65f, 0.655f, -0.268f, 0.0f, 0.739f, 0.654f, 0.657f, -0.255f, 0.0f, 0.742f, 0.657f, 0.658f, -0.243f, 0.0f, 0.745f, 0.659f, 0.661f,
+ -0.23f, 0.0f, 0.747f, 0.662f, 0.663f, -0.217f, 0.0f, 0.75f, 0.664f, 0.664f, -0.203f, 0.0f, 0.753f, 0.666f, 0.666f, -0.19f, 0.0f, 0.755f, 0.667f, 0.668f,
+ -0.177f, 0.0f, 0.757f, 0.669f, 0.67f, -0.163f, 0.0f, 0.76f, 0.671f, 0.671f, -0.15f, 0.0f, 0.762f, 0.673f, 0.672f, -0.136f, 0.0f, 0.764f, 0.674f, 0.674f,
+ -0.122f, 0.0f, 0.767f, 0.676f, 0.676f, -0.108f, 0.0f, 0.769f, 0.677f, 0.678f, -0.093f, 0.0f, 0.771f, 0.678f, 0.68f, -0.079f, 0.0f, 0.773f, 0.678f, 0.68f,
+ -0.064f, 0.0f, 0.774f, 0.679f, 0.679f, -0.049f, 0.0f, 0.775f, 0.68f, 0.68f, -0.033f, 0.0f, 0.775f, 0.68f, 0.68f, -0.018f, 0.0f, 0.776f, 0.68f, 0.68f,
+ -0.002f, 0.0f, 0.776f, 0.681f, 0.68f, 0.013f, 0.0f, 0.777f, 0.681f, 0.681f, 0.029f, 0.0f, 0.777f, 0.682f, 0.681f, 0.045f, 0.0f, 0.777f, 0.682f, 0.681f,
+ 0.061f, 0.0f, 0.777f, 0.683f, 0.683f, 0.077f, 0.0f, 0.776f, 0.683f, 0.683f, 0.094f, 0.0f, 0.775f, 0.684f, 0.684f, 0.11f, 0.0f, 0.774f, 0.685f, 0.683f,
+ 0.126f, 0.0f, 0.773f, 0.685f, 0.685f, 0.142f, 0.0f, 0.771f, 0.687f, 0.685f, 0.158f, 0.0f, 0.769f, 0.688f, 0.685f, 0.174f, 0.0f, 0.767f, 0.69f, 0.686f,
+ 0.19f, 0.0f, 0.765f, 0.691f, 0.692f, 0.206f, 0.0f, 0.762f, 0.693f, 0.694f, 0.222f, 0.0f, 0.757f, 0.695f, 0.696f, 0.238f, 0.0f, 0.752f, 0.697f, 0.697f,
+ 0.254f, 0.0f, 0.747f, 0.699f, 0.698f, 0.27f, 0.0f, 0.742f, 0.7f, 0.7f, 0.286f, 0.0f, 0.736f, 0.702f, 0.702f, 0.302f, 0.0f, 0.73f, 0.704f, 0.704f,
+ 0.318f, 0.0f, 0.724f, 0.705f, 0.71f, 0.335f, 0.0f, 0.717f, 0.707f, 0.71f, 0.351f, 0.0f, 0.709f, 0.708f, 0.71f, 0.367f, 0.0f, 0.701f, 0.709f, 0.711f,
+ 0.382f, 0.0f, 0.692f, 0.71f, 0.713f, 0.397f, 0.0f, 0.683f, 0.711f, 0.713f, 0.41f, 0.0f, 0.675f, 0.712f, 0.713f, 0.422f, 0.0f, 0.666f, 0.712f, 0.714f,
+ 0.434f, 0.0f, 0.658f, 0.713f, 0.714f, 0.446f, 0.0f, 0.649f, 0.714f, 0.714f, 0.458f, 0.0f, 0.641f, 0.714f, 0.714f, 0.47f, 0.0f, 0.632f, 0.715f, 0.715f,
+ 0.483f, 0.0f, 0.622f, 0.715f, 0.716f, 0.496f, 0.0f, 0.611f, 0.715f, 0.716f, 0.51f, 0.0f, 0.6f, 0.716f, 0.717f, 0.523f, 0.0f, 0.588f, 0.716f, 0.716f,
+ 0.536f, 0.0f, 0.576f, 0.717f, 0.717f, 0.55f, 0.0f, 0.563f, 0.717f, 0.717f, 0.564f, 0.0f, 0.549f, 0.717f, 0.717f, 0.577f, 0.0f, 0.536f, 0.718f, 0.717f,
+ 0.59f, 0.0f, 0.522f, 0.718f, 0.717f, 0.603f, 0.0f, 0.508f, 0.718f, 0.718f, 0.615f, 0.0f, 0.496f, 0.718f, 0.718f, 0.625f, 0.0f, 0.484f, 0.718f, 0.718f,
+ 0.635f, 0.0f, 0.473f, 0.719f, 0.718f, 0.645f, 0.0f, 0.461f, 0.719f, 0.718f, 0.654f, 0.0f, 0.45f, 0.719f, 0.718f, 0.662f, 0.0f, 0.44f, 0.719f, 0.719f,
+ 0.67f, 0.0f, 0.431f, 0.719f, 0.719f, 0.676f, 0.0f, 0.422f, 0.719f, 0.719f, 0.682f, 0.0f, 0.414f, 0.719f, 0.719f, 0.687f, 0.0f, 0.407f, 0.719f, 0.719f,
+ 0.692f, 0.0f, 0.4f, 0.719f, 0.719f, 0.697f, 0.0f, 0.394f, 0.719f, 0.719f, 0.701f, 0.0f, 0.388f, 0.718f, 0.718f, 0.705f, 0.0f, 0.383f, 0.718f, 0.717f,
+ 0.708f, 0.0f, 0.378f, 0.718f, 0.717f, 0.711f, 0.0f, 0.374f, 0.717f, 0.717f, 0.714f, 0.0f, 0.37f, 0.717f, 0.717f, 0.717f, 0.0f, 0.366f, 0.717f, 0.717f,
+ 0.719f, 0.0f, 0.362f, 0.718f, 0.717f, 0.722f, 0.0f, 0.359f, 0.718f, 0.718f, 0.724f, 0.0f, 0.356f, 0.718f, 0.717f, 0.727f, 0.0f, 0.352f, 0.717f, 0.719f,
+ 0.73f, 0.0f, 0.349f, 0.717f, 0.719f, 0.734f, 0.0f, 0.347f, 0.715f, 0.719f, 0.737f, 0.0f, 0.344f, 0.714f, 0.714f, 0.742f, 0.0f, 0.341f, 0.713f, 0.709f,
+ 0.746f, 0.0f, 0.339f, 0.714f, 0.707f, 0.751f, 0.0f, 0.336f, 0.718f, 0.704f, 0.757f, 0.0f, 0.334f, 0.724f, 0.705f, 0.763f, 0.0f, 0.332f, 0.732f, 0.705f,
+ 0.769f, -0.0f, 0.329f, 0.742f, 0.704f, 0.775f, -0.0f, 0.328f, 0.753f, 0.713f, 0.782f, -0.0f, 0.327f, 0.764f, 0.804f, 0.789f, -0.0f, 0.327f, 0.774f, 0.813f,
+ 0.797f, -0.0f, 0.327f, 0.783f, 0.815f, 0.805f, -0.0f, 0.328f, 0.791f, 0.815f, 0.814f, -0.0f, 0.329f, 0.797f, 0.816f, 0.823f, -0.0f, 0.331f, 0.802f, 0.815f,
+ 0.832f, 0.0f, 0.335f, 0.806f, 0.816f, 0.841f, 0.0f, 0.341f, 0.809f, 0.816f, 0.851f, 0.0f, 0.346f, 0.811f, 0.816f, 0.861f, 0.0f, 0.351f, 0.812f, 0.816f,
+ 0.871f, 0.0f, 0.356f, 0.813f, 0.815f, 0.881f, 0.0f, 0.361f, 0.814f, 0.816f, 0.893f, 0.0f, 0.365f, 0.814f, 0.816f, 0.906f, 0.0f, 0.368f, 0.814f, 0.817f,
+ 0.922f, 0.0f, 0.372f, 0.813f, 0.816f, 0.939f, 0.0f, 0.375f, 0.812f, 0.817f, 0.957f, 0.0f, 0.377f, 0.811f, 0.817f, 0.977f, 0.0f, 0.379f, 0.81f, 0.815f,
+ 0.995f, 0.0f, 0.38f, 0.808f, 0.813f, 1.012f, 0.0f, 0.379f, 0.806f, 0.807f, 1.028f, 0.0f, 0.377f, 0.803f, 0.803f, 1.042f, 0.0f, 0.374f, 0.8f, 0.801f,
+ 1.054f, 0.0f, 0.371f, 0.797f, 0.8f, 1.065f, 0.0f, 0.366f, 0.794f, 0.8f, 1.076f, 0.0f, 0.361f, 0.791f, 0.792f, 1.085f, 0.0f, 0.355f, 0.788f, 0.781f,
+ 1.093f, 0.0f, 0.348f, 0.785f, 0.781f, 1.1f, 0.0f, 0.34f, 0.783f, 0.78f, 1.106f, 0.0f, 0.33f, 0.782f, 0.78f, 1.113f, 0.0f, 0.321f, 0.781f, 0.778f,
+ 1.117f, 0.0f, 0.31f, 0.78f, 0.777f, 1.122f, -0.0f, 0.299f, 0.779f, 0.777f, 1.125f, -0.0f, 0.286f, 0.778f, 0.776f, 1.129f, -0.0f, 0.274f, 0.778f, 0.777f,
+ 1.131f, -0.0f, 0.262f, 0.778f, 0.777f, 1.132f, -0.0f, 0.249f, 0.777f, 0.777f, 1.134f, -0.0f, 0.237f, 0.777f, 0.778f, 1.134f, -0.0f, 0.225f, 0.777f, 0.778f,
+ 1.135f, -0.0f, 0.213f, 0.776f, 0.777f, 1.134f, -0.0f, 0.201f, 0.776f, 0.776f, 1.134f, -0.0f, 0.189f, 0.776f, 0.775f, 1.132f, -0.0f, 0.177f, 0.775f, 0.776f,
+ 1.13f, -0.0f, 0.164f, 0.775f, 0.775f, 1.129f, -0.0f, 0.152f, 0.774f, 0.774f, 1.126f, -0.0f, 0.141f, 0.774f, 0.773f, 1.122f, -0.0f, 0.13f, 0.774f, 0.772f,
+ 1.118f, -0.0f, 0.118f, 0.773f, 0.772f, 1.113f, -0.0f, 0.108f, 0.773f, 0.773f, 1.107f, -0.0f, 0.097f, 0.773f, 0.774f, 1.102f, -0.0f, 0.087f, 0.772f, 0.773f,
+ 1.095f, -0.0f, 0.077f, 0.772f, 0.773f, 1.088f, -0.0f, 0.067f, 0.771f, 0.772f, 1.081f, -0.0f, 0.057f, 0.771f, 0.773f, 1.073f, -0.0f, 0.048f, 0.77f, 0.772f,
+ 1.066f, -0.0f, 0.038f, 0.769f, 0.767f, 1.058f, -0.0f, 0.029f, 0.768f, 0.766f, 1.05f, -0.0f, 0.019f, 0.768f, 0.765f, 1.041f, -0.0f, 0.011f, 0.767f, 0.765f,
+ 1.032f, -0.0f, 0.003f, 0.767f, 0.766f, 1.023f, -0.0f, -0.004f, 0.766f, 0.765f, 1.013f, -0.0f, -0.011f, 0.766f, 0.765f, 1.003f, -0.0f, -0.019f, 0.765f, 0.766f,
+ 0.993f, -0.0f, -0.026f, 0.765f, 0.765f, 0.983f, -0.0f, -0.034f, 0.764f, 0.765f, 0.972f, -0.0f, -0.041f, 0.762f, 0.765f, 0.962f, -0.0f, -0.048f, 0.761f, 0.765f,
+ 0.951f, -0.0f, -0.055f, 0.759f, 0.762f, 0.94f, -0.0f, -0.063f, 0.756f, 0.761f, 0.929f, -0.0f, -0.07f, 0.754f, 0.755f, 0.918f, -0.0f, -0.078f, 0.751f, 0.751f,
+ 0.907f, -0.0f, -0.085f, 0.748f, 0.747f, 0.896f, -0.0f, -0.092f, 0.745f, 0.744f, 0.884f, -0.0f, -0.099f, 0.742f, 0.742f, 0.873f, -0.0f, -0.105f, 0.739f, 0.738f,
+ 0.861f, -0.0f, -0.11f, 0.736f, 0.737f, 0.849f, 0.0f, -0.115f, 0.733f, 0.731f, 0.836f, 0.0f, -0.119f, 0.73f, 0.73f, 0.823f, 0.0f, -0.124f, 0.728f, 0.727f,
+ 0.81f, 0.0f, -0.128f, 0.725f, 0.725f, 0.796f, 0.0f, -0.132f, 0.723f, 0.723f, 0.783f, 0.0f, -0.136f, 0.72f, 0.719f, 0.77f, 0.0f, -0.141f, 0.718f, 0.717f,
+ 0.756f, 0.0f, -0.145f, 0.715f, 0.712f, 0.742f, 0.0f, -0.15f, 0.713f, 0.708f, 0.728f, 0.0f, -0.152f, 0.711f, 0.707f, 0.713f, 0.0f, -0.155f, 0.709f, 0.706f,
+ 0.699f, 0.0f, -0.156f, 0.706f, 0.706f, 0.684f, 0.0f, -0.158f, 0.704f, 0.705f, 0.67f, 0.0f, -0.159f, 0.702f, 0.705f, 0.656f, 0.0f, -0.16f, 0.7f, 0.704f,
+ 0.642f, 0.0f, -0.161f, 0.698f, 0.702f, 0.628f, 0.0f, -0.161f, 0.695f, 0.698f, 0.614f, 0.0f, -0.162f, 0.693f, 0.695f, 0.6f, 0.0f, -0.162f, 0.691f, 0.691f,
+ 0.587f, 0.0f, -0.162f, 0.688f, 0.686f, 0.574f, 0.0f, -0.162f, 0.686f, 0.685f, 0.561f, 0.0f, -0.161f, 0.683f, 0.683f, 0.548f, 0.0f, -0.161f, 0.681f, 0.683f,
+ 0.535f, 0.0f, -0.161f, 0.678f, 0.678f, 0.523f, 0.0f, -0.16f, 0.676f, 0.676f, 0.512f, 0.0f, -0.16f, 0.673f, 0.674f, 0.501f, 0.0f, -0.16f, 0.671f, 0.67f,
+ 0.49f, 0.0f, -0.16f, 0.668f, 0.668f, 0.48f, 0.0f, -0.161f, 0.666f, 0.663f, 0.469f, 0.0f, -0.162f, 0.665f, 0.66f, 0.458f, 0.0f, -0.165f, 0.663f, 0.66f,
+ 0.447f, 0.0f, -0.167f, 0.662f, 0.659f, 0.437f, 0.0f, -0.171f, 0.661f, 0.659f, 0.426f, 0.0f, -0.175f, 0.66f, 0.659f, 0.415f, 0.0f, -0.18f, 0.66f, 0.659f,
+ 0.404f, 0.0f, -0.185f, 0.659f, 0.659f, 0.393f, 0.0f, -0.191f, 0.659f, 0.657f, 0.383f, 0.0f, -0.196f, 0.659f, 0.657f, 0.373f, 0.0f, -0.202f, 0.658f, 0.659f,
+ 0.363f, -0.0f, -0.208f, 0.658f, 0.658f, 0.353f, -0.0f, -0.215f, 0.658f, 0.659f, 0.344f, -0.0f, -0.223f, 0.658f, 0.659f, 0.336f, -0.0f, -0.23f, 0.658f, 0.659f,
+ 0.327f, -0.0f, -0.238f, 0.658f, 0.658f, 0.319f, -0.0f, -0.245f, 0.657f, 0.657f, 0.312f, -0.0f, -0.253f, 0.657f, 0.656f, 0.305f, -0.0f, -0.261f, 0.656f, 0.658f,
+ 0.299f, -0.0f, -0.269f, 0.655f, 0.658f, 0.293f, 0.0f, -0.278f, 0.653f, 0.657f, 0.288f, 0.0f, -0.287f, 0.65f, 0.657f, 0.283f, 0.0f, -0.295f, 0.646f, 0.656f,
+ 0.279f, 0.0f, -0.304f, 0.642f, 0.655f, 0.275f, 0.0f, -0.313f, 0.637f, 0.642f, 0.271f, 0.0f, -0.322f, 0.633f, 0.637f, 0.268f, 0.0f, -0.331f, 0.628f, 0.609f,
+ 0.265f, 0.0f, -0.341f, 0.624f, 0.607f, 0.263f, 0.0f, -0.35f, 0.62f, 0.608f, 0.261f, 0.0f, -0.359f, 0.617f, 0.608f, 0.259f, 0.0f, -0.369f, 0.614f, 0.607f,
+ 0.258f, 0.0f, -0.379f, 0.612f, 0.606f, 0.257f, 0.0f, -0.389f, 0.61f, 0.606f, 0.258f, 0.0f, -0.399f, 0.609f, 0.605f, 0.258f, 0.0f, -0.41f, 0.608f, 0.604f,
+ 0.26f, 0.0f, -0.421f, 0.608f, 0.606f, 0.263f, 0.0f, -0.431f, 0.607f, 0.606f, 0.266f, 0.0f, -0.441f, 0.607f, 0.606f, 0.27f, 0.0f, -0.452f, 0.606f, 0.607f,
+ 0.274f, 0.0f, -0.463f, 0.606f, 0.607f, 0.279f, 0.0f, -0.475f, 0.605f, 0.607f, 0.283f, 0.0f, -0.487f, 0.604f, 0.607f, 0.288f, 0.0f, -0.498f, 0.603f, 0.607f,
+ 0.293f, 0.0f, -0.511f, 0.601f, 0.607f, 0.297f, 0.0f, -0.523f, 0.598f, 0.606f, 0.301f, 0.0f, -0.536f, 0.595f, 0.605f, 0.305f, 0.0f, -0.549f, 0.591f, 0.602f,
+ 0.309f, 0.0f, -0.562f, 0.588f, 0.597f, 0.312f, 0.0f, -0.576f, 0.583f, 0.585f, 0.315f, 0.0f, -0.59f, 0.579f, 0.577f, 0.318f, 0.0f, -0.604f, 0.574f, 0.576f,
+ 0.321f, 0.0f, -0.618f, 0.569f, 0.57f, 0.323f, 0.0f, -0.633f, 0.564f, 0.564f, 0.326f, 0.0f, -0.647f, 0.559f, 0.554f, 0.328f, 0.0f, -0.663f, 0.555f, 0.549f,
+ 0.33f, 0.0f, -0.678f, 0.551f, 0.546f, 0.332f, 0.0f, -0.693f, 0.547f, 0.543f, 0.334f, 0.0f, -0.709f, 0.544f, 0.543f, 0.336f, 0.0f, -0.726f, 0.541f, 0.541f,
+ 0.338f, 0.0f, -0.742f, 0.538f, 0.54f, 0.338f, 0.0f, -0.758f, 0.536f, 0.538f, 0.338f, 0.0f, -0.773f, 0.534f, 0.53f, 0.337f, 0.0f, -0.787f, 0.532f, 0.528f,
+ 0.337f, 0.0f, -0.801f, 0.53f, 0.528f, 0.336f, 0.0f, -0.814f, 0.529f, 0.528f, 0.334f, 0.0f, -0.827f, 0.527f, 0.528f, 0.333f, 0.0f, -0.84f, 0.525f, 0.529f,
+ 0.331f, 0.0f, -0.853f, 0.523f, 0.529f, 0.328f, 0.0f, -0.866f, 0.521f, 0.528f, 0.324f, 0.0f, -0.877f, 0.519f, 0.516f, 0.32f, 0.0f, -0.889f, 0.516f, 0.515f,
+ 0.315f, 0.0f, -0.9f, 0.513f, 0.515f, 0.31f, 0.0f, -0.91f, 0.51f, 0.514f, 0.304f, 0.0f, -0.921f, 0.507f, 0.513f, 0.297f, 0.0f, -0.931f, 0.505f, 0.507f,
+ 0.289f, 0.0f, -0.94f, 0.502f, 0.498f, 0.281f, 0.0f, -0.948f, 0.499f, 0.494f, 0.272f, 0.0f, -0.956f, 0.497f, 0.491f, 0.262f, 0.0f, -0.963f, 0.495f, 0.49f,
+ 0.253f, 0.0f, -0.969f, 0.494f, 0.491f, 0.242f, 0.0f, -0.975f, 0.493f, 0.491f, 0.231f, 0.0f, -0.98f, 0.492f, 0.49f, 0.22f, 0.0f, -0.986f, 0.491f, 0.489f,
+ 0.208f, 0.0f, -0.99f, 0.491f, 0.49f, 0.195f, 0.0f, -0.994f, 0.491f, 0.491f, 0.181f, 0.0f, -0.998f, 0.491f, 0.491f, 0.168f, 0.0f, -1.001f, 0.491f, 0.492f,
+ 0.154f, 0.0f, -1.005f, 0.491f, 0.492f, 0.141f, 0.0f, -1.008f, 0.492f, 0.492f, 0.126f, 0.0f, -1.01f, 0.492f, 0.492f, 0.112f, 0.0f, -1.011f, 0.492f, 0.492f,
+ 0.097f, 0.0f, -1.013f, 0.492f, 0.492f, 0.081f, 0.0f, -1.013f, 0.492f, 0.492f, 0.066f, 0.0f, -1.014f, 0.493f, 0.493f, 0.05f, 0.0f, -1.014f, 0.493f, 0.494f,
+ 0.035f, 0.0f, -1.014f, 0.493f, 0.494f, 0.019f, 0.0f, -1.013f, 0.493f, 0.494f, 0.004f, 0.0f, -1.012f, 0.493f, 0.494f, -0.011f, 0.0f, -1.011f, 0.493f, 0.493f,
+ -0.026f, 0.0f, -1.01f, 0.492f, 0.493f, -0.041f, 0.0f, -1.008f, 0.492f, 0.492f, -0.056f, 0.0f, -1.006f, 0.492f, 0.492f, -0.07f, 0.0f, -1.004f, 0.491f, 0.492f,
+ -0.084f, 0.0f, -1.001f, 0.491f, 0.492f, -0.098f, 0.0f, -0.999f, 0.491f, 0.491f, -0.112f, 0.0f, -0.995f, 0.491f, 0.49f, -0.125f, 0.0f, -0.992f, 0.49f, 0.49f,
+ -0.138f, 0.0f, -0.987f, 0.49f, 0.491f, -0.15f, 0.0f, -0.983f, 0.49f, 0.49f, -0.162f, 0.0f, -0.978f, 0.49f, 0.49f, -0.174f, 0.0f, -0.973f, 0.489f, 0.489f,
+ -0.185f, 0.0f, -0.967f, 0.489f, 0.488f, -0.196f, 0.0f, -0.961f, 0.489f, 0.489f, -0.207f, 0.0f, -0.955f, 0.489f, 0.489f, -0.218f, 0.0f, -0.949f, 0.489f, 0.49f,
+ -0.229f, 0.0f, -0.943f, 0.489f, 0.489f, -0.24f, 0.0f, -0.936f, 0.489f, 0.489f, -0.25f, 0.0f, -0.929f, 0.489f, 0.489f, -0.261f, 0.0f, -0.922f, 0.489f, 0.489f,
+ -0.271f, 0.0f, -0.914f, 0.489f, 0.49f, -0.28f, 0.0f, -0.907f, 0.49f, 0.49f, -0.289f, 0.0f, -0.898f, 0.49f, 0.489f, -0.298f, 0.0f, -0.89f, 0.49f, 0.489f,
+ -0.306f, 0.0f, -0.882f, 0.49f, 0.49f, -0.314f, 0.0f, -0.875f, 0.491f, 0.489f, -0.322f, 0.0f, -0.866f, 0.492f, 0.489f, -0.328f, 0.0f, -0.857f, 0.492f, 0.489f,
+ -0.333f, 0.0f, -0.847f, 0.493f, 0.49f, -0.336f, 0.0f, -0.836f, 0.494f, 0.488f, -0.338f, 0.0f, -0.824f, 0.496f, 0.49f, -0.338f, 0.0f, -0.811f, 0.497f, 0.49f,
+ -0.338f, 0.0f, -0.798f, 0.499f, 0.491f, -0.337f, 0.0f, -0.785f, 0.501f, 0.497f, -0.337f, 0.0f, -0.772f, 0.503f, 0.5f, -0.337f, 0.0f, -0.759f, 0.505f, 0.504f,
+ -0.336f, -0.0f, -0.746f, 0.507f, 0.505f, -0.336f, -0.0f, -0.733f, 0.51f, 0.51f, -0.335f, -0.0f, -0.719f, 0.512f, 0.513f, -0.334f, -0.0f, -0.706f, 0.515f, 0.515f,
+ -0.333f, -0.0f, -0.692f, 0.518f, 0.516f, -0.332f, -0.0f, -0.678f, 0.52f, 0.522f, -0.331f, -0.0f, -0.665f, 0.523f, 0.523f, -0.329f, -0.0f, -0.651f, 0.525f, 0.528f,
+ -0.327f, -0.0f, -0.637f, 0.528f, 0.53f, -0.325f, -0.0f, -0.624f, 0.53f, 0.532f, -0.322f, -0.0f, -0.61f, 0.532f, 0.534f, -0.319f, -0.0f, -0.597f, 0.535f, 0.535f,
+ -0.316f, -0.0f, -0.584f, 0.537f, 0.538f, -0.313f, -0.0f, -0.57f, 0.539f, 0.54f, -0.31f, -0.0f, -0.557f, 0.541f, 0.542f, -0.307f, -0.0f, -0.544f, 0.542f, 0.545f,
+ -0.303f, -0.0f, -0.531f, 0.544f, 0.546f, -0.3f, -0.0f, -0.519f, 0.546f, 0.549f, -0.298f, -0.0f, -0.506f, 0.547f, 0.549f, -0.295f, -0.0f, -0.494f, 0.548f, 0.549f,
+ -0.292f, -0.0f, -0.482f, 0.549f, 0.55f, -0.29f, -0.0f, -0.47f, 0.55f, 0.552f, -0.287f, -0.0f, -0.459f, 0.551f, 0.552f, -0.285f, -0.0f, -0.447f, 0.551f, 0.552f,
+ -0.284f, -0.0f, -0.436f, 0.552f, 0.552f, -0.282f, -0.0f, -0.425f, 0.552f, 0.553f, -0.281f, -0.0f, -0.413f, 0.553f, 0.553f, -0.28f, -0.0f, -0.402f, 0.553f, 0.553f,
+ -0.28f, -0.0f, -0.392f, 0.553f, 0.553f, -0.281f, -0.0f, -0.381f, 0.554f, 0.553f, -0.283f, -0.0f, -0.369f, 0.554f, 0.554f, -0.286f, -0.0f, -0.359f, 0.554f, 0.554f,
+ -0.289f, -0.0f, -0.348f, 0.555f, 0.554f, -0.294f, -0.0f, -0.337f, 0.555f, 0.555f, -0.299f, -0.0f, -0.327f, 0.555f, 0.554f, -0.305f, -0.0f, -0.317f, 0.556f, 0.555f,
+ -0.312f, -0.0f, -0.307f, 0.556f, 0.555f, -0.319f, -0.0f, -0.297f, 0.556f, 0.557f, -0.326f, 0.0f, -0.287f, 0.557f, 0.558f, -0.334f, 0.0f, -0.278f, 0.557f, 0.557f,
+ -0.341f, 0.0f, -0.268f, 0.557f, 0.558f, -0.349f, 0.0f, -0.259f, 0.558f, 0.558f, -0.359f, 0.0f, -0.251f, 0.558f, 0.558f, -0.368f, 0.0f, -0.243f, 0.558f, 0.558f,
+ -0.378f, 0.0f, -0.235f, 0.558f, 0.559f, -0.388f, 0.0f, -0.228f, 0.558f, 0.558f, -0.398f, 0.0f, -0.221f, 0.559f, 0.559f, -0.408f, 0.0f, -0.214f, 0.559f, 0.559f,
+ -0.418f, 0.0f, -0.208f, 0.559f, 0.559f, -0.427f, 0.0f, -0.202f, 0.559f, 0.558f, -0.436f, 0.0f, -0.196f, 0.559f, 0.559f, -0.445f, 0.0f, -0.191f, 0.559f, 0.559f,
+ -0.453f, 0.0f, -0.187f, 0.558f, 0.559f, -0.462f, 0.0f, -0.183f, 0.558f, 0.558f, -0.469f, 0.0f, -0.18f, 0.558f, 0.558f, -0.477f, 0.0f, -0.176f, 0.558f, 0.558f,
+ -0.484f, 0.0f, -0.174f, 0.557f, 0.558f, -0.493f, 0.0f, -0.17f, 0.555f, 0.559f,
+};
+
+
+static const float data1[136 * GP_PRIM_DATABUF_SIZE] = {
+ -0.369f, 0.0f, -0.048f, 0.065f, 0.065f, -0.378f, 0.0f, -0.046f, 0.239f, 0.293f, -0.383f, 0.0f, -0.044f, 0.316f, 0.339f, -0.39f, 0.0f, -0.041f, 0.348f, 0.355f,
+ -0.398f, 0.0f, -0.038f, 0.364f, 0.368f, -0.405f, 0.0f, -0.035f, 0.373f, 0.374f, -0.413f, 0.0f, -0.031f, 0.381f, 0.381f, -0.421f, 0.0f, -0.026f, 0.388f, 0.391f,
+ -0.429f, 0.0f, -0.02f, 0.392f, 0.394f, -0.437f, 0.0f, -0.014f, 0.395f, 0.396f, -0.445f, 0.0f, -0.008f, 0.397f, 0.397f, -0.453f, 0.0f, -0.001f, 0.399f, 0.4f,
+ -0.461f, 0.0f, 0.007f, 0.401f, 0.401f, -0.468f, -0.0f, 0.016f, 0.404f, 0.404f, -0.474f, 0.0f, 0.023f, 0.406f, 0.407f, -0.479f, 0.0f, 0.03f, 0.409f, 0.409f,
+ -0.485f, 0.0f, 0.039f, 0.412f, 0.412f, -0.49f, 0.0f, 0.048f, 0.415f, 0.415f, -0.495f, 0.0f, 0.057f, 0.417f, 0.417f, -0.499f, 0.0f, 0.068f, 0.42f, 0.421f,
+ -0.503f, 0.0f, 0.079f, 0.421f, 0.421f, -0.507f, -0.0f, 0.091f, 0.423f, 0.423f, -0.51f, -0.0f, 0.102f, 0.424f, 0.424f, -0.513f, -0.0f, 0.112f, 0.424f, 0.425f,
+ -0.515f, -0.0f, 0.123f, 0.425f, 0.425f, -0.517f, -0.0f, 0.135f, 0.425f, 0.425f, -0.518f, -0.0f, 0.146f, 0.426f, 0.425f, -0.519f, -0.0f, 0.158f, 0.426f, 0.425f,
+ -0.52f, -0.0f, 0.169f, 0.426f, 0.426f, -0.52f, -0.0f, 0.181f, 0.427f, 0.427f, -0.519f, -0.0f, 0.192f, 0.427f, 0.427f, -0.518f, -0.0f, 0.203f, 0.427f, 0.427f,
+ -0.517f, -0.0f, 0.213f, 0.427f, 0.428f, -0.515f, -0.0f, 0.222f, 0.428f, 0.427f, -0.513f, -0.0f, 0.232f, 0.428f, 0.427f, -0.51f, -0.0f, 0.241f, 0.429f, 0.427f,
+ -0.508f, -0.0f, 0.25f, 0.43f, 0.428f, -0.505f, -0.0f, 0.259f, 0.431f, 0.431f, -0.501f, -0.0f, 0.267f, 0.431f, 0.432f, -0.497f, -0.0f, 0.276f, 0.432f, 0.433f,
+ -0.493f, -0.0f, 0.284f, 0.433f, 0.433f, -0.488f, -0.0f, 0.293f, 0.434f, 0.434f, -0.484f, -0.0f, 0.301f, 0.434f, 0.435f, -0.479f, -0.0f, 0.308f, 0.435f, 0.436f,
+ -0.474f, -0.0f, 0.316f, 0.435f, 0.435f, -0.468f, -0.0f, 0.322f, 0.436f, 0.436f, -0.463f, -0.0f, 0.329f, 0.436f, 0.436f, -0.457f, -0.0f, 0.335f, 0.436f, 0.436f,
+ -0.451f, -0.0f, 0.341f, 0.437f, 0.436f, -0.445f, -0.0f, 0.347f, 0.438f, 0.437f, -0.438f, -0.0f, 0.352f, 0.44f, 0.437f, -0.432f, -0.0f, 0.357f, 0.442f, 0.441f,
+ -0.426f, 0.0f, 0.362f, 0.444f, 0.446f, -0.419f, 0.0f, 0.366f, 0.445f, 0.447f, -0.413f, 0.0f, 0.369f, 0.446f, 0.447f, -0.407f, 0.0f, 0.373f, 0.446f, 0.447f,
+ -0.401f, 0.0f, 0.376f, 0.447f, 0.447f, -0.395f, 0.0f, 0.378f, 0.447f, 0.448f, -0.388f, 0.0f, 0.381f, 0.447f, 0.448f, -0.382f, 0.0f, 0.383f, 0.448f, 0.448f,
+ -0.375f, 0.0f, 0.384f, 0.448f, 0.448f, -0.369f, 0.0f, 0.386f, 0.448f, 0.448f, -0.362f, 0.0f, 0.387f, 0.448f, 0.448f, -0.355f, 0.0f, 0.388f, 0.448f, 0.448f,
+ -0.348f, 0.0f, 0.388f, 0.448f, 0.448f, -0.341f, 0.0f, 0.387f, 0.448f, 0.449f, -0.334f, 0.0f, 0.387f, 0.448f, 0.448f, -0.327f, 0.0f, 0.386f, 0.448f, 0.449f,
+ -0.32f, 0.0f, 0.384f, 0.449f, 0.449f, -0.313f, 0.0f, 0.382f, 0.449f, 0.449f, -0.307f, 0.0f, 0.38f, 0.449f, 0.449f, -0.3f, 0.0f, 0.377f, 0.449f, 0.45f,
+ -0.294f, 0.0f, 0.375f, 0.45f, 0.45f, -0.288f, -0.0f, 0.372f, 0.45f, 0.45f, -0.282f, -0.0f, 0.368f, 0.45f, 0.451f, -0.276f, -0.0f, 0.365f, 0.45f, 0.451f,
+ -0.27f, -0.0f, 0.361f, 0.45f, 0.451f, -0.264f, -0.0f, 0.357f, 0.45f, 0.451f, -0.258f, -0.0f, 0.352f, 0.45f, 0.45f, -0.251f, -0.0f, 0.347f, 0.45f, 0.451f,
+ -0.245f, -0.0f, 0.341f, 0.451f, 0.451f, -0.24f, -0.0f, 0.335f, 0.451f, 0.451f, -0.234f, -0.0f, 0.329f, 0.451f, 0.451f, -0.228f, -0.0f, 0.323f, 0.452f, 0.452f,
+ -0.223f, -0.0f, 0.316f, 0.452f, 0.453f, -0.218f, -0.0f, 0.309f, 0.452f, 0.453f, -0.213f, -0.0f, 0.301f, 0.453f, 0.453f, -0.208f, -0.0f, 0.294f, 0.453f, 0.453f,
+ -0.204f, -0.0f, 0.286f, 0.453f, 0.453f, -0.2f, -0.0f, 0.277f, 0.453f, 0.454f, -0.196f, -0.0f, 0.269f, 0.453f, 0.454f, -0.192f, -0.0f, 0.26f, 0.454f, 0.454f,
+ -0.189f, -0.0f, 0.25f, 0.454f, 0.454f, -0.186f, -0.0f, 0.241f, 0.454f, 0.455f, -0.183f, -0.0f, 0.231f, 0.454f, 0.455f, -0.181f, -0.0f, 0.221f, 0.454f, 0.455f,
+ -0.179f, -0.0f, 0.209f, 0.455f, 0.455f, -0.177f, -0.0f, 0.197f, 0.455f, 0.455f, -0.176f, -0.0f, 0.184f, 0.455f, 0.455f, -0.176f, -0.0f, 0.171f, 0.455f, 0.456f,
+ -0.176f, -0.0f, 0.158f, 0.455f, 0.456f, -0.177f, -0.0f, 0.145f, 0.455f, 0.456f, -0.178f, -0.0f, 0.132f, 0.455f, 0.456f, -0.18f, -0.0f, 0.12f, 0.456f, 0.456f,
+ -0.182f, -0.0f, 0.108f, 0.456f, 0.456f, -0.185f, -0.0f, 0.097f, 0.456f, 0.456f, -0.188f, -0.0f, 0.086f, 0.456f, 0.457f, -0.191f, -0.0f, 0.076f, 0.456f, 0.457f,
+ -0.194f, -0.0f, 0.067f, 0.457f, 0.457f, -0.198f, -0.0f, 0.058f, 0.457f, 0.457f, -0.202f, -0.0f, 0.05f, 0.457f, 0.457f, -0.206f, -0.0f, 0.042f, 0.457f, 0.457f,
+ -0.21f, -0.0f, 0.034f, 0.458f, 0.457f, -0.215f, -0.0f, 0.027f, 0.458f, 0.457f, -0.22f, -0.0f, 0.02f, 0.458f, 0.458f, -0.225f, -0.0f, 0.014f, 0.458f, 0.458f,
+ -0.23f, -0.0f, 0.007f, 0.458f, 0.458f, -0.235f, -0.0f, 0.002f, 0.459f, 0.458f, -0.24f, -0.0f, -0.004f, 0.459f, 0.458f, -0.246f, -0.0f, -0.009f, 0.46f, 0.459f,
+ -0.251f, 0.0f, -0.013f, 0.464f, 0.463f, -0.257f, 0.0f, -0.018f, 0.467f, 0.468f, -0.262f, 0.0f, -0.022f, 0.469f, 0.469f, -0.268f, 0.0f, -0.026f, 0.471f, 0.47f,
+ -0.274f, 0.0f, -0.029f, 0.477f, 0.478f, -0.28f, 0.0f, -0.033f, 0.478f, 0.478f, -0.286f, 0.0f, -0.036f, 0.478f, 0.478f, -0.292f, 0.0f, -0.038f, 0.479f, 0.479f,
+ -0.298f, 0.0f, -0.041f, 0.48f, 0.48f, -0.305f, 0.0f, -0.043f, 0.48f, 0.48f, -0.311f, 0.0f, -0.045f, 0.482f, 0.482f, -0.318f, 0.0f, -0.047f, 0.482f, 0.482f,
+ -0.324f, 0.0f, -0.048f, 0.482f, 0.482f, -0.331f, 0.0f, -0.049f, 0.48f, 0.482f, -0.336f, 0.0f, -0.05f, 0.457f, 0.485f, -0.344f, 0.0f, -0.05f, 0.32f, 0.32f,
+};
+
+static const float data2[2 * GP_PRIM_DATABUF_SIZE] = {
+ -0.512f, 0.0f, -0.168f, 0.545f, 0.557f, -0.521f, 0.0f, -0.167f, 0.535f, 0.558f,
+};
+
+static const float data3[1 * GP_PRIM_DATABUF_SIZE] = {
+ -1.014f, 0.0f, 0.186f, 0.0f, 0.003f,
+};
+
+static const float data4[1 * GP_PRIM_DATABUF_SIZE] = {
+ -1.014f, 0.0f, 0.186f, 0.02f, 0.02f,
+};
+
+static const float data5[48 * GP_PRIM_DATABUF_SIZE] = {
+ -1.014f, 0.0f, 0.187f, 0.066f, 0.066f, -1.013f, 0.0f, 0.2f, 0.222f, 0.356f, -1.01f, 0.0f, 0.208f, 0.295f, 0.404f, -1.006f, 0.0f, 0.218f, 0.354f, 0.431f,
+ -1.001f, 0.0f, 0.226f, 0.392f, 0.445f, -0.994f, 0.0f, 0.233f, 0.418f, 0.453f, -0.987f, 0.0f, 0.238f, 0.437f, 0.457f, -0.979f, 0.0f, 0.242f, 0.45f, 0.47f,
+ -0.97f, 0.0f, 0.245f, 0.459f, 0.473f, -0.96f, -0.0f, 0.246f, 0.465f, 0.474f, -0.951f, -0.0f, 0.245f, 0.469f, 0.475f, -0.942f, 0.0f, 0.242f, 0.471f, 0.473f,
+ -0.932f, 0.0f, 0.239f, 0.472f, 0.474f, -0.924f, 0.0f, 0.234f, 0.471f, 0.474f, -0.915f, 0.0f, 0.228f, 0.469f, 0.474f, -0.906f, 0.0f, 0.22f, 0.464f, 0.47f,
+ -0.898f, 0.0f, 0.212f, 0.458f, 0.46f, -0.89f, 0.0f, 0.203f, 0.451f, 0.453f, -0.882f, 0.0f, 0.193f, 0.443f, 0.443f, -0.875f, 0.0f, 0.182f, 0.435f, 0.437f,
+ -0.869f, 0.0f, 0.172f, 0.426f, 0.428f, -0.863f, 0.0f, 0.161f, 0.417f, 0.415f, -0.858f, 0.0f, 0.148f, 0.409f, 0.41f, -0.854f, 0.0f, 0.137f, 0.399f, 0.399f,
+ -0.85f, 0.0f, 0.126f, 0.39f, 0.392f, -0.847f, 0.0f, 0.116f, 0.379f, 0.386f, -0.846f, 0.0f, 0.109f, 0.369f, 0.371f, -0.846f, 0.0f, 0.104f, 0.361f, 0.357f,
+ -0.847f, 0.0f, 0.101f, 0.355f, 0.339f, -0.849f, 0.0f, 0.101f, 0.353f, 0.334f, -0.853f, 0.0f, 0.103f, 0.354f, 0.345f, -0.859f, 0.0f, 0.108f, 0.357f, 0.35f,
+ -0.865f, 0.0f, 0.116f, 0.363f, 0.365f, -0.873f, 0.0f, 0.126f, 0.369f, 0.375f, -0.881f, 0.0f, 0.137f, 0.375f, 0.379f, -0.89f, 0.0f, 0.149f, 0.381f, 0.38f,
+ -0.899f, 0.0f, 0.159f, 0.387f, 0.385f, -0.908f, 0.0f, 0.168f, 0.394f, 0.394f, -0.919f, 0.0f, 0.177f, 0.401f, 0.398f, -0.932f, 0.0f, 0.184f, 0.409f, 0.404f,
+ -0.945f, 0.0f, 0.191f, 0.418f, 0.415f, -0.958f, 0.0f, 0.195f, 0.427f, 0.431f, -0.969f, 0.0f, 0.197f, 0.434f, 0.443f, -0.979f, 0.0f, 0.197f, 0.436f, 0.445f,
+ -0.987f, 0.0f, 0.195f, 0.428f, 0.463f, -0.995f, 0.0f, 0.192f, 0.398f, 0.46f, -1.001f, 0.0f, 0.189f, 0.345f, 0.465f, -1.01f, 0.0f, 0.183f, 0.236f, 0.236f,
+};
+
+static const float data6[47 * GP_PRIM_DATABUF_SIZE] = {
+ 0.022f, 0.0f, -0.353f, 0.125f, 0.125f, 0.012f, 0.0f, -0.352f, 0.175f, 0.288f, 0.004f, 0.0f, -0.352f, 0.206f, 0.313f, -0.006f, 0.0f, -0.352f, 0.241f, 0.323f,
+ -0.017f, 0.0f, -0.352f, 0.27f, 0.33f, -0.029f, 0.0f, -0.351f, 0.295f, 0.334f, -0.041f, 0.0f, -0.349f, 0.314f, 0.337f, -0.052f, 0.0f, -0.344f, 0.327f, 0.341f,
+ -0.063f, 0.0f, -0.337f, 0.336f, 0.344f, -0.072f, 0.0f, -0.329f, 0.341f, 0.345f, -0.081f, 0.0f, -0.32f, 0.345f, 0.345f, -0.088f, 0.0f, -0.311f, 0.348f, 0.345f,
+ -0.093f, 0.0f, -0.303f, 0.352f, 0.347f, -0.098f, 0.0f, -0.295f, 0.356f, 0.352f, -0.101f, 0.0f, -0.287f, 0.361f, 0.357f, -0.102f, 0.0f, -0.279f, 0.367f, 0.364f,
+ -0.103f, 0.0f, -0.271f, 0.373f, 0.378f, -0.102f, 0.0f, -0.263f, 0.379f, 0.382f, -0.1f, 0.0f, -0.255f, 0.383f, 0.389f, -0.098f, 0.0f, -0.247f, 0.387f, 0.391f,
+ -0.094f, 0.0f, -0.24f, 0.389f, 0.393f, -0.09f, 0.0f, -0.233f, 0.391f, 0.393f, -0.086f, 0.0f, -0.227f, 0.392f, 0.393f, -0.082f, 0.0f, -0.222f, 0.393f, 0.393f,
+ -0.078f, 0.0f, -0.219f, 0.394f, 0.393f, -0.075f, 0.0f, -0.217f, 0.397f, 0.393f, -0.072f, 0.0f, -0.217f, 0.4f, 0.393f, -0.07f, 0.0f, -0.219f, 0.402f, 0.408f,
+ -0.069f, 0.0f, -0.222f, 0.404f, 0.408f, -0.069f, 0.0f, -0.228f, 0.406f, 0.409f, -0.069f, 0.0f, -0.234f, 0.407f, 0.409f, -0.07f, 0.0f, -0.241f, 0.408f, 0.409f,
+ -0.07f, 0.0f, -0.248f, 0.408f, 0.409f, -0.07f, 0.0f, -0.256f, 0.409f, 0.409f, -0.07f, 0.0f, -0.263f, 0.409f, 0.41f, -0.069f, 0.0f, -0.271f, 0.41f, 0.411f,
+ -0.068f, 0.0f, -0.279f, 0.41f, 0.411f, -0.065f, 0.0f, -0.287f, 0.41f, 0.411f, -0.062f, 0.0f, -0.295f, 0.409f, 0.411f, -0.057f, 0.0f, -0.303f, 0.409f, 0.409f,
+ -0.052f, 0.0f, -0.31f, 0.408f, 0.409f, -0.047f, 0.0f, -0.318f, 0.407f, 0.408f, -0.041f, 0.0f, -0.324f, 0.406f, 0.407f, -0.035f, 0.0f, -0.329f, 0.403f, 0.407f,
+ -0.027f, 0.0f, -0.333f, 0.4f, 0.408f, -0.021f, 0.0f, -0.336f, 0.398f, 0.403f, -0.012f, 0.0f, -0.339f, 0.393f, 0.393f,
+};
+
+static const float data7[162 * GP_PRIM_DATABUF_SIZE] = {
+ -0.291f, 0.0f, -0.34f, 0.093f, 0.093f, -0.289f, -0.0f, -0.35f, 0.149f, 0.176f, -0.287f, -0.0f, -0.357f, 0.182f, 0.242f, -0.284f, -0.0f, -0.365f, 0.215f, 0.257f,
+ -0.281f, -0.0f, -0.374f, 0.242f, 0.266f, -0.278f, -0.0f, -0.384f, 0.266f, 0.287f, -0.275f, -0.0f, -0.394f, 0.285f, 0.304f, -0.271f, 0.0f, -0.405f, 0.302f, 0.316f,
+ -0.267f, 0.0f, -0.417f, 0.317f, 0.326f, -0.263f, 0.0f, -0.429f, 0.33f, 0.337f, -0.259f, 0.0f, -0.442f, 0.342f, 0.346f, -0.256f, 0.0f, -0.454f, 0.354f, 0.351f,
+ -0.253f, 0.0f, -0.467f, 0.365f, 0.362f, -0.251f, 0.0f, -0.48f, 0.376f, 0.38f, -0.249f, -0.0f, -0.493f, 0.386f, 0.391f, -0.247f, -0.0f, -0.505f, 0.394f, 0.396f,
+ -0.246f, -0.0f, -0.518f, 0.401f, 0.405f, -0.245f, 0.0f, -0.53f, 0.408f, 0.409f, -0.245f, 0.0f, -0.542f, 0.415f, 0.413f, -0.245f, 0.0f, -0.554f, 0.421f, 0.42f,
+ -0.245f, 0.0f, -0.565f, 0.426f, 0.43f, -0.246f, 0.0f, -0.575f, 0.43f, 0.433f, -0.246f, -0.0f, -0.585f, 0.432f, 0.435f, -0.247f, -0.0f, -0.594f, 0.434f, 0.436f,
+ -0.247f, -0.0f, -0.603f, 0.435f, 0.436f, -0.248f, -0.0f, -0.612f, 0.436f, 0.436f, -0.25f, -0.0f, -0.621f, 0.437f, 0.438f, -0.252f, -0.0f, -0.631f, 0.437f, 0.438f,
+ -0.254f, -0.0f, -0.642f, 0.438f, 0.438f, -0.255f, 0.0f, -0.653f, 0.438f, 0.438f, -0.258f, 0.0f, -0.664f, 0.438f, 0.439f, -0.26f, 0.0f, -0.674f, 0.439f, 0.439f,
+ -0.261f, 0.0f, -0.685f, 0.439f, 0.439f, -0.262f, 0.0f, -0.696f, 0.439f, 0.439f, -0.264f, 0.0f, -0.706f, 0.439f, 0.439f, -0.265f, 0.0f, -0.717f, 0.439f, 0.439f,
+ -0.265f, 0.0f, -0.727f, 0.438f, 0.439f, -0.266f, 0.0f, -0.738f, 0.437f, 0.439f, -0.266f, 0.0f, -0.749f, 0.435f, 0.438f, -0.266f, 0.0f, -0.76f, 0.433f, 0.433f,
+ -0.265f, 0.0f, -0.771f, 0.431f, 0.428f, -0.265f, 0.0f, -0.781f, 0.43f, 0.428f, -0.263f, 0.0f, -0.792f, 0.429f, 0.428f, -0.26f, 0.0f, -0.802f, 0.428f, 0.429f,
+ -0.257f, 0.0f, -0.812f, 0.426f, 0.427f, -0.254f, 0.0f, -0.821f, 0.423f, 0.426f, -0.25f, 0.0f, -0.829f, 0.421f, 0.42f, -0.247f, 0.0f, -0.837f, 0.418f, 0.416f,
+ -0.242f, 0.0f, -0.844f, 0.417f, 0.415f, -0.238f, 0.0f, -0.85f, 0.415f, 0.413f, -0.234f, 0.0f, -0.857f, 0.415f, 0.413f, -0.229f, 0.0f, -0.864f, 0.414f, 0.413f,
+ -0.224f, 0.0f, -0.87f, 0.414f, 0.413f, -0.219f, 0.0f, -0.877f, 0.414f, 0.414f, -0.214f, 0.0f, -0.883f, 0.414f, 0.413f, -0.208f, 0.0f, -0.89f, 0.413f, 0.413f,
+ -0.203f, 0.0f, -0.897f, 0.413f, 0.413f, -0.197f, 0.0f, -0.903f, 0.413f, 0.413f, -0.191f, 0.0f, -0.909f, 0.413f, 0.413f, -0.186f, 0.0f, -0.914f, 0.413f, 0.413f,
+ -0.181f, 0.0f, -0.92f, 0.413f, 0.413f, -0.175f, -0.0f, -0.925f, 0.413f, 0.413f, -0.17f, -0.0f, -0.931f, 0.413f, 0.413f, -0.164f, -0.0f, -0.936f, 0.413f, 0.413f,
+ -0.159f, -0.0f, -0.942f, 0.413f, 0.413f, -0.152f, -0.0f, -0.948f, 0.413f, 0.413f, -0.145f, -0.0f, -0.955f, 0.413f, 0.413f, -0.137f, -0.0f, -0.961f, 0.414f, 0.413f,
+ -0.13f, -0.0f, -0.967f, 0.414f, 0.413f, -0.122f, -0.0f, -0.974f, 0.414f, 0.414f, -0.114f, -0.0f, -0.979f, 0.414f, 0.413f, -0.106f, -0.0f, -0.985f, 0.414f, 0.413f,
+ -0.098f, -0.0f, -0.989f, 0.414f, 0.414f, -0.091f, -0.0f, -0.993f, 0.414f, 0.413f, -0.083f, -0.0f, -0.997f, 0.414f, 0.414f, -0.075f, -0.0f, -0.999f, 0.414f, 0.414f,
+ -0.066f, -0.0f, -1.001f, 0.414f, 0.414f, -0.057f, -0.0f, -1.003f, 0.414f, 0.413f, -0.046f, -0.0f, -1.006f, 0.414f, 0.413f, -0.038f, -0.0f, -1.008f, 0.414f, 0.413f,
+ -0.031f, -0.0f, -1.009f, 0.421f, 0.413f, -0.036f, -0.0f, -1.008f, 0.423f, 0.424f, -0.045f, -0.0f, -1.006f, 0.425f, 0.425f, -0.054f, -0.0f, -1.005f, 0.425f, 0.425f,
+ -0.064f, -0.0f, -1.005f, 0.425f, 0.425f, -0.073f, -0.0f, -1.004f, 0.425f, 0.425f, -0.084f, -0.0f, -1.003f, 0.425f, 0.425f, -0.095f, -0.0f, -1.001f, 0.424f, 0.424f,
+ -0.105f, -0.0f, -0.997f, 0.423f, 0.424f, -0.116f, -0.0f, -0.994f, 0.422f, 0.422f, -0.127f, -0.0f, -0.991f, 0.421f, 0.419f, -0.137f, -0.0f, -0.987f, 0.42f, 0.419f,
+ -0.148f, -0.0f, -0.983f, 0.42f, 0.419f, -0.158f, -0.0f, -0.98f, 0.42f, 0.419f, -0.167f, -0.0f, -0.976f, 0.419f, 0.419f, -0.176f, -0.0f, -0.973f, 0.419f, 0.419f,
+ -0.184f, -0.0f, -0.969f, 0.419f, 0.419f, -0.192f, -0.0f, -0.966f, 0.419f, 0.418f, -0.2f, 0.0f, -0.962f, 0.419f, 0.418f, -0.207f, 0.0f, -0.957f, 0.419f, 0.419f,
+ -0.215f, 0.0f, -0.953f, 0.419f, 0.418f, -0.223f, 0.0f, -0.948f, 0.419f, 0.419f, -0.231f, 0.0f, -0.944f, 0.419f, 0.419f, -0.239f, 0.0f, -0.939f, 0.419f, 0.419f,
+ -0.247f, 0.0f, -0.934f, 0.419f, 0.419f, -0.255f, 0.0f, -0.929f, 0.419f, 0.419f, -0.262f, 0.0f, -0.924f, 0.419f, 0.419f, -0.269f, 0.0f, -0.919f, 0.419f, 0.418f,
+ -0.275f, 0.0f, -0.914f, 0.419f, 0.419f, -0.281f, 0.0f, -0.909f, 0.419f, 0.418f, -0.287f, 0.0f, -0.904f, 0.419f, 0.418f, -0.293f, 0.0f, -0.899f, 0.419f, 0.418f,
+ -0.299f, 0.0f, -0.894f, 0.42f, 0.419f, -0.304f, 0.0f, -0.888f, 0.421f, 0.42f, -0.311f, 0.0f, -0.882f, 0.423f, 0.422f, -0.317f, 0.0f, -0.876f, 0.424f, 0.424f,
+ -0.322f, 0.0f, -0.869f, 0.426f, 0.426f, -0.328f, 0.0f, -0.861f, 0.427f, 0.427f, -0.332f, 0.0f, -0.853f, 0.429f, 0.429f, -0.336f, 0.0f, -0.843f, 0.43f, 0.429f,
+ -0.339f, 0.0f, -0.834f, 0.432f, 0.431f, -0.341f, 0.0f, -0.821f, 0.435f, 0.434f, -0.342f, 0.0f, -0.809f, 0.438f, 0.439f, -0.343f, 0.0f, -0.796f, 0.44f, 0.44f,
+ -0.343f, 0.0f, -0.783f, 0.442f, 0.442f, -0.343f, 0.0f, -0.772f, 0.446f, 0.445f, -0.342f, 0.0f, -0.76f, 0.45f, 0.45f, -0.342f, 0.0f, -0.748f, 0.454f, 0.455f,
+ -0.34f, 0.0f, -0.735f, 0.457f, 0.457f, -0.339f, 0.0f, -0.723f, 0.46f, 0.46f, -0.338f, 0.0f, -0.711f, 0.463f, 0.464f, -0.336f, 0.0f, -0.7f, 0.465f, 0.465f,
+ -0.335f, 0.0f, -0.688f, 0.466f, 0.466f, -0.332f, 0.0f, -0.676f, 0.467f, 0.467f, -0.331f, 0.0f, -0.664f, 0.467f, 0.467f, -0.33f, 0.0f, -0.651f, 0.467f, 0.467f,
+ -0.328f, 0.0f, -0.638f, 0.467f, 0.467f, -0.325f, 0.0f, -0.625f, 0.467f, 0.467f, -0.323f, 0.0f, -0.614f, 0.467f, 0.467f, -0.321f, 0.0f, -0.603f, 0.467f, 0.466f,
+ -0.318f, 0.0f, -0.592f, 0.467f, 0.466f, -0.315f, 0.0f, -0.581f, 0.467f, 0.466f, -0.313f, 0.0f, -0.569f, 0.467f, 0.467f, -0.311f, -0.0f, -0.557f, 0.467f, 0.467f,
+ -0.309f, -0.0f, -0.543f, 0.467f, 0.467f, -0.306f, -0.0f, -0.531f, 0.467f, 0.467f, -0.303f, -0.0f, -0.519f, 0.467f, 0.467f, -0.301f, -0.0f, -0.507f, 0.467f, 0.468f,
+ -0.299f, -0.0f, -0.497f, 0.467f, 0.467f, -0.297f, -0.0f, -0.487f, 0.467f, 0.467f, -0.295f, 0.0f, -0.476f, 0.465f, 0.467f, -0.293f, 0.0f, -0.466f, 0.463f, 0.467f,
+ -0.292f, 0.0f, -0.456f, 0.46f, 0.466f, -0.291f, 0.0f, -0.445f, 0.455f, 0.459f, -0.29f, 0.0f, -0.435f, 0.449f, 0.457f, -0.29f, 0.0f, -0.424f, 0.44f, 0.448f,
+ -0.29f, 0.0f, -0.413f, 0.43f, 0.44f, -0.29f, 0.0f, -0.403f, 0.418f, 0.437f, -0.29f, -0.0f, -0.393f, 0.404f, 0.415f, -0.291f, -0.0f, -0.384f, 0.388f, 0.393f,
+ -0.29f, -0.0f, -0.376f, 0.374f, 0.379f, -0.29f, -0.0f, -0.365f, 0.352f, 0.352f,
+};
+
+static const float data8[55 * GP_PRIM_DATABUF_SIZE] = {
+ 0.781f, 0.0f, 0.098f, 0.109f, 0.109f, 0.784f, 0.0f, 0.105f, 0.202f, 0.338f, 0.785f, 0.0f, 0.108f, 0.254f, 0.369f, 0.787f, 0.0f, 0.113f, 0.306f, 0.382f,
+ 0.787f, 0.0f, 0.118f, 0.344f, 0.392f, 0.789f, 0.0f, 0.123f, 0.372f, 0.401f, 0.79f, 0.0f, 0.128f, 0.392f, 0.41f, 0.792f, 0.0f, 0.135f, 0.406f, 0.42f,
+ 0.794f, 0.0f, 0.142f, 0.416f, 0.424f, 0.797f, 0.0f, 0.152f, 0.424f, 0.428f, 0.801f, 0.0f, 0.161f, 0.429f, 0.431f, 0.807f, 0.0f, 0.172f, 0.432f, 0.435f,
+ 0.814f, 0.0f, 0.182f, 0.435f, 0.438f, 0.821f, 0.0f, 0.19f, 0.437f, 0.439f, 0.828f, 0.0f, 0.197f, 0.439f, 0.44f, 0.836f, 0.0f, 0.204f, 0.44f, 0.441f,
+ 0.845f, -0.0f, 0.211f, 0.44f, 0.441f, 0.853f, -0.0f, 0.215f, 0.441f, 0.441f, 0.861f, -0.0f, 0.219f, 0.441f, 0.441f, 0.87f, -0.0f, 0.222f, 0.441f, 0.442f,
+ 0.878f, -0.0f, 0.224f, 0.441f, 0.442f, 0.886f, -0.0f, 0.226f, 0.441f, 0.442f, 0.895f, -0.0f, 0.227f, 0.44f, 0.442f, 0.903f, 0.0f, 0.226f, 0.439f, 0.441f,
+ 0.911f, 0.0f, 0.225f, 0.436f, 0.441f, 0.919f, 0.0f, 0.224f, 0.432f, 0.441f, 0.927f, 0.0f, 0.221f, 0.425f, 0.436f, 0.934f, 0.0f, 0.218f, 0.415f, 0.429f,
+ 0.94f, 0.0f, 0.215f, 0.404f, 0.406f, 0.944f, 0.0f, 0.211f, 0.393f, 0.389f, 0.947f, 0.0f, 0.208f, 0.384f, 0.378f, 0.948f, 0.0f, 0.204f, 0.376f, 0.371f,
+ 0.946f, 0.0f, 0.2f, 0.369f, 0.364f, 0.943f, 0.0f, 0.196f, 0.365f, 0.358f, 0.937f, 0.0f, 0.193f, 0.364f, 0.354f, 0.931f, 0.0f, 0.189f, 0.366f, 0.359f,
+ 0.925f, 0.0f, 0.186f, 0.37f, 0.367f, 0.917f, 0.0f, 0.182f, 0.374f, 0.375f, 0.908f, 0.0f, 0.177f, 0.378f, 0.382f, 0.899f, 0.0f, 0.172f, 0.381f, 0.384f,
+ 0.889f, 0.0f, 0.167f, 0.384f, 0.385f, 0.876f, 0.0f, 0.163f, 0.387f, 0.387f, 0.864f, 0.0f, 0.156f, 0.39f, 0.388f, 0.852f, 0.0f, 0.15f, 0.393f, 0.39f,
+ 0.841f, 0.0f, 0.144f, 0.396f, 0.396f, 0.832f, 0.0f, 0.138f, 0.399f, 0.401f, 0.826f, 0.0f, 0.133f, 0.401f, 0.404f, 0.82f, 0.0f, 0.127f, 0.403f, 0.405f,
+ 0.816f, 0.0f, 0.122f, 0.403f, 0.407f, 0.812f, 0.0f, 0.119f, 0.399f, 0.406f, 0.808f, 0.0f, 0.115f, 0.39f, 0.405f, 0.805f, 0.0f, 0.113f, 0.371f, 0.407f,
+ 0.801f, 0.0f, 0.111f, 0.341f, 0.407f, 0.799f, 0.0f, 0.109f, 0.309f, 0.405f, 0.795f, 0.0f, 0.106f, 0.255f, 0.255f,
+};
+
+static const float data9[70 * GP_PRIM_DATABUF_SIZE] = {
+ 0.819f, -0.0f, 0.325f, 0.109f, 0.109f, 0.829f, -0.0f, 0.328f, 0.258f, 0.403f, 0.835f, -0.0f, 0.329f, 0.327f, 0.428f, 0.843f, -0.0f, 0.331f, 0.383f, 0.452f,
+ 0.851f, -0.0f, 0.332f, 0.419f, 0.465f, 0.861f, -0.0f, 0.334f, 0.444f, 0.473f, 0.87f, -0.0f, 0.336f, 0.461f, 0.48f, 0.881f, -0.0f, 0.337f, 0.473f, 0.486f,
+ 0.892f, -0.0f, 0.339f, 0.482f, 0.496f, 0.904f, -0.0f, 0.341f, 0.489f, 0.501f, 0.917f, -0.0f, 0.342f, 0.494f, 0.503f, 0.931f, -0.0f, 0.342f, 0.498f, 0.505f,
+ 0.945f, -0.0f, 0.342f, 0.501f, 0.505f, 0.958f, -0.0f, 0.342f, 0.503f, 0.506f, 0.971f, -0.0f, 0.341f, 0.505f, 0.506f, 0.984f, -0.0f, 0.341f, 0.506f, 0.506f,
+ 0.997f, -0.0f, 0.339f, 0.507f, 0.508f, 1.009f, -0.0f, 0.337f, 0.507f, 0.507f, 1.021f, -0.0f, 0.333f, 0.508f, 0.508f, 1.033f, -0.0f, 0.33f, 0.508f, 0.508f,
+ 1.044f, -0.0f, 0.326f, 0.508f, 0.508f, 1.056f, -0.0f, 0.322f, 0.508f, 0.508f, 1.068f, -0.0f, 0.317f, 0.508f, 0.508f, 1.078f, -0.0f, 0.311f, 0.507f, 0.508f,
+ 1.089f, -0.0f, 0.304f, 0.506f, 0.508f, 1.099f, 0.0f, 0.294f, 0.503f, 0.506f, 1.107f, 0.0f, 0.287f, 0.498f, 0.506f, 1.113f, 0.0f, 0.28f, 0.49f, 0.505f,
+ 1.117f, 0.0f, 0.276f, 0.48f, 0.501f, 1.121f, 0.0f, 0.272f, 0.468f, 0.492f, 1.124f, 0.0f, 0.27f, 0.455f, 0.467f, 1.127f, 0.0f, 0.27f, 0.443f, 0.431f,
+ 1.129f, 0.0f, 0.271f, 0.431f, 0.4f, 1.13f, 0.0f, 0.274f, 0.422f, 0.399f, 1.13f, 0.0f, 0.278f, 0.414f, 0.399f, 1.13f, 0.0f, 0.286f, 0.408f, 0.399f,
+ 1.128f, 0.0f, 0.295f, 0.404f, 0.399f, 1.124f, 0.0f, 0.305f, 0.402f, 0.399f, 1.119f, 0.0f, 0.316f, 0.403f, 0.4f, 1.113f, -0.0f, 0.327f, 0.405f, 0.401f,
+ 1.107f, -0.0f, 0.337f, 0.408f, 0.411f, 1.1f, -0.0f, 0.345f, 0.412f, 0.412f, 1.094f, -0.0f, 0.352f, 0.416f, 0.413f, 1.087f, -0.0f, 0.357f, 0.421f, 0.422f,
+ 1.08f, -0.0f, 0.363f, 0.426f, 0.428f, 1.071f, -0.0f, 0.368f, 0.429f, 0.43f, 1.062f, -0.0f, 0.373f, 0.431f, 0.431f, 1.051f, -0.0f, 0.377f, 0.433f, 0.431f,
+ 1.039f, -0.0f, 0.381f, 0.436f, 0.437f, 1.026f, -0.0f, 0.383f, 0.438f, 0.44f, 1.013f, -0.0f, 0.384f, 0.44f, 0.44f, 1.0f, -0.0f, 0.385f, 0.441f, 0.443f,
+ 0.987f, -0.0f, 0.385f, 0.442f, 0.443f, 0.975f, -0.0f, 0.384f, 0.443f, 0.443f, 0.962f, -0.0f, 0.383f, 0.443f, 0.444f, 0.949f, -0.0f, 0.381f, 0.443f, 0.443f,
+ 0.936f, -0.0f, 0.38f, 0.443f, 0.444f, 0.923f, -0.0f, 0.378f, 0.443f, 0.444f, 0.909f, -0.0f, 0.375f, 0.443f, 0.444f, 0.897f, -0.0f, 0.371f, 0.443f, 0.444f,
+ 0.886f, -0.0f, 0.367f, 0.443f, 0.443f, 0.876f, -0.0f, 0.363f, 0.443f, 0.444f, 0.868f, -0.0f, 0.359f, 0.443f, 0.442f, 0.86f, -0.0f, 0.355f, 0.442f, 0.443f,
+ 0.852f, -0.0f, 0.35f, 0.441f, 0.443f, 0.844f, -0.0f, 0.347f, 0.433f, 0.443f, 0.837f, -0.0f, 0.343f, 0.409f, 0.443f, 0.83f, -0.0f, 0.338f, 0.344f, 0.443f,
+ 0.824f, -0.0f, 0.335f, 0.239f, 0.437f, 0.815f, -0.0f, 0.326f, 0.0f, 0.003f,
+};
+
+static const float data10[227 * GP_PRIM_DATABUF_SIZE] = {
+ -0.675f, 0.0f, 0.411f, 0.099f, 0.099f, -0.669f, 0.0f, 0.418f, 0.358f, 0.358f, -0.666f, 0.0f, 0.424f, 0.381f, 0.381f, -0.662f, 0.0f, 0.431f, 0.389f, 0.389f,
+ -0.658f, 0.0f, 0.438f, 0.393f, 0.393f, -0.649f, 0.0f, 0.448f, 0.404f, 0.404f, -0.641f, 0.0f, 0.458f, 0.419f, 0.419f, -0.632f, 0.0f, 0.468f, 0.431f, 0.434f,
+ -0.626f, 0.0f, 0.476f, 0.435f, 0.436f, -0.62f, 0.0f, 0.484f, 0.437f, 0.438f, -0.615f, 0.0f, 0.492f, 0.439f, 0.439f, -0.61f, 0.0f, 0.499f, 0.439f, 0.44f,
+ -0.605f, 0.0f, 0.506f, 0.44f, 0.44f, -0.6f, 0.0f, 0.512f, 0.44f, 0.44f, -0.595f, 0.0f, 0.519f, 0.44f, 0.44f, -0.59f, 0.0f, 0.526f, 0.441f, 0.441f,
+ -0.584f, 0.0f, 0.532f, 0.441f, 0.441f, -0.579f, 0.0f, 0.539f, 0.441f, 0.441f, -0.573f, 0.0f, 0.545f, 0.442f, 0.442f, -0.566f, 0.0f, 0.551f, 0.443f, 0.443f,
+ -0.559f, 0.0f, 0.557f, 0.443f, 0.443f, -0.552f, 0.0f, 0.563f, 0.444f, 0.444f, -0.545f, 0.0f, 0.569f, 0.445f, 0.445f, -0.538f, 0.0f, 0.576f, 0.447f, 0.447f,
+ -0.532f, 0.0f, 0.582f, 0.448f, 0.448f, -0.525f, 0.0f, 0.589f, 0.45f, 0.45f, -0.519f, 0.0f, 0.595f, 0.451f, 0.452f, -0.513f, 0.0f, 0.602f, 0.452f, 0.453f,
+ -0.506f, 0.0f, 0.608f, 0.453f, 0.453f, -0.5f, 0.0f, 0.613f, 0.453f, 0.454f, -0.493f, 0.0f, 0.619f, 0.453f, 0.454f, -0.486f, 0.0f, 0.625f, 0.453f, 0.454f,
+ -0.479f, 0.0f, 0.631f, 0.453f, 0.454f, -0.472f, 0.0f, 0.637f, 0.453f, 0.454f, -0.464f, 0.0f, 0.642f, 0.453f, 0.454f, -0.457f, 0.0f, 0.649f, 0.453f, 0.454f,
+ -0.45f, 0.0f, 0.655f, 0.453f, 0.453f, -0.443f, 0.0f, 0.661f, 0.453f, 0.453f, -0.435f, 0.0f, 0.667f, 0.453f, 0.454f, -0.427f, 0.0f, 0.672f, 0.453f, 0.454f,
+ -0.419f, 0.0f, 0.677f, 0.453f, 0.454f, -0.411f, 0.0f, 0.682f, 0.453f, 0.453f, -0.403f, 0.0f, 0.688f, 0.453f, 0.453f, -0.395f, 0.0f, 0.692f, 0.453f, 0.454f,
+ -0.387f, 0.0f, 0.697f, 0.453f, 0.454f, -0.379f, 0.0f, 0.702f, 0.453f, 0.454f, -0.372f, 0.0f, 0.707f, 0.454f, 0.454f, -0.364f, 0.0f, 0.712f, 0.454f, 0.454f,
+ -0.356f, 0.0f, 0.716f, 0.454f, 0.454f, -0.349f, 0.0f, 0.721f, 0.454f, 0.454f, -0.342f, 0.0f, 0.725f, 0.454f, 0.454f, -0.334f, 0.0f, 0.73f, 0.454f, 0.454f,
+ -0.326f, 0.0f, 0.733f, 0.454f, 0.454f, -0.318f, 0.0f, 0.737f, 0.454f, 0.454f, -0.31f, 0.0f, 0.74f, 0.454f, 0.454f, -0.301f, 0.0f, 0.743f, 0.454f, 0.454f,
+ -0.293f, 0.0f, 0.746f, 0.454f, 0.455f, -0.284f, 0.0f, 0.749f, 0.454f, 0.455f, -0.274f, 0.0f, 0.752f, 0.455f, 0.455f, -0.265f, 0.0f, 0.755f, 0.455f, 0.455f,
+ -0.255f, 0.0f, 0.757f, 0.455f, 0.455f, -0.245f, 0.0f, 0.76f, 0.456f, 0.455f, -0.234f, 0.0f, 0.762f, 0.457f, 0.456f, -0.223f, 0.0f, 0.764f, 0.458f, 0.458f,
+ -0.212f, 0.0f, 0.766f, 0.459f, 0.46f, -0.201f, 0.0f, 0.769f, 0.461f, 0.46f, -0.189f, 0.0f, 0.771f, 0.462f, 0.461f, -0.177f, 0.0f, 0.773f, 0.464f, 0.463f,
+ -0.166f, 0.0f, 0.775f, 0.465f, 0.465f, -0.153f, 0.0f, 0.777f, 0.467f, 0.467f, -0.141f, 0.0f, 0.779f, 0.469f, 0.469f, -0.128f, 0.0f, 0.781f, 0.472f, 0.472f,
+ -0.116f, 0.0f, 0.782f, 0.474f, 0.473f, -0.101f, 0.0f, 0.782f, 0.477f, 0.477f, -0.087f, 0.0f, 0.783f, 0.482f, 0.477f, -0.073f, 0.0f, 0.783f, 0.489f, 0.483f,
+ -0.059f, 0.0f, 0.783f, 0.497f, 0.5f, -0.046f, 0.0f, 0.784f, 0.503f, 0.509f, -0.033f, 0.0f, 0.784f, 0.508f, 0.51f, -0.022f, 0.0f, 0.784f, 0.51f, 0.512f,
+ -0.011f, 0.0f, 0.785f, 0.512f, 0.512f, -0.0f, 0.0f, 0.786f, 0.513f, 0.512f, 0.011f, 0.0f, 0.786f, 0.515f, 0.513f, 0.022f, 0.0f, 0.786f, 0.517f, 0.517f,
+ 0.032f, 0.0f, 0.786f, 0.52f, 0.519f, 0.044f, 0.0f, 0.786f, 0.522f, 0.524f, 0.055f, 0.0f, 0.785f, 0.525f, 0.525f, 0.066f, 0.0f, 0.785f, 0.527f, 0.525f,
+ 0.076f, 0.0f, 0.784f, 0.53f, 0.53f, 0.086f, 0.0f, 0.783f, 0.532f, 0.533f, 0.097f, 0.0f, 0.782f, 0.535f, 0.534f, 0.108f, 0.0f, 0.782f, 0.538f, 0.541f,
+ 0.119f, 0.0f, 0.781f, 0.54f, 0.542f, 0.13f, 0.0f, 0.781f, 0.543f, 0.543f, 0.141f, 0.0f, 0.78f, 0.545f, 0.545f, 0.154f, 0.0f, 0.779f, 0.547f, 0.547f,
+ 0.165f, 0.0f, 0.777f, 0.549f, 0.548f, 0.177f, 0.0f, 0.775f, 0.55f, 0.552f, 0.188f, 0.0f, 0.772f, 0.552f, 0.552f, 0.199f, 0.0f, 0.77f, 0.553f, 0.553f,
+ 0.209f, 0.0f, 0.767f, 0.554f, 0.554f, 0.218f, 0.0f, 0.765f, 0.555f, 0.556f, 0.226f, 0.0f, 0.763f, 0.556f, 0.557f, 0.235f, 0.0f, 0.761f, 0.557f, 0.557f,
+ 0.244f, 0.0f, 0.758f, 0.558f, 0.558f, 0.253f, 0.0f, 0.755f, 0.559f, 0.559f, 0.263f, 0.0f, 0.752f, 0.56f, 0.559f, 0.272f, 0.0f, 0.749f, 0.561f, 0.56f,
+ 0.285f, 0.0f, 0.745f, 0.562f, 0.56f, 0.299f, 0.0f, 0.741f, 0.563f, 0.563f, 0.316f, 0.0f, 0.736f, 0.564f, 0.564f, 0.331f, 0.0f, 0.728f, 0.565f, 0.567f,
+ 0.349f, 0.0f, 0.718f, 0.565f, 0.568f, 0.365f, 0.0f, 0.708f, 0.566f, 0.568f, 0.38f, 0.0f, 0.699f, 0.566f, 0.568f, 0.39f, 0.0f, 0.693f, 0.566f, 0.568f,
+ 0.397f, 0.0f, 0.687f, 0.566f, 0.569f, 0.4f, 0.0f, 0.683f, 0.566f, 0.569f, 0.401f, 0.0f, 0.681f, 0.565f, 0.57f, 0.4f, 0.0f, 0.679f, 0.565f, 0.57f,
+ 0.397f, 0.0f, 0.678f, 0.564f, 0.57f, 0.393f, 0.0f, 0.678f, 0.564f, 0.565f, 0.387f, 0.0f, 0.678f, 0.563f, 0.559f, 0.379f, 0.0f, 0.679f, 0.562f, 0.558f,
+ 0.37f, 0.0f, 0.681f, 0.561f, 0.557f, 0.357f, 0.0f, 0.684f, 0.561f, 0.557f, 0.342f, 0.0f, 0.689f, 0.56f, 0.557f, 0.324f, 0.0f, 0.694f, 0.56f, 0.557f,
+ 0.307f, 0.0f, 0.697f, 0.559f, 0.558f, 0.291f, 0.0f, 0.699f, 0.559f, 0.558f, 0.274f, 0.0f, 0.701f, 0.559f, 0.557f, 0.26f, 0.0f, 0.703f, 0.558f, 0.558f,
+ 0.246f, 0.0f, 0.705f, 0.558f, 0.558f, 0.235f, 0.0f, 0.707f, 0.558f, 0.558f, 0.224f, 0.0f, 0.709f, 0.558f, 0.558f, 0.214f, 0.0f, 0.711f, 0.558f, 0.558f,
+ 0.203f, 0.0f, 0.713f, 0.558f, 0.559f, 0.192f, 0.0f, 0.714f, 0.558f, 0.558f, 0.181f, 0.0f, 0.714f, 0.557f, 0.557f, 0.17f, 0.0f, 0.714f, 0.557f, 0.557f,
+ 0.16f, 0.0f, 0.715f, 0.557f, 0.556f, 0.149f, 0.0f, 0.715f, 0.557f, 0.556f, 0.139f, 0.0f, 0.716f, 0.557f, 0.556f, 0.129f, 0.0f, 0.716f, 0.558f, 0.556f,
+ 0.119f, 0.0f, 0.717f, 0.558f, 0.556f, 0.109f, 0.0f, 0.717f, 0.558f, 0.557f, 0.099f, 0.0f, 0.718f, 0.558f, 0.557f, 0.089f, 0.0f, 0.718f, 0.559f, 0.557f,
+ 0.079f, 0.0f, 0.718f, 0.559f, 0.558f, 0.068f, 0.0f, 0.719f, 0.559f, 0.559f, 0.057f, 0.0f, 0.719f, 0.56f, 0.56f, 0.046f, 0.0f, 0.718f, 0.56f, 0.561f,
+ 0.035f, 0.0f, 0.718f, 0.561f, 0.561f, 0.024f, 0.0f, 0.718f, 0.561f, 0.562f, 0.013f, 0.0f, 0.717f, 0.562f, 0.562f, 0.002f, 0.0f, 0.717f, 0.562f, 0.563f,
+ -0.01f, 0.0f, 0.717f, 0.563f, 0.564f, -0.021f, 0.0f, 0.717f, 0.563f, 0.564f, -0.032f, 0.0f, 0.716f, 0.563f, 0.564f, -0.044f, 0.0f, 0.715f, 0.564f, 0.564f,
+ -0.055f, 0.0f, 0.714f, 0.564f, 0.565f, -0.066f, 0.0f, 0.713f, 0.564f, 0.565f, -0.078f, 0.0f, 0.712f, 0.564f, 0.564f, -0.089f, 0.0f, 0.711f, 0.564f, 0.564f,
+ -0.101f, 0.0f, 0.709f, 0.565f, 0.564f, -0.112f, 0.0f, 0.708f, 0.565f, 0.564f, -0.124f, 0.0f, 0.707f, 0.565f, 0.564f, -0.135f, 0.0f, 0.705f, 0.565f, 0.564f,
+ -0.146f, 0.0f, 0.704f, 0.566f, 0.564f, -0.158f, 0.0f, 0.702f, 0.566f, 0.564f, -0.169f, 0.0f, 0.7f, 0.566f, 0.566f, -0.18f, 0.0f, 0.698f, 0.567f, 0.568f,
+ -0.191f, 0.0f, 0.696f, 0.567f, 0.568f, -0.203f, 0.0f, 0.693f, 0.567f, 0.568f, -0.215f, 0.0f, 0.69f, 0.567f, 0.568f, -0.227f, 0.0f, 0.687f, 0.567f, 0.568f,
+ -0.238f, 0.0f, 0.684f, 0.567f, 0.568f, -0.25f, 0.0f, 0.681f, 0.567f, 0.569f, -0.262f, 0.0f, 0.678f, 0.567f, 0.569f, -0.273f, 0.0f, 0.675f, 0.567f, 0.567f,
+ -0.284f, 0.0f, 0.673f, 0.567f, 0.566f, -0.295f, 0.0f, 0.671f, 0.567f, 0.567f, -0.305f, 0.0f, 0.669f, 0.566f, 0.567f, -0.316f, 0.0f, 0.666f, 0.566f, 0.567f,
+ -0.326f, 0.0f, 0.663f, 0.565f, 0.566f, -0.337f, 0.0f, 0.66f, 0.565f, 0.566f, -0.348f, 0.0f, 0.655f, 0.564f, 0.564f, -0.359f, 0.0f, 0.652f, 0.563f, 0.564f,
+ -0.369f, 0.0f, 0.648f, 0.562f, 0.563f, -0.379f, 0.0f, 0.644f, 0.561f, 0.56f, -0.389f, 0.0f, 0.64f, 0.561f, 0.559f, -0.399f, 0.0f, 0.636f, 0.56f, 0.559f,
+ -0.409f, 0.0f, 0.633f, 0.559f, 0.559f, -0.419f, 0.0f, 0.629f, 0.559f, 0.559f, -0.428f, 0.0f, 0.625f, 0.559f, 0.558f, -0.438f, 0.0f, 0.62f, 0.559f, 0.559f,
+ -0.447f, 0.0f, 0.615f, 0.559f, 0.559f, -0.457f, 0.0f, 0.61f, 0.559f, 0.559f, -0.466f, 0.0f, 0.605f, 0.559f, 0.559f, -0.474f, 0.0f, 0.6f, 0.559f, 0.559f,
+ -0.483f, 0.0f, 0.595f, 0.559f, 0.559f, -0.492f, 0.0f, 0.591f, 0.559f, 0.559f, -0.5f, 0.0f, 0.586f, 0.559f, 0.559f, -0.508f, 0.0f, 0.58f, 0.559f, 0.559f,
+ -0.515f, 0.0f, 0.574f, 0.559f, 0.559f, -0.523f, 0.0f, 0.568f, 0.559f, 0.559f, -0.531f, 0.0f, 0.562f, 0.559f, 0.558f, -0.54f, 0.0f, 0.556f, 0.559f, 0.558f,
+ -0.548f, 0.0f, 0.549f, 0.559f, 0.559f, -0.556f, 0.0f, 0.543f, 0.559f, 0.559f, -0.562f, 0.0f, 0.537f, 0.559f, 0.559f, -0.568f, 0.0f, 0.531f, 0.559f, 0.559f,
+ -0.574f, 0.0f, 0.524f, 0.559f, 0.559f, -0.58f, 0.0f, 0.518f, 0.558f, 0.559f, -0.586f, 0.0f, 0.512f, 0.557f, 0.558f, -0.591f, 0.0f, 0.506f, 0.555f, 0.557f,
+ -0.597f, 0.0f, 0.5f, 0.551f, 0.556f, -0.603f, 0.0f, 0.493f, 0.546f, 0.547f, -0.609f, 0.0f, 0.487f, 0.541f, 0.538f, -0.614f, 0.0f, 0.48f, 0.536f, 0.535f,
+ -0.621f, 0.0f, 0.473f, 0.534f, 0.534f, -0.628f, 0.0f, 0.467f, 0.534f, 0.534f, -0.637f, 0.0f, 0.459f, 0.534f, 0.534f, -0.642f, 0.0f, 0.452f, 0.532f, 0.532f,
+ -0.65f, 0.0f, 0.445f, 0.528f, 0.528f, -0.654f, 0.0f, 0.438f, 0.525f, 0.525f, -0.659f, 0.0f, 0.431f, 0.522f, 0.522f,
+};
+
+static const float data11[1 * GP_PRIM_DATABUF_SIZE] = {
+ -0.525f, 0.0f, 0.174f, 0.124f, 0.124f,
+};
+
+static const float data12[123 * GP_PRIM_DATABUF_SIZE] = {
+ -0.53f, 0.0f, 0.193f, 0.147f, 0.147f, -0.532f, 0.0f, 0.186f, 0.316f, 0.316f, -0.534f, 0.0f, 0.18f, 0.353f, 0.353f, -0.535f, 0.0f, 0.173f, 0.382f, 0.382f,
+ -0.537f, 0.0f, 0.165f, 0.384f, 0.384f, -0.538f, 0.0f, 0.155f, 0.387f, 0.387f, -0.539f, 0.0f, 0.145f, 0.393f, 0.393f, -0.54f, -0.0f, 0.134f, 0.399f, 0.399f,
+ -0.541f, -0.0f, 0.123f, 0.4f, 0.4f, -0.542f, -0.0f, 0.11f, 0.401f, 0.401f, -0.542f, 0.0f, 0.094f, 0.402f, 0.402f, -0.54f, 0.0f, 0.078f, 0.403f, 0.403f,
+ -0.538f, 0.0f, 0.061f, 0.404f, 0.404f, -0.535f, 0.0f, 0.045f, 0.404f, 0.404f, -0.531f, 0.0f, 0.031f, 0.404f, 0.404f, -0.526f, 0.0f, 0.018f, 0.404f, 0.404f,
+ -0.52f, -0.0f, 0.005f, 0.405f, 0.405f, -0.513f, -0.0f, -0.01f, 0.405f, 0.405f, -0.505f, -0.0f, -0.024f, 0.405f, 0.405f, -0.495f, -0.0f, -0.037f, 0.405f, 0.405f,
+ -0.485f, 0.0f, -0.051f, 0.405f, 0.405f, -0.474f, 0.0f, -0.064f, 0.406f, 0.406f, -0.462f, 0.0f, -0.076f, 0.405f, 0.405f, -0.451f, 0.0f, -0.086f, 0.406f, 0.406f,
+ -0.442f, 0.0f, -0.094f, 0.406f, 0.406f, -0.432f, 0.0f, -0.102f, 0.406f, 0.406f, -0.422f, 0.0f, -0.108f, 0.405f, 0.405f, -0.411f, 0.0f, -0.114f, 0.406f, 0.406f,
+ -0.4f, 0.0f, -0.119f, 0.405f, 0.405f, -0.389f, 0.0f, -0.122f, 0.406f, 0.406f, -0.378f, 0.0f, -0.125f, 0.407f, 0.407f, -0.365f, 0.0f, -0.127f, 0.412f, 0.412f,
+ -0.354f, 0.0f, -0.129f, 0.418f, 0.418f, -0.342f, 0.0f, -0.131f, 0.44f, 0.44f, -0.33f, 0.0f, -0.131f, 0.448f, 0.448f, -0.317f, 0.0f, -0.131f, 0.469f, 0.469f,
+ -0.305f, 0.0f, -0.13f, 0.477f, 0.477f, -0.293f, 0.0f, -0.128f, 0.482f, 0.482f, -0.278f, 0.0f, -0.125f, 0.494f, 0.494f, -0.266f, 0.0f, -0.121f, 0.5f, 0.5f,
+ -0.253f, 0.0f, -0.116f, 0.507f, 0.507f, -0.242f, 0.0f, -0.111f, 0.509f, 0.509f, -0.231f, 0.0f, -0.105f, 0.511f, 0.511f, -0.222f, 0.0f, -0.099f, 0.511f, 0.511f,
+ -0.213f, 0.0f, -0.092f, 0.512f, 0.512f, -0.206f, 0.0f, -0.084f, 0.513f, 0.513f, -0.199f, 0.0f, -0.076f, 0.514f, 0.514f, -0.192f, 0.0f, -0.067f, 0.515f, 0.515f,
+ -0.186f, -0.0f, -0.058f, 0.516f, 0.516f, -0.18f, -0.0f, -0.049f, 0.516f, 0.516f, -0.175f, -0.0f, -0.04f, 0.515f, 0.515f, -0.17f, -0.0f, -0.03f, 0.515f, 0.515f,
+ -0.166f, -0.0f, -0.02f, 0.516f, 0.516f, -0.163f, -0.0f, -0.01f, 0.504f, 0.504f, -0.159f, -0.0f, 0.002f, 0.502f, 0.502f, -0.155f, -0.0f, 0.014f, 0.501f, 0.501f,
+ -0.152f, -0.0f, 0.027f, 0.502f, 0.502f, -0.149f, -0.0f, 0.043f, 0.5f, 0.5f, -0.148f, -0.0f, 0.058f, 0.49f, 0.49f, -0.147f, -0.0f, 0.075f, 0.47f, 0.47f,
+ -0.146f, -0.0f, 0.09f, 0.463f, 0.463f, -0.146f, -0.0f, 0.105f, 0.454f, 0.454f, -0.146f, -0.0f, 0.12f, 0.427f, 0.427f, -0.148f, 0.0f, 0.133f, 0.413f, 0.413f,
+ -0.15f, 0.0f, 0.144f, 0.4f, 0.4f, -0.153f, 0.0f, 0.152f, 0.383f, 0.383f, -0.156f, 0.0f, 0.157f, 0.369f, 0.369f, -0.158f, 0.0f, 0.16f, 0.36f, 0.36f,
+ -0.16f, 0.0f, 0.158f, 0.349f, 0.349f, -0.162f, 0.0f, 0.154f, 0.364f, 0.364f, -0.164f, 0.0f, 0.147f, 0.37f, 0.37f, -0.166f, 0.0f, 0.139f, 0.378f, 0.378f,
+ -0.168f, 0.0f, 0.13f, 0.386f, 0.386f, -0.172f, 0.0f, 0.119f, 0.394f, 0.394f, -0.176f, -0.0f, 0.108f, 0.405f, 0.405f, -0.18f, -0.0f, 0.096f, 0.412f, 0.412f,
+ -0.185f, -0.0f, 0.084f, 0.417f, 0.417f, -0.191f, -0.0f, 0.073f, 0.425f, 0.425f, -0.196f, -0.0f, 0.063f, 0.431f, 0.431f, -0.202f, -0.0f, 0.053f, 0.441f, 0.441f,
+ -0.208f, -0.0f, 0.043f, 0.444f, 0.444f, -0.214f, -0.0f, 0.034f, 0.451f, 0.451f, -0.22f, 0.0f, 0.026f, 0.46f, 0.46f, -0.226f, 0.0f, 0.018f, 0.463f, 0.463f,
+ -0.232f, 0.0f, 0.01f, 0.474f, 0.474f, -0.239f, 0.0f, 0.004f, 0.477f, 0.477f, -0.247f, 0.0f, -0.003f, 0.48f, 0.48f, -0.255f, 0.0f, -0.008f, 0.483f, 0.483f,
+ -0.264f, 0.0f, -0.013f, 0.497f, 0.497f, -0.274f, 0.0f, -0.018f, 0.501f, 0.501f, -0.285f, 0.0f, -0.022f, 0.505f, 0.505f, -0.297f, 0.0f, -0.024f, 0.509f, 0.509f,
+ -0.311f, 0.0f, -0.025f, 0.51f, 0.51f, -0.325f, 0.0f, -0.024f, 0.512f, 0.512f, -0.339f, 0.0f, -0.023f, 0.512f, 0.512f, -0.354f, 0.0f, -0.022f, 0.513f, 0.513f,
+ -0.368f, 0.0f, -0.02f, 0.513f, 0.513f, -0.382f, 0.0f, -0.017f, 0.514f, 0.514f, -0.397f, 0.0f, -0.013f, 0.514f, 0.514f, -0.41f, 0.0f, -0.007f, 0.514f, 0.514f,
+ -0.422f, 0.0f, 0.001f, 0.513f, 0.513f, -0.434f, 0.0f, 0.009f, 0.514f, 0.514f, -0.446f, 0.0f, 0.018f, 0.514f, 0.514f, -0.458f, 0.0f, 0.028f, 0.514f, 0.514f,
+ -0.47f, -0.0f, 0.039f, 0.514f, 0.514f, -0.48f, 0.0f, 0.048f, 0.514f, 0.514f, -0.487f, 0.0f, 0.057f, 0.514f, 0.514f, -0.493f, 0.0f, 0.068f, 0.514f, 0.514f,
+ -0.498f, 0.0f, 0.08f, 0.514f, 0.514f, -0.502f, 0.0f, 0.092f, 0.514f, 0.514f, -0.506f, 0.0f, 0.104f, 0.514f, 0.514f, -0.509f, -0.0f, 0.116f, 0.515f, 0.515f,
+ -0.511f, -0.0f, 0.125f, 0.515f, 0.515f, -0.513f, -0.0f, 0.133f, 0.515f, 0.515f, -0.515f, -0.0f, 0.141f, 0.515f, 0.515f, -0.517f, 0.0f, 0.148f, 0.515f, 0.515f,
+ -0.519f, 0.0f, 0.155f, 0.514f, 0.514f, -0.52f, 0.0f, 0.161f, 0.514f, 0.514f, -0.522f, 0.0f, 0.168f, 0.514f, 0.514f, -0.523f, 0.0f, 0.174f, 0.514f, 0.514f,
+ -0.525f, 0.0f, 0.18f, 0.514f, 0.514f, -0.526f, 0.0f, 0.185f, 0.514f, 0.514f, -0.527f, 0.0f, 0.191f, 0.513f, 0.513f,
+};
+
+static const float data13[125 * GP_PRIM_DATABUF_SIZE] = {
+ 0.184f, 0.0f, 0.22f, 0.026f, 0.026f, 0.182f, 0.0f, 0.21f, 0.275f, 0.275f, 0.18f, 0.0f, 0.203f, 0.301f, 0.301f, 0.178f, 0.0f, 0.195f, 0.322f, 0.322f,
+ 0.176f, 0.0f, 0.186f, 0.343f, 0.343f, 0.173f, 0.0f, 0.176f, 0.36f, 0.36f, 0.17f, -0.0f, 0.166f, 0.367f, 0.367f, 0.168f, -0.0f, 0.156f, 0.38f, 0.38f,
+ 0.165f, -0.0f, 0.145f, 0.385f, 0.385f, 0.163f, -0.0f, 0.132f, 0.391f, 0.391f, 0.161f, -0.0f, 0.119f, 0.401f, 0.401f, 0.16f, -0.0f, 0.103f, 0.405f, 0.405f,
+ 0.161f, -0.0f, 0.086f, 0.405f, 0.405f, 0.163f, -0.0f, 0.068f, 0.407f, 0.407f, 0.165f, 0.0f, 0.051f, 0.409f, 0.409f, 0.168f, 0.0f, 0.034f, 0.409f, 0.409f,
+ 0.172f, 0.0f, 0.018f, 0.409f, 0.409f, 0.177f, 0.0f, 0.004f, 0.409f, 0.409f, 0.183f, 0.0f, -0.008f, 0.411f, 0.411f, 0.19f, 0.0f, -0.022f, 0.411f, 0.411f,
+ 0.196f, 0.0f, -0.034f, 0.411f, 0.411f, 0.203f, 0.0f, -0.045f, 0.411f, 0.411f, 0.211f, 0.0f, -0.055f, 0.411f, 0.411f, 0.219f, 0.0f, -0.064f, 0.411f, 0.411f,
+ 0.227f, 0.0f, -0.072f, 0.411f, 0.411f, 0.235f, 0.0f, -0.08f, 0.412f, 0.412f, 0.244f, 0.0f, -0.087f, 0.412f, 0.412f, 0.253f, 0.0f, -0.094f, 0.413f, 0.413f,
+ 0.262f, 0.0f, -0.1f, 0.413f, 0.413f, 0.273f, 0.0f, -0.105f, 0.413f, 0.413f, 0.284f, 0.0f, -0.11f, 0.413f, 0.413f, 0.295f, 0.0f, -0.114f, 0.419f, 0.419f,
+ 0.307f, 0.0f, -0.117f, 0.425f, 0.425f, 0.321f, -0.0f, -0.118f, 0.433f, 0.433f, 0.334f, -0.0f, -0.12f, 0.446f, 0.446f, 0.347f, -0.0f, -0.12f, 0.474f, 0.474f,
+ 0.36f, -0.0f, -0.12f, 0.481f, 0.481f, 0.374f, -0.0f, -0.119f, 0.491f, 0.491f, 0.387f, -0.0f, -0.118f, 0.494f, 0.494f, 0.401f, 0.0f, -0.116f, 0.5f, 0.5f,
+ 0.414f, 0.0f, -0.112f, 0.505f, 0.505f, 0.426f, -0.0f, -0.107f, 0.51f, 0.51f, 0.438f, -0.0f, -0.101f, 0.513f, 0.513f, 0.449f, -0.0f, -0.094f, 0.515f, 0.515f,
+ 0.46f, -0.0f, -0.086f, 0.517f, 0.517f, 0.47f, -0.0f, -0.078f, 0.519f, 0.519f, 0.478f, -0.0f, -0.07f, 0.52f, 0.52f, 0.486f, -0.0f, -0.061f, 0.522f, 0.522f,
+ 0.493f, -0.0f, -0.052f, 0.523f, 0.523f, 0.499f, -0.0f, -0.044f, 0.522f, 0.522f, 0.505f, -0.0f, -0.035f, 0.522f, 0.522f, 0.51f, -0.0f, -0.027f, 0.523f, 0.523f,
+ 0.514f, -0.0f, -0.018f, 0.523f, 0.523f, 0.517f, -0.0f, -0.009f, 0.523f, 0.523f, 0.52f, -0.0f, -0.001f, 0.524f, 0.524f, 0.522f, -0.0f, 0.008f, 0.523f, 0.523f,
+ 0.525f, -0.0f, 0.018f, 0.521f, 0.522f, 0.527f, -0.0f, 0.027f, 0.515f, 0.514f, 0.529f, -0.0f, 0.036f, 0.512f, 0.512f, 0.531f, -0.0f, 0.045f, 0.509f, 0.51f,
+ 0.533f, -0.0f, 0.053f, 0.506f, 0.505f, 0.535f, -0.0f, 0.062f, 0.503f, 0.503f, 0.536f, -0.0f, 0.071f, 0.5f, 0.5f, 0.538f, -0.0f, 0.08f, 0.496f, 0.497f,
+ 0.538f, -0.0f, 0.09f, 0.491f, 0.492f, 0.539f, -0.0f, 0.1f, 0.485f, 0.486f, 0.539f, 0.0f, 0.11f, 0.475f, 0.476f, 0.539f, 0.0f, 0.12f, 0.46f, 0.459f,
+ 0.539f, 0.0f, 0.13f, 0.444f, 0.448f, 0.538f, 0.0f, 0.139f, 0.406f, 0.405f, 0.537f, 0.0f, 0.144f, 0.399f, 0.399f, 0.536f, 0.0f, 0.146f, 0.395f, 0.395f,
+ 0.535f, 0.0f, 0.144f, 0.412f, 0.412f, 0.533f, 0.0f, 0.139f, 0.413f, 0.413f, 0.53f, 0.0f, 0.131f, 0.414f, 0.413f, 0.528f, 0.0f, 0.122f, 0.419f, 0.418f,
+ 0.525f, 0.0f, 0.112f, 0.425f, 0.424f, 0.521f, 0.0f, 0.102f, 0.444f, 0.444f, 0.518f, 0.0f, 0.094f, 0.451f, 0.452f, 0.514f, 0.0f, 0.085f, 0.457f, 0.457f,
+ 0.509f, 0.0f, 0.078f, 0.461f, 0.46f, 0.504f, 0.0f, 0.069f, 0.469f, 0.468f, 0.499f, 0.0f, 0.06f, 0.481f, 0.481f, 0.493f, 0.0f, 0.052f, 0.489f, 0.489f,
+ 0.487f, 0.0f, 0.044f, 0.492f, 0.492f, 0.481f, 0.0f, 0.037f, 0.501f, 0.5f, 0.474f, 0.0f, 0.029f, 0.513f, 0.513f, 0.467f, 0.0f, 0.022f, 0.521f, 0.521f,
+ 0.458f, 0.0f, 0.015f, 0.524f, 0.524f, 0.449f, 0.0f, 0.008f, 0.525f, 0.525f, 0.439f, 0.0f, 0.001f, 0.528f, 0.528f, 0.427f, 0.0f, -0.005f, 0.532f, 0.532f,
+ 0.416f, 0.0f, -0.011f, 0.533f, 0.533f, 0.401f, 0.0f, -0.015f, 0.537f, 0.537f, 0.386f, 0.0f, -0.018f, 0.539f, 0.539f, 0.371f, 0.0f, -0.02f, 0.538f, 0.538f,
+ 0.356f, 0.0f, -0.021f, 0.543f, 0.543f, 0.341f, 0.0f, -0.023f, 0.543f, 0.543f, 0.326f, 0.0f, -0.023f, 0.543f, 0.543f, 0.312f, 0.0f, -0.022f, 0.543f, 0.543f,
+ 0.298f, 0.0f, -0.018f, 0.543f, 0.543f, 0.286f, 0.0f, -0.014f, 0.543f, 0.543f, 0.273f, 0.0f, -0.006f, 0.543f, 0.543f, 0.26f, 0.0f, 0.004f, 0.543f, 0.543f,
+ 0.247f, 0.0f, 0.013f, 0.543f, 0.543f, 0.235f, 0.0f, 0.022f, 0.543f, 0.543f, 0.225f, 0.0f, 0.033f, 0.543f, 0.543f, 0.215f, 0.0f, 0.045f, 0.542f, 0.542f,
+ 0.206f, 0.0f, 0.061f, 0.54f, 0.54f, 0.199f, 0.0f, 0.078f, 0.542f, 0.542f, 0.193f, 0.0f, 0.094f, 0.542f, 0.542f, 0.189f, -0.0f, 0.109f, 0.541f, 0.541f,
+ 0.186f, -0.0f, 0.119f, 0.542f, 0.542f, 0.185f, -0.0f, 0.127f, 0.542f, 0.542f, 0.184f, -0.0f, 0.135f, 0.542f, 0.542f, 0.184f, -0.0f, 0.142f, 0.542f, 0.542f,
+ 0.183f, -0.0f, 0.149f, 0.541f, 0.541f, 0.183f, -0.0f, 0.156f, 0.538f, 0.538f, 0.183f, -0.0f, 0.163f, 0.539f, 0.539f, 0.183f, -0.0f, 0.17f, 0.54f, 0.54f,
+ 0.183f, 0.0f, 0.177f, 0.54f, 0.54f, 0.183f, 0.0f, 0.184f, 0.54f, 0.54f, 0.183f, 0.0f, 0.191f, 0.54f, 0.54f, 0.184f, 0.0f, 0.196f, 0.539f, 0.539f,
+ 0.184f, 0.0f, 0.204f, 0.518f, 0.518f,
+};
+
+static const float data14[45 * GP_PRIM_DATABUF_SIZE] = {
+ -0.096f, -0.0f, -0.305f, 0.01f, 0.01f, -0.09f, -0.0f, -0.313f, 0.121f, 0.362f, -0.086f, -0.0f, -0.318f, 0.179f, 0.368f, -0.081f, -0.0f, -0.325f, 0.234f, 0.37f,
+ -0.075f, -0.0f, -0.331f, 0.272f, 0.37f, -0.068f, -0.0f, -0.338f, 0.302f, 0.371f, -0.061f, -0.0f, -0.345f, 0.324f, 0.374f, -0.053f, -0.0f, -0.352f, 0.34f, 0.377f,
+ -0.044f, -0.0f, -0.358f, 0.352f, 0.378f, -0.035f, -0.0f, -0.362f, 0.362f, 0.377f, -0.026f, -0.0f, -0.366f, 0.37f, 0.378f, -0.018f, -0.0f, -0.368f, 0.377f, 0.378f,
+ -0.009f, -0.0f, -0.369f, 0.383f, 0.376f, -0.001f, -0.0f, -0.369f, 0.389f, 0.369f, 0.007f, -0.0f, -0.368f, 0.395f, 0.364f, 0.015f, -0.0f, -0.367f, 0.4f, 0.388f,
+ 0.023f, -0.0f, -0.365f, 0.405f, 0.41f, 0.03f, -0.0f, -0.363f, 0.41f, 0.429f, 0.038f, -0.0f, -0.36f, 0.414f, 0.438f, 0.044f, -0.0f, -0.357f, 0.417f, 0.441f,
+ 0.05f, -0.0f, -0.355f, 0.419f, 0.444f, 0.055f, -0.0f, -0.352f, 0.42f, 0.441f, 0.06f, -0.0f, -0.349f, 0.421f, 0.445f, 0.063f, -0.0f, -0.347f, 0.421f, 0.446f,
+ 0.065f, -0.0f, -0.344f, 0.42f, 0.443f, 0.065f, -0.0f, -0.342f, 0.42f, 0.437f, 0.065f, -0.0f, -0.341f, 0.419f, 0.413f, 0.063f, -0.0f, -0.339f, 0.418f, 0.404f,
+ 0.061f, -0.0f, -0.338f, 0.418f, 0.403f, 0.057f, -0.0f, -0.337f, 0.418f, 0.402f, 0.052f, -0.0f, -0.337f, 0.418f, 0.407f, 0.046f, -0.0f, -0.337f, 0.419f, 0.411f,
+ 0.04f, 0.0f, -0.336f, 0.42f, 0.416f, 0.032f, 0.0f, -0.337f, 0.422f, 0.421f, 0.023f, 0.0f, -0.339f, 0.424f, 0.425f, 0.014f, 0.0f, -0.34f, 0.426f, 0.427f,
+ 0.003f, 0.0f, -0.341f, 0.428f, 0.427f, -0.007f, 0.0f, -0.341f, 0.43f, 0.433f, -0.018f, 0.0f, -0.339f, 0.432f, 0.437f, -0.027f, 0.0f, -0.335f, 0.434f, 0.438f,
+ -0.037f, 0.0f, -0.33f, 0.435f, 0.437f, -0.046f, -0.0f, -0.326f, 0.436f, 0.438f, -0.055f, -0.0f, -0.321f, 0.436f, 0.44f, -0.062f, -0.0f, -0.316f, 0.437f, 0.439f,
+ -0.073f, -0.0f, -0.31f, 0.437f, 0.437f,
+};
+
+static const float data16[84 * GP_PRIM_DATABUF_SIZE] = {
+ 0.737f, 0.0f, 0.177f, 0.148f, 0.148f, 0.735f, 0.0f, 0.164f, 0.214f, 0.39f, 0.734f, 0.0f, 0.155f, 0.254f, 0.402f, 0.732f, 0.0f, 0.143f, 0.295f, 0.413f,
+ 0.73f, 0.0f, 0.132f, 0.328f, 0.415f, 0.728f, 0.0f, 0.121f, 0.355f, 0.415f, 0.726f, 0.0f, 0.109f, 0.375f, 0.416f, 0.724f, 0.0f, 0.097f, 0.39f, 0.417f,
+ 0.721f, 0.0f, 0.086f, 0.401f, 0.418f, 0.719f, 0.0f, 0.074f, 0.408f, 0.419f, 0.716f, 0.0f, 0.062f, 0.413f, 0.42f, 0.713f, 0.0f, 0.05f, 0.416f, 0.42f,
+ 0.71f, 0.0f, 0.039f, 0.418f, 0.421f, 0.707f, 0.0f, 0.028f, 0.42f, 0.421f, 0.703f, 0.0f, 0.017f, 0.421f, 0.422f, 0.7f, 0.0f, 0.006f, 0.421f, 0.422f,
+ 0.696f, 0.0f, -0.005f, 0.422f, 0.422f, 0.693f, 0.0f, -0.015f, 0.422f, 0.422f, 0.689f, 0.0f, -0.025f, 0.423f, 0.423f, 0.685f, 0.0f, -0.034f, 0.423f, 0.423f,
+ 0.681f, 0.0f, -0.044f, 0.423f, 0.423f, 0.677f, 0.0f, -0.053f, 0.423f, 0.423f, 0.672f, 0.0f, -0.062f, 0.423f, 0.423f, 0.668f, 0.0f, -0.071f, 0.422f, 0.424f,
+ 0.662f, 0.0f, -0.08f, 0.422f, 0.424f, 0.657f, 0.0f, -0.088f, 0.422f, 0.422f, 0.651f, 0.0f, -0.095f, 0.421f, 0.419f, 0.645f, 0.0f, -0.103f, 0.42f, 0.419f,
+ 0.638f, 0.0f, -0.109f, 0.42f, 0.419f, 0.631f, 0.0f, -0.115f, 0.419f, 0.419f, 0.624f, 0.0f, -0.12f, 0.419f, 0.419f, 0.617f, 0.0f, -0.125f, 0.419f, 0.419f,
+ 0.61f, 0.0f, -0.129f, 0.418f, 0.418f, 0.602f, 0.0f, -0.133f, 0.418f, 0.416f, 0.594f, 0.0f, -0.137f, 0.417f, 0.416f, 0.587f, 0.0f, -0.14f, 0.417f, 0.415f,
+ 0.579f, 0.0f, -0.142f, 0.417f, 0.416f, 0.571f, 0.0f, -0.144f, 0.417f, 0.415f, 0.564f, 0.0f, -0.145f, 0.417f, 0.416f, 0.556f, 0.0f, -0.146f, 0.417f, 0.415f,
+ 0.549f, 0.0f, -0.146f, 0.417f, 0.415f, 0.541f, 0.0f, -0.146f, 0.417f, 0.415f, 0.535f, 0.0f, -0.145f, 0.417f, 0.416f, 0.53f, 0.0f, -0.143f, 0.418f, 0.418f,
+ 0.526f, 0.0f, -0.14f, 0.418f, 0.418f, 0.524f, 0.0f, -0.136f, 0.42f, 0.418f, 0.524f, 0.0f, -0.132f, 0.422f, 0.416f, 0.527f, 0.0f, -0.126f, 0.424f, 0.424f,
+ 0.531f, 0.0f, -0.121f, 0.427f, 0.428f, 0.536f, 0.0f, -0.115f, 0.43f, 0.433f, 0.542f, 0.0f, -0.109f, 0.433f, 0.436f, 0.548f, 0.0f, -0.102f, 0.435f, 0.436f,
+ 0.555f, 0.0f, -0.095f, 0.436f, 0.437f, 0.562f, 0.0f, -0.088f, 0.437f, 0.438f, 0.568f, 0.0f, -0.081f, 0.437f, 0.438f, 0.575f, 0.0f, -0.073f, 0.438f, 0.438f,
+ 0.581f, 0.0f, -0.065f, 0.438f, 0.438f, 0.587f, 0.0f, -0.058f, 0.438f, 0.438f, 0.593f, 0.0f, -0.05f, 0.438f, 0.438f, 0.599f, 0.0f, -0.041f, 0.438f, 0.438f,
+ 0.605f, 0.0f, -0.033f, 0.438f, 0.438f, 0.61f, 0.0f, -0.024f, 0.438f, 0.438f, 0.615f, 0.0f, -0.015f, 0.438f, 0.438f, 0.621f, 0.0f, -0.006f, 0.438f, 0.438f,
+ 0.626f, 0.0f, 0.004f, 0.438f, 0.438f, 0.631f, 0.0f, 0.013f, 0.437f, 0.438f, 0.636f, 0.0f, 0.023f, 0.436f, 0.438f, 0.641f, 0.0f, 0.032f, 0.434f, 0.438f,
+ 0.647f, 0.0f, 0.042f, 0.432f, 0.437f, 0.652f, 0.0f, 0.051f, 0.431f, 0.429f, 0.657f, 0.0f, 0.06f, 0.429f, 0.426f, 0.662f, 0.0f, 0.069f, 0.427f, 0.425f,
+ 0.668f, 0.0f, 0.078f, 0.425f, 0.425f, 0.673f, 0.0f, 0.087f, 0.423f, 0.424f, 0.678f, 0.0f, 0.095f, 0.42f, 0.422f, 0.683f, 0.0f, 0.104f, 0.416f, 0.42f,
+ 0.688f, 0.0f, 0.112f, 0.411f, 0.421f, 0.693f, 0.0f, 0.12f, 0.403f, 0.417f, 0.698f, 0.0f, 0.128f, 0.394f, 0.411f, 0.702f, 0.0f, 0.135f, 0.382f, 0.404f,
+ 0.707f, 0.0f, 0.143f, 0.369f, 0.388f, 0.711f, 0.0f, 0.15f, 0.352f, 0.371f, 0.714f, 0.0f, 0.155f, 0.338f, 0.352f, 0.719f, 0.0f, 0.164f, 0.315f, 0.315f,
+};
+
+static const float data15[44 * GP_PRIM_DATABUF_SIZE] = {
+ -0.085f, 0.0f, -0.816f, 0.138f, 0.138f, -0.079f, 0.0f, -0.825f, 0.246f, 0.309f, -0.074f, 0.0f, -0.832f, 0.302f, 0.34f, -0.067f, 0.0f, -0.84f, 0.335f, 0.352f,
+ -0.059f, 0.0f, -0.848f, 0.357f, 0.374f, -0.05f, 0.0f, -0.855f, 0.371f, 0.378f, -0.041f, 0.0f, -0.861f, 0.382f, 0.383f, -0.031f, 0.0f, -0.866f, 0.391f, 0.396f,
+ -0.021f, 0.0f, -0.871f, 0.398f, 0.401f, -0.011f, 0.0f, -0.874f, 0.404f, 0.407f, -0.001f, 0.0f, -0.877f, 0.409f, 0.411f, 0.01f, 0.0f, -0.878f, 0.415f, 0.412f,
+ 0.02f, 0.0f, -0.878f, 0.422f, 0.417f, 0.031f, 0.0f, -0.878f, 0.43f, 0.421f, 0.042f, 0.0f, -0.876f, 0.438f, 0.437f, 0.052f, 0.0f, -0.873f, 0.445f, 0.451f,
+ 0.062f, 0.0f, -0.868f, 0.451f, 0.459f, 0.071f, 0.0f, -0.863f, 0.456f, 0.463f, 0.08f, 0.0f, -0.857f, 0.46f, 0.465f, 0.087f, 0.0f, -0.85f, 0.462f, 0.465f,
+ 0.094f, 0.0f, -0.842f, 0.461f, 0.465f, 0.098f, 0.0f, -0.835f, 0.458f, 0.467f, 0.101f, 0.0f, -0.827f, 0.451f, 0.457f, 0.103f, 0.0f, -0.82f, 0.436f, 0.451f,
+ 0.102f, 0.0f, -0.815f, 0.422f, 0.418f, 0.1f, 0.0f, -0.811f, 0.419f, 0.378f, 0.096f, 0.0f, -0.814f, 0.436f, 0.447f, 0.089f, 0.0f, -0.817f, 0.454f, 0.465f,
+ 0.082f, 0.0f, -0.821f, 0.465f, 0.47f, 0.072f, 0.0f, -0.825f, 0.473f, 0.477f, 0.061f, 0.0f, -0.828f, 0.477f, 0.479f, 0.049f, 0.0f, -0.832f, 0.48f, 0.485f,
+ 0.036f, 0.0f, -0.834f, 0.483f, 0.48f, 0.023f, 0.0f, -0.836f, 0.484f, 0.485f, 0.01f, 0.0f, -0.838f, 0.486f, 0.487f, -0.003f, 0.0f, -0.84f, 0.486f, 0.488f,
+ -0.016f, 0.0f, -0.84f, 0.486f, 0.489f, -0.027f, 0.0f, -0.84f, 0.485f, 0.485f, -0.039f, 0.0f, -0.839f, 0.484f, 0.484f, -0.049f, 0.0f, -0.837f, 0.483f, 0.485f,
+ -0.058f, 0.0f, -0.834f, 0.48f, 0.481f, -0.066f, 0.0f, -0.83f, 0.473f, 0.479f, -0.072f, 0.0f, -0.827f, 0.462f, 0.472f, -0.081f, 0.0f, -0.823f, 0.442f, 0.442f,
+};
+
+static const float data17[56 * GP_PRIM_DATABUF_SIZE] = {
+ -1.007f, -0.0f, 0.183f, 0.022f, 0.022f, -1.003f, -0.0f, 0.181f, 0.192f, 0.436f, -0.998f, -0.0f, 0.18f, 0.28f, 0.451f, -0.99f, -0.0f, 0.178f, 0.355f, 0.459f,
+ -0.98f, -0.0f, 0.175f, 0.402f, 0.464f, -0.967f, -0.0f, 0.169f, 0.432f, 0.467f, -0.952f, -0.0f, 0.152f, 0.449f, 0.468f, -0.943f, 0.0f, 0.138f, 0.459f, 0.469f,
+ -0.939f, 0.0f, 0.128f, 0.464f, 0.469f, -0.934f, 0.0f, 0.119f, 0.467f, 0.47f, -0.929f, 0.0f, 0.11f, 0.469f, 0.47f, -0.924f, 0.0f, 0.101f, 0.47f, 0.47f,
+ -0.919f, 0.0f, 0.092f, 0.47f, 0.471f, -0.913f, 0.0f, 0.082f, 0.471f, 0.471f, -0.908f, 0.0f, 0.072f, 0.471f, 0.471f, -0.903f, 0.0f, 0.063f, 0.472f, 0.472f,
+ -0.897f, 0.0f, 0.053f, 0.472f, 0.472f, -0.892f, 0.0f, 0.044f, 0.473f, 0.473f, -0.886f, 0.0f, 0.035f, 0.473f, 0.473f, -0.881f, 0.0f, 0.026f, 0.473f, 0.473f,
+ -0.876f, 0.0f, 0.018f, 0.473f, 0.473f, -0.87f, 0.0f, 0.012f, 0.472f, 0.473f, -0.865f, 0.0f, 0.006f, 0.47f, 0.473f, -0.86f, 0.0f, 0.003f, 0.468f, 0.473f,
+ -0.855f, 0.0f, 0.001f, 0.466f, 0.469f, -0.85f, 0.0f, 0.001f, 0.463f, 0.469f, -0.846f, 0.0f, 0.003f, 0.46f, 0.45f, -0.843f, 0.0f, 0.008f, 0.458f, 0.454f,
+ -0.84f, 0.0f, 0.014f, 0.456f, 0.454f, -0.838f, 0.0f, 0.021f, 0.455f, 0.454f, -0.836f, 0.0f, 0.03f, 0.453f, 0.455f, -0.835f, 0.0f, 0.039f, 0.451f, 0.455f,
+ -0.835f, 0.0f, 0.049f, 0.449f, 0.453f, -0.836f, 0.0f, 0.059f, 0.447f, 0.445f, -0.837f, 0.0f, 0.068f, 0.445f, 0.441f, -0.84f, 0.0f, 0.078f, 0.443f, 0.44f,
+ -0.843f, 0.0f, 0.087f, 0.442f, 0.44f, -0.846f, 0.0f, 0.095f, 0.442f, 0.44f, -0.851f, -0.0f, 0.103f, 0.441f, 0.441f, -0.855f, -0.0f, 0.111f, 0.441f, 0.44f,
+ -0.86f, -0.0f, 0.119f, 0.441f, 0.441f, -0.865f, -0.0f, 0.127f, 0.441f, 0.441f, -0.871f, -0.0f, 0.134f, 0.441f, 0.441f, -0.877f, -0.0f, 0.141f, 0.441f, 0.441f,
+ -0.883f, -0.0f, 0.149f, 0.441f, 0.442f, -0.889f, -0.0f, 0.156f, 0.441f, 0.441f, -0.896f, -0.0f, 0.163f, 0.441f, 0.442f, -0.904f, -0.0f, 0.169f, 0.442f, 0.441f,
+ -0.913f, -0.0f, 0.176f, 0.442f, 0.441f, -0.925f, -0.0f, 0.183f, 0.443f, 0.441f, -0.941f, -0.0f, 0.19f, 0.444f, 0.442f, -0.956f, -0.0f, 0.195f, 0.446f, 0.443f,
+ -0.971f, -0.0f, 0.198f, 0.448f, 0.443f, -0.983f, -0.0f, 0.198f, 0.451f, 0.452f, -0.992f, -0.0f, 0.198f, 0.454f, 0.456f, -1.001f, 0.0f, 0.196f, 0.457f, 0.457f,
+};
+
+static const float data18[59 * GP_PRIM_DATABUF_SIZE] = {
+ 0.782f, 0.0f, 0.099f, 0.04f, 0.04f, 0.779f, 0.0f, 0.088f, 0.108f, 0.34f, 0.777f, 0.0f, 0.08f, 0.149f, 0.35f, 0.774f, 0.0f, 0.071f, 0.194f, 0.352f,
+ 0.772f, 0.0f, 0.062f, 0.231f, 0.352f, 0.771f, 0.0f, 0.053f, 0.263f, 0.353f, 0.769f, 0.0f, 0.044f, 0.289f, 0.353f, 0.768f, 0.0f, 0.036f, 0.31f, 0.353f,
+ 0.767f, 0.0f, 0.029f, 0.327f, 0.353f, 0.767f, 0.0f, 0.023f, 0.341f, 0.353f, 0.767f, 0.0f, 0.017f, 0.353f, 0.353f, 0.768f, 0.0f, 0.013f, 0.363f, 0.353f,
+ 0.769f, 0.0f, 0.01f, 0.373f, 0.353f, 0.771f, 0.0f, 0.009f, 0.382f, 0.351f, 0.773f, 0.0f, 0.008f, 0.39f, 0.393f, 0.776f, 0.0f, 0.009f, 0.399f, 0.41f,
+ 0.779f, 0.0f, 0.011f, 0.407f, 0.425f, 0.783f, 0.0f, 0.015f, 0.415f, 0.434f, 0.787f, 0.0f, 0.019f, 0.423f, 0.44f, 0.792f, 0.0f, 0.024f, 0.429f, 0.441f,
+ 0.797f, 0.0f, 0.03f, 0.435f, 0.444f, 0.802f, 0.0f, 0.037f, 0.441f, 0.447f, 0.807f, 0.0f, 0.044f, 0.445f, 0.453f, 0.813f, 0.0f, 0.051f, 0.449f, 0.457f,
+ 0.819f, 0.0f, 0.058f, 0.452f, 0.458f, 0.825f, 0.0f, 0.066f, 0.455f, 0.46f, 0.831f, 0.0f, 0.074f, 0.457f, 0.462f, 0.838f, 0.0f, 0.082f, 0.459f, 0.462f,
+ 0.845f, 0.0f, 0.09f, 0.461f, 0.462f, 0.852f, 0.0f, 0.098f, 0.462f, 0.463f, 0.859f, 0.0f, 0.106f, 0.463f, 0.464f, 0.867f, 0.0f, 0.113f, 0.464f, 0.464f,
+ 0.874f, 0.0f, 0.121f, 0.465f, 0.465f, 0.882f, 0.0f, 0.129f, 0.465f, 0.465f, 0.889f, 0.0f, 0.136f, 0.466f, 0.466f, 0.897f, 0.0f, 0.143f, 0.466f, 0.467f,
+ 0.904f, 0.0f, 0.15f, 0.467f, 0.466f, 0.911f, 0.0f, 0.157f, 0.467f, 0.467f, 0.916f, 0.0f, 0.163f, 0.468f, 0.468f, 0.921f, 0.0f, 0.169f, 0.468f, 0.469f,
+ 0.924f, 0.0f, 0.173f, 0.468f, 0.469f, 0.926f, 0.0f, 0.177f, 0.469f, 0.468f, 0.925f, 0.0f, 0.18f, 0.469f, 0.468f, 0.922f, 0.0f, 0.181f, 0.469f, 0.469f,
+ 0.918f, 0.0f, 0.181f, 0.469f, 0.469f, 0.912f, 0.0f, 0.18f, 0.469f, 0.469f, 0.905f, 0.0f, 0.178f, 0.468f, 0.47f, 0.898f, 0.0f, 0.175f, 0.466f, 0.471f,
+ 0.89f, 0.0f, 0.172f, 0.462f, 0.469f, 0.882f, 0.0f, 0.168f, 0.454f, 0.468f, 0.874f, 0.0f, 0.164f, 0.442f, 0.467f, 0.866f, 0.0f, 0.159f, 0.423f, 0.467f,
+ 0.858f, 0.0f, 0.154f, 0.398f, 0.468f, 0.851f, 0.0f, 0.149f, 0.366f, 0.468f, 0.844f, 0.0f, 0.144f, 0.326f, 0.469f, 0.837f, 0.0f, 0.139f, 0.282f, 0.469f,
+ 0.83f, 0.0f, 0.134f, 0.231f, 0.467f, 0.824f, 0.0f, 0.13f, 0.184f, 0.415f, 0.816f, 0.0f, 0.124f, 0.111f, 0.111f,
+};
+
+static const float data19[100 * GP_PRIM_DATABUF_SIZE] = {
+ -0.279f, 0.0f, 0.568f, 0.154f, 0.154f, -0.266f, 0.0f, 0.569f, 0.249f, 0.318f, -0.258f, 0.0f, 0.57f, 0.296f, 0.357f, -0.248f, 0.0f, 0.571f, 0.337f, 0.383f,
+ -0.238f, 0.0f, 0.571f, 0.363f, 0.396f, -0.229f, 0.0f, 0.571f, 0.381f, 0.403f, -0.219f, 0.0f, 0.57f, 0.392f, 0.407f, -0.209f, 0.0f, 0.568f, 0.399f, 0.407f,
+ -0.2f, 0.0f, 0.566f, 0.403f, 0.408f, -0.19f, 0.0f, 0.563f, 0.406f, 0.41f, -0.181f, 0.0f, 0.559f, 0.407f, 0.41f, -0.171f, 0.0f, 0.555f, 0.409f, 0.41f,
+ -0.161f, 0.0f, 0.551f, 0.409f, 0.411f, -0.152f, 0.0f, 0.546f, 0.41f, 0.411f, -0.142f, 0.0f, 0.542f, 0.41f, 0.412f, -0.132f, 0.0f, 0.537f, 0.411f, 0.411f,
+ -0.122f, 0.0f, 0.533f, 0.411f, 0.411f, -0.112f, 0.0f, 0.528f, 0.411f, 0.412f, -0.102f, 0.0f, 0.524f, 0.411f, 0.412f, -0.092f, 0.0f, 0.519f, 0.41f, 0.412f,
+ -0.081f, 0.0f, 0.515f, 0.407f, 0.411f, -0.071f, 0.0f, 0.511f, 0.403f, 0.408f, -0.061f, 0.0f, 0.507f, 0.399f, 0.401f, -0.051f, 0.0f, 0.503f, 0.394f, 0.395f,
+ -0.041f, 0.0f, 0.499f, 0.39f, 0.388f, -0.031f, 0.0f, 0.495f, 0.386f, 0.383f, -0.021f, 0.0f, 0.491f, 0.383f, 0.38f, -0.011f, 0.0f, 0.488f, 0.381f, 0.378f,
+ -0.001f, 0.0f, 0.486f, 0.379f, 0.377f, 0.009f, 0.0f, 0.484f, 0.378f, 0.377f, 0.019f, 0.0f, 0.483f, 0.377f, 0.375f, 0.03f, 0.0f, 0.482f, 0.377f, 0.375f,
+ 0.041f, 0.0f, 0.482f, 0.378f, 0.376f, 0.051f, 0.0f, 0.483f, 0.379f, 0.376f, 0.062f, 0.0f, 0.484f, 0.381f, 0.376f, 0.073f, 0.0f, 0.486f, 0.385f, 0.379f,
+ 0.085f, 0.0f, 0.488f, 0.389f, 0.382f, 0.096f, 0.0f, 0.491f, 0.395f, 0.392f, 0.108f, 0.0f, 0.494f, 0.402f, 0.4f, 0.12f, 0.0f, 0.497f, 0.409f, 0.409f,
+ 0.132f, 0.0f, 0.501f, 0.415f, 0.416f, 0.144f, 0.0f, 0.505f, 0.421f, 0.427f, 0.157f, 0.0f, 0.509f, 0.425f, 0.43f, 0.17f, 0.0f, 0.513f, 0.429f, 0.433f,
+ 0.181f, 0.0f, 0.517f, 0.431f, 0.433f, 0.192f, 0.0f, 0.52f, 0.433f, 0.434f, 0.201f, 0.0f, 0.522f, 0.433f, 0.435f, 0.208f, 0.0f, 0.524f, 0.433f, 0.435f,
+ 0.213f, 0.0f, 0.524f, 0.432f, 0.436f, 0.216f, 0.0f, 0.523f, 0.431f, 0.435f, 0.217f, 0.0f, 0.521f, 0.43f, 0.426f, 0.215f, 0.0f, 0.518f, 0.429f, 0.427f,
+ 0.213f, 0.0f, 0.515f, 0.428f, 0.427f, 0.208f, 0.0f, 0.511f, 0.428f, 0.427f, 0.203f, 0.0f, 0.506f, 0.428f, 0.427f, 0.196f, 0.0f, 0.502f, 0.428f, 0.427f,
+ 0.189f, 0.0f, 0.497f, 0.428f, 0.427f, 0.181f, 0.0f, 0.492f, 0.428f, 0.427f, 0.173f, 0.0f, 0.487f, 0.428f, 0.428f, 0.163f, 0.0f, 0.482f, 0.429f, 0.428f,
+ 0.154f, 0.0f, 0.477f, 0.429f, 0.429f, 0.145f, 0.0f, 0.472f, 0.43f, 0.43f, 0.135f, 0.0f, 0.467f, 0.431f, 0.431f, 0.125f, 0.0f, 0.462f, 0.432f, 0.43f,
+ 0.116f, 0.0f, 0.457f, 0.433f, 0.431f, 0.106f, 0.0f, 0.453f, 0.435f, 0.434f, 0.096f, 0.0f, 0.448f, 0.436f, 0.436f, 0.086f, 0.0f, 0.444f, 0.437f, 0.438f,
+ 0.076f, 0.0f, 0.44f, 0.438f, 0.44f, 0.065f, 0.0f, 0.436f, 0.439f, 0.441f, 0.055f, 0.0f, 0.433f, 0.44f, 0.441f, 0.044f, 0.0f, 0.431f, 0.441f, 0.442f,
+ 0.033f, 0.0f, 0.429f, 0.441f, 0.442f, 0.022f, 0.0f, 0.427f, 0.441f, 0.442f, 0.011f, 0.0f, 0.426f, 0.442f, 0.443f, -0.0f, 0.0f, 0.426f, 0.442f, 0.442f,
+ -0.011f, 0.0f, 0.426f, 0.442f, 0.442f, -0.022f, 0.0f, 0.427f, 0.442f, 0.442f, -0.033f, 0.0f, 0.429f, 0.442f, 0.442f, -0.042f, 0.0f, 0.432f, 0.441f, 0.442f,
+ -0.052f, 0.0f, 0.435f, 0.441f, 0.441f, -0.061f, 0.0f, 0.439f, 0.441f, 0.441f, -0.07f, 0.0f, 0.443f, 0.441f, 0.441f, -0.078f, 0.0f, 0.448f, 0.441f, 0.441f,
+ -0.087f, 0.0f, 0.453f, 0.441f, 0.442f, -0.095f, 0.0f, 0.458f, 0.441f, 0.441f, -0.104f, 0.0f, 0.463f, 0.44f, 0.44f, -0.113f, 0.0f, 0.468f, 0.44f, 0.44f,
+ -0.122f, 0.0f, 0.473f, 0.44f, 0.44f, -0.132f, 0.0f, 0.479f, 0.44f, 0.44f, -0.143f, 0.0f, 0.485f, 0.44f, 0.44f, -0.154f, 0.0f, 0.491f, 0.44f, 0.44f,
+ -0.165f, 0.0f, 0.498f, 0.44f, 0.44f, -0.176f, 0.0f, 0.504f, 0.439f, 0.439f, -0.187f, 0.0f, 0.51f, 0.435f, 0.44f, -0.198f, 0.0f, 0.516f, 0.424f, 0.44f,
+ -0.209f, 0.0f, 0.522f, 0.393f, 0.44f, -0.219f, 0.0f, 0.527f, 0.324f, 0.44f, -0.228f, 0.0f, 0.532f, 0.222f, 0.404f, -0.241f, 0.0f, 0.538f, 0.037f, 0.037f,
+};
+
+static const float data20[136 * GP_PRIM_DATABUF_SIZE] = {
+ 0.331f, 0.0f, -0.036f, 0.065f, 0.065f, 0.322f, 0.0f, -0.034f, 0.239f, 0.293f, 0.317f, 0.0f, -0.032f, 0.316f, 0.339f, 0.31f, 0.0f, -0.029f, 0.348f, 0.355f,
+ 0.302f, 0.0f, -0.027f, 0.364f, 0.368f, 0.295f, 0.0f, -0.023f, 0.373f, 0.374f, 0.287f, 0.0f, -0.02f, 0.381f, 0.381f, 0.279f, 0.0f, -0.015f, 0.388f, 0.391f,
+ 0.271f, 0.0f, -0.01f, 0.392f, 0.394f, 0.263f, 0.0f, -0.004f, 0.395f, 0.396f, 0.255f, 0.0f, 0.002f, 0.397f, 0.397f, 0.247f, 0.0f, 0.008f, 0.399f, 0.4f,
+ 0.239f, 0.0f, 0.016f, 0.401f, 0.401f, 0.232f, -0.0f, 0.024f, 0.404f, 0.404f, 0.226f, 0.0f, 0.031f, 0.406f, 0.407f, 0.221f, 0.0f, 0.038f, 0.409f, 0.409f,
+ 0.215f, 0.0f, 0.045f, 0.412f, 0.412f, 0.21f, 0.0f, 0.054f, 0.415f, 0.415f, 0.205f, 0.0f, 0.063f, 0.417f, 0.417f, 0.201f, 0.0f, 0.073f, 0.42f, 0.421f,
+ 0.197f, 0.0f, 0.083f, 0.421f, 0.421f, 0.193f, -0.0f, 0.094f, 0.423f, 0.423f, 0.19f, -0.0f, 0.104f, 0.424f, 0.424f, 0.187f, -0.0f, 0.114f, 0.424f, 0.425f,
+ 0.185f, -0.0f, 0.125f, 0.425f, 0.425f, 0.183f, -0.0f, 0.135f, 0.425f, 0.425f, 0.182f, -0.0f, 0.146f, 0.426f, 0.425f, 0.181f, -0.0f, 0.157f, 0.426f, 0.425f,
+ 0.18f, -0.0f, 0.168f, 0.426f, 0.426f, 0.18f, -0.0f, 0.179f, 0.427f, 0.427f, 0.181f, -0.0f, 0.189f, 0.427f, 0.427f, 0.182f, -0.0f, 0.199f, 0.427f, 0.427f,
+ 0.183f, -0.0f, 0.208f, 0.427f, 0.428f, 0.185f, -0.0f, 0.218f, 0.428f, 0.427f, 0.187f, -0.0f, 0.226f, 0.428f, 0.427f, 0.19f, -0.0f, 0.235f, 0.429f, 0.427f,
+ 0.192f, -0.0f, 0.243f, 0.43f, 0.428f, 0.196f, -0.0f, 0.252f, 0.431f, 0.431f, 0.199f, -0.0f, 0.26f, 0.431f, 0.432f, 0.203f, -0.0f, 0.268f, 0.432f, 0.433f,
+ 0.207f, -0.0f, 0.276f, 0.433f, 0.433f, 0.212f, -0.0f, 0.283f, 0.434f, 0.434f, 0.216f, -0.0f, 0.291f, 0.434f, 0.435f, 0.221f, -0.0f, 0.298f, 0.435f, 0.436f,
+ 0.227f, -0.0f, 0.305f, 0.435f, 0.435f, 0.232f, -0.0f, 0.311f, 0.436f, 0.436f, 0.238f, -0.0f, 0.317f, 0.436f, 0.436f, 0.243f, -0.0f, 0.323f, 0.436f, 0.436f,
+ 0.249f, -0.0f, 0.329f, 0.437f, 0.436f, 0.255f, -0.0f, 0.334f, 0.438f, 0.437f, 0.262f, -0.0f, 0.339f, 0.44f, 0.437f, 0.268f, -0.0f, 0.344f, 0.442f, 0.441f,
+ 0.274f, 0.0f, 0.348f, 0.444f, 0.446f, 0.281f, 0.0f, 0.352f, 0.445f, 0.447f, 0.287f, 0.0f, 0.355f, 0.446f, 0.447f, 0.293f, 0.0f, 0.358f, 0.446f, 0.447f,
+ 0.299f, 0.0f, 0.361f, 0.447f, 0.447f, 0.306f, 0.0f, 0.363f, 0.447f, 0.448f, 0.312f, 0.0f, 0.366f, 0.447f, 0.448f, 0.318f, 0.0f, 0.368f, 0.448f, 0.448f,
+ 0.325f, 0.0f, 0.369f, 0.448f, 0.448f, 0.331f, 0.0f, 0.371f, 0.448f, 0.448f, 0.338f, 0.0f, 0.372f, 0.448f, 0.448f, 0.345f, 0.0f, 0.372f, 0.448f, 0.448f,
+ 0.352f, 0.0f, 0.372f, 0.448f, 0.448f, 0.359f, 0.0f, 0.372f, 0.448f, 0.449f, 0.366f, 0.0f, 0.371f, 0.448f, 0.448f, 0.373f, 0.0f, 0.37f, 0.448f, 0.449f,
+ 0.38f, 0.0f, 0.369f, 0.449f, 0.449f, 0.387f, 0.0f, 0.367f, 0.449f, 0.449f, 0.393f, 0.0f, 0.365f, 0.449f, 0.449f, 0.4f, 0.0f, 0.363f, 0.449f, 0.45f,
+ 0.406f, 0.0f, 0.36f, 0.45f, 0.45f, 0.412f, -0.0f, 0.357f, 0.45f, 0.45f, 0.418f, -0.0f, 0.354f, 0.45f, 0.451f, 0.424f, -0.0f, 0.351f, 0.45f, 0.451f,
+ 0.43f, -0.0f, 0.347f, 0.45f, 0.451f, 0.436f, -0.0f, 0.343f, 0.45f, 0.451f, 0.443f, -0.0f, 0.339f, 0.45f, 0.45f, 0.449f, -0.0f, 0.334f, 0.45f, 0.451f,
+ 0.455f, -0.0f, 0.329f, 0.451f, 0.451f, 0.46f, -0.0f, 0.323f, 0.451f, 0.451f, 0.466f, -0.0f, 0.318f, 0.451f, 0.451f, 0.472f, -0.0f, 0.311f, 0.452f, 0.452f,
+ 0.477f, -0.0f, 0.305f, 0.452f, 0.453f, 0.482f, -0.0f, 0.298f, 0.452f, 0.453f, 0.487f, -0.0f, 0.291f, 0.453f, 0.453f, 0.492f, -0.0f, 0.284f, 0.453f, 0.453f,
+ 0.496f, -0.0f, 0.277f, 0.453f, 0.453f, 0.5f, -0.0f, 0.269f, 0.453f, 0.454f, 0.504f, -0.0f, 0.261f, 0.453f, 0.454f, 0.508f, -0.0f, 0.252f, 0.454f, 0.454f,
+ 0.511f, -0.0f, 0.244f, 0.454f, 0.454f, 0.514f, -0.0f, 0.235f, 0.454f, 0.455f, 0.517f, -0.0f, 0.225f, 0.454f, 0.455f, 0.519f, -0.0f, 0.216f, 0.454f, 0.455f,
+ 0.521f, -0.0f, 0.205f, 0.455f, 0.455f, 0.523f, -0.0f, 0.194f, 0.455f, 0.455f, 0.524f, -0.0f, 0.182f, 0.455f, 0.455f, 0.524f, -0.0f, 0.169f, 0.455f, 0.456f,
+ 0.524f, -0.0f, 0.157f, 0.455f, 0.456f, 0.523f, -0.0f, 0.145f, 0.455f, 0.456f, 0.522f, -0.0f, 0.133f, 0.455f, 0.456f, 0.52f, -0.0f, 0.122f, 0.456f, 0.456f,
+ 0.518f, -0.0f, 0.11f, 0.456f, 0.456f, 0.515f, -0.0f, 0.1f, 0.456f, 0.456f, 0.513f, -0.0f, 0.09f, 0.456f, 0.457f, 0.509f, -0.0f, 0.081f, 0.456f, 0.457f,
+ 0.506f, -0.0f, 0.072f, 0.457f, 0.457f, 0.502f, -0.0f, 0.064f, 0.457f, 0.457f, 0.498f, -0.0f, 0.056f, 0.457f, 0.457f, 0.494f, -0.0f, 0.049f, 0.457f, 0.457f,
+ 0.49f, -0.0f, 0.041f, 0.458f, 0.457f, 0.485f, -0.0f, 0.034f, 0.458f, 0.457f, 0.48f, -0.0f, 0.028f, 0.458f, 0.458f, 0.475f, -0.0f, 0.022f, 0.458f, 0.458f,
+ 0.47f, -0.0f, 0.016f, 0.458f, 0.458f, 0.465f, -0.0f, 0.011f, 0.459f, 0.458f, 0.46f, -0.0f, 0.006f, 0.459f, 0.458f, 0.454f, -0.0f, 0.001f, 0.46f, 0.459f,
+ 0.449f, 0.0f, -0.003f, 0.464f, 0.463f, 0.443f, 0.0f, -0.007f, 0.467f, 0.468f, 0.438f, 0.0f, -0.011f, 0.469f, 0.469f, 0.432f, 0.0f, -0.015f, 0.471f, 0.47f,
+ 0.426f, 0.0f, -0.018f, 0.477f, 0.478f, 0.42f, 0.0f, -0.021f, 0.478f, 0.478f, 0.414f, 0.0f, -0.024f, 0.478f, 0.478f, 0.408f, 0.0f, -0.027f, 0.479f, 0.479f,
+ 0.402f, 0.0f, -0.029f, 0.48f, 0.48f, 0.395f, 0.0f, -0.031f, 0.48f, 0.48f, 0.389f, 0.0f, -0.033f, 0.482f, 0.482f, 0.382f, 0.0f, -0.035f, 0.482f, 0.482f,
+ 0.376f, 0.0f, -0.036f, 0.482f, 0.482f, 0.369f, 0.0f, -0.037f, 0.48f, 0.482f, 0.364f, 0.0f, -0.037f, 0.457f, 0.485f, 0.356f, 0.0f, -0.038f, 0.32f, 0.32f,
+};
+
+static const float data21[353 * GP_PRIM_DATABUF_SIZE] = {
+ -0.382f, 0.0f, 0.397f, 0.0f, 1.0f, -0.386f, 0.0f, 0.394f, 0.0f, 1.0f, -0.389f, 0.0f, 0.392f, 0.0f, 1.0f, -0.392f, 0.0f, 0.39f, 0.0f, 1.0f,
+ -0.395f, 0.0f, 0.388f, 0.0f, 1.0f, -0.399f, 0.0f, 0.385f, 0.0f, 1.0f, -0.402f, 0.0f, 0.383f, 0.0f, 1.0f, -0.405f, 0.0f, 0.381f, 0.0f, 1.0f,
+ -0.408f, 0.0f, 0.379f, 0.0f, 1.0f, -0.411f, 0.0f, 0.377f, 0.0f, 1.0f, -0.414f, 0.0f, 0.375f, 0.0f, 1.0f, -0.417f, 0.0f, 0.372f, 0.0f, 1.0f,
+ -0.42f, 0.0f, 0.37f, 0.0f, 1.0f, -0.423f, 0.0f, 0.368f, 0.0f, 1.0f, -0.425f, 0.0f, 0.366f, 0.0f, 1.0f, -0.428f, 0.0f, 0.364f, 0.0f, 1.0f,
+ -0.431f, 0.0f, 0.362f, 0.0f, 1.0f, -0.433f, 0.0f, 0.359f, 0.0f, 1.0f, -0.436f, 0.0f, 0.357f, 0.0f, 1.0f, -0.438f, 0.0f, 0.355f, 0.0f, 1.0f,
+ -0.441f, 0.0f, 0.353f, 0.0f, 1.0f, -0.443f, 0.0f, 0.351f, 0.0f, 1.0f, -0.445f, 0.0f, 0.349f, 0.0f, 1.0f, -0.447f, 0.0f, 0.346f, 0.0f, 1.0f,
+ -0.45f, 0.0f, 0.344f, 0.0f, 1.0f, -0.452f, 0.0f, 0.342f, 0.0f, 1.0f, -0.454f, 0.0f, 0.34f, 0.0f, 1.0f, -0.456f, 0.0f, 0.337f, 0.0f, 1.0f,
+ -0.458f, 0.0f, 0.335f, 0.0f, 1.0f, -0.46f, 0.0f, 0.333f, 0.0f, 1.0f, -0.462f, 0.0f, 0.33f, 0.0f, 1.0f, -0.464f, 0.0f, 0.328f, 0.0f, 1.0f,
+ -0.466f, 0.0f, 0.326f, 0.0f, 1.0f, -0.468f, 0.0f, 0.323f, 0.0f, 1.0f, -0.47f, 0.0f, 0.321f, 0.0f, 1.0f, -0.472f, 0.0f, 0.319f, 0.0f, 1.0f,
+ -0.474f, 0.0f, 0.316f, 0.0f, 1.0f, -0.475f, 0.0f, 0.314f, 0.0f, 1.0f, -0.477f, 0.0f, 0.311f, 0.0f, 1.0f, -0.479f, 0.0f, 0.309f, 0.0f, 1.0f,
+ -0.481f, 0.0f, 0.307f, 0.0f, 1.0f, -0.482f, 0.0f, 0.304f, 0.0f, 1.0f, -0.484f, 0.0f, 0.302f, 0.0f, 1.0f, -0.486f, 0.0f, 0.299f, 0.0f, 1.0f,
+ -0.487f, 0.0f, 0.297f, 0.0f, 1.0f, -0.489f, 0.0f, 0.294f, 0.0f, 1.0f, -0.49f, 0.0f, 0.292f, 0.0f, 1.0f, -0.492f, 0.0f, 0.289f, 0.0f, 1.0f,
+ -0.494f, 0.0f, 0.286f, 0.0f, 1.0f, -0.495f, 0.0f, 0.284f, 0.0f, 1.0f, -0.497f, 0.0f, 0.281f, 0.0f, 1.0f, -0.498f, 0.0f, 0.279f, 0.001f, 1.0f,
+ -0.499f, 0.0f, 0.276f, 0.001f, 1.0f, -0.501f, 0.0f, 0.273f, 0.002f, 1.0f, -0.502f, 0.0f, 0.271f, 0.003f, 1.0f, -0.504f, 0.0f, 0.268f, 0.005f, 1.0f,
+ -0.505f, 0.0f, 0.265f, 0.008f, 1.0f, -0.506f, 0.0f, 0.262f, 0.011f, 1.0f, -0.508f, 0.0f, 0.259f, 0.016f, 1.0f, -0.509f, 0.0f, 0.256f, 0.021f, 1.0f,
+ -0.51f, 0.0f, 0.254f, 0.027f, 1.0f, -0.512f, 0.0f, 0.251f, 0.035f, 1.0f, -0.513f, 0.0f, 0.248f, 0.043f, 1.0f, -0.514f, 0.0f, 0.245f, 0.053f, 1.0f,
+ -0.515f, 0.0f, 0.242f, 0.064f, 1.0f, -0.516f, 0.0f, 0.239f, 0.076f, 1.0f, -0.517f, 0.0f, 0.235f, 0.09f, 1.0f, -0.519f, 0.0f, 0.232f, 0.105f, 1.0f,
+ -0.52f, 0.0f, 0.229f, 0.122f, 1.0f, -0.521f, 0.0f, 0.226f, 0.14f, 1.0f, -0.521f, 0.0f, 0.222f, 0.159f, 1.0f, -0.522f, 0.0f, 0.219f, 0.179f, 1.0f,
+ -0.523f, 0.0f, 0.216f, 0.2f, 1.0f, -0.524f, 0.0f, 0.212f, 0.221f, 1.0f, -0.525f, 0.0f, 0.209f, 0.243f, 1.0f, -0.526f, 0.0f, 0.205f, 0.265f, 1.0f,
+ -0.526f, 0.0f, 0.202f, 0.286f, 1.0f, -0.527f, 0.0f, 0.198f, 0.306f, 1.0f, -0.527f, 0.0f, 0.195f, 0.326f, 1.0f, -0.528f, 0.0f, 0.191f, 0.345f, 1.0f,
+ -0.528f, 0.0f, 0.187f, 0.363f, 1.0f, -0.529f, 0.0f, 0.184f, 0.38f, 1.0f, -0.529f, 0.0f, 0.18f, 0.395f, 1.0f, -0.529f, 0.0f, 0.176f, 0.41f, 1.0f,
+ -0.53f, 0.0f, 0.173f, 0.424f, 1.0f, -0.53f, 0.0f, 0.169f, 0.438f, 1.0f, -0.53f, 0.0f, 0.165f, 0.452f, 1.0f, -0.53f, 0.0f, 0.161f, 0.465f, 1.0f,
+ -0.53f, 0.0f, 0.157f, 0.478f, 1.0f, -0.53f, 0.0f, 0.154f, 0.492f, 1.0f, -0.53f, 0.0f, 0.15f, 0.505f, 1.0f, -0.53f, 0.0f, 0.146f, 0.517f, 1.0f,
+ -0.53f, 0.0f, 0.142f, 0.53f, 1.0f, -0.529f, 0.0f, 0.138f, 0.542f, 1.0f, -0.529f, 0.0f, 0.134f, 0.553f, 1.0f, -0.528f, 0.0f, 0.13f, 0.564f, 1.0f,
+ -0.528f, 0.0f, 0.127f, 0.574f, 1.0f, -0.527f, 0.0f, 0.123f, 0.583f, 1.0f, -0.527f, 0.0f, 0.119f, 0.592f, 1.0f, -0.526f, 0.0f, 0.115f, 0.6f, 1.0f,
+ -0.526f, 0.0f, 0.111f, 0.608f, 1.0f, -0.525f, 0.0f, 0.108f, 0.615f, 1.0f, -0.524f, 0.0f, 0.104f, 0.622f, 1.0f, -0.523f, 0.0f, 0.1f, 0.628f, 1.0f,
+ -0.522f, 0.0f, 0.097f, 0.635f, 1.0f, -0.521f, 0.0f, 0.093f, 0.641f, 1.0f, -0.52f, 0.0f, 0.089f, 0.647f, 1.0f, -0.519f, 0.0f, 0.086f, 0.653f, 1.0f,
+ -0.518f, 0.0f, 0.082f, 0.659f, 1.0f, -0.517f, 0.0f, 0.079f, 0.664f, 1.0f, -0.515f, 0.0f, 0.075f, 0.67f, 1.0f, -0.514f, 0.0f, 0.072f, 0.675f, 1.0f,
+ -0.513f, 0.0f, 0.069f, 0.68f, 1.0f, -0.511f, 0.0f, 0.065f, 0.685f, 1.0f, -0.51f, 0.0f, 0.062f, 0.69f, 1.0f, -0.509f, 0.0f, 0.059f, 0.695f, 1.0f,
+ -0.507f, 0.0f, 0.056f, 0.7f, 1.0f, -0.505f, 0.0f, 0.053f, 0.704f, 1.0f, -0.504f, 0.0f, 0.049f, 0.709f, 1.0f, -0.502f, 0.0f, 0.046f, 0.714f, 1.0f,
+ -0.5f, 0.0f, 0.043f, 0.719f, 1.0f, -0.499f, 0.0f, 0.04f, 0.724f, 1.0f, -0.497f, 0.0f, 0.038f, 0.73f, 1.0f, -0.495f, 0.0f, 0.035f, 0.735f, 1.0f,
+ -0.493f, 0.0f, 0.032f, 0.741f, 1.0f, -0.491f, 0.0f, 0.029f, 0.748f, 1.0f, -0.489f, 0.0f, 0.026f, 0.754f, 1.0f, -0.488f, -0.0f, 0.024f, 0.76f, 1.0f,
+ -0.486f, -0.0f, 0.022f, 0.767f, 1.0f, -0.485f, -0.0f, 0.019f, 0.773f, 1.0f, -0.483f, -0.0f, 0.017f, 0.779f, 1.0f, -0.482f, -0.0f, 0.015f, 0.785f, 1.0f,
+ -0.48f, -0.0f, 0.013f, 0.79f, 1.0f, -0.478f, -0.0f, 0.01f, 0.795f, 1.0f, -0.476f, -0.0f, 0.008f, 0.8f, 1.0f, -0.474f, -0.0f, 0.006f, 0.804f, 1.0f,
+ -0.472f, -0.0f, 0.004f, 0.808f, 1.0f, -0.47f, -0.0f, 0.002f, 0.811f, 1.0f, -0.468f, -0.0f, -0.0f, 0.814f, 1.0f, -0.466f, -0.0f, -0.002f, 0.816f, 1.0f,
+ -0.464f, -0.0f, -0.004f, 0.818f, 1.0f, -0.461f, -0.0f, -0.006f, 0.82f, 1.0f, -0.459f, -0.0f, -0.008f, 0.822f, 1.0f, -0.456f, -0.0f, -0.01f, 0.823f, 1.0f,
+ -0.454f, -0.0f, -0.012f, 0.825f, 1.0f, -0.451f, -0.0f, -0.014f, 0.826f, 1.0f, -0.448f, -0.0f, -0.016f, 0.827f, 1.0f, -0.445f, -0.0f, -0.018f, 0.828f, 1.0f,
+ -0.442f, -0.0f, -0.02f, 0.829f, 1.0f, -0.439f, -0.0f, -0.022f, 0.829f, 1.0f, -0.436f, -0.0f, -0.024f, 0.83f, 1.0f, -0.433f, -0.0f, -0.026f, 0.83f, 1.0f,
+ -0.43f, -0.0f, -0.027f, 0.83f, 1.0f, -0.426f, -0.0f, -0.029f, 0.83f, 1.0f, -0.423f, 0.0f, -0.031f, 0.83f, 1.0f, -0.42f, 0.0f, -0.032f, 0.83f, 1.0f,
+ -0.417f, 0.0f, -0.033f, 0.831f, 1.0f, -0.414f, 0.0f, -0.034f, 0.831f, 1.0f, -0.411f, 0.0f, -0.035f, 0.831f, 1.0f, -0.408f, 0.0f, -0.037f, 0.831f, 1.0f,
+ -0.405f, 0.0f, -0.038f, 0.831f, 1.0f, -0.402f, 0.0f, -0.039f, 0.831f, 1.0f, -0.399f, 0.0f, -0.039f, 0.831f, 1.0f, -0.396f, 0.0f, -0.04f, 0.832f, 1.0f,
+ -0.393f, 0.0f, -0.041f, 0.832f, 1.0f, -0.389f, 0.0f, -0.042f, 0.832f, 1.0f, -0.386f, 0.0f, -0.043f, 0.832f, 1.0f, -0.383f, 0.0f, -0.044f, 0.832f, 1.0f,
+ -0.379f, 0.0f, -0.044f, 0.832f, 1.0f, -0.376f, 0.0f, -0.045f, 0.832f, 1.0f, -0.372f, 0.0f, -0.045f, 0.832f, 1.0f, -0.369f, 0.0f, -0.046f, 0.832f, 1.0f,
+ -0.366f, 0.0f, -0.047f, 0.832f, 1.0f, -0.362f, 0.0f, -0.047f, 0.832f, 1.0f, -0.359f, 0.0f, -0.047f, 0.831f, 1.0f, -0.355f, 0.0f, -0.048f, 0.831f, 1.0f,
+ -0.352f, 0.0f, -0.048f, 0.83f, 1.0f, -0.348f, 0.0f, -0.048f, 0.83f, 1.0f, -0.345f, 0.0f, -0.049f, 0.829f, 1.0f, -0.341f, 0.0f, -0.049f, 0.828f, 1.0f,
+ -0.338f, 0.0f, -0.049f, 0.827f, 1.0f, -0.334f, 0.0f, -0.049f, 0.826f, 1.0f, -0.331f, 0.0f, -0.049f, 0.823f, 1.0f, -0.327f, 0.0f, -0.049f, 0.82f, 1.0f,
+ -0.323f, 0.0f, -0.048f, 0.816f, 1.0f, -0.32f, 0.0f, -0.048f, 0.811f, 1.0f, -0.316f, 0.0f, -0.048f, 0.804f, 1.0f, -0.313f, 0.0f, -0.048f, 0.797f, 1.0f,
+ -0.309f, 0.0f, -0.047f, 0.79f, 1.0f, -0.306f, 0.0f, -0.047f, 0.782f, 1.0f, -0.302f, 0.0f, -0.046f, 0.774f, 1.0f, -0.299f, 0.0f, -0.045f, 0.767f, 1.0f,
+ -0.295f, 0.0f, -0.044f, 0.76f, 1.0f, -0.292f, 0.0f, -0.044f, 0.753f, 1.0f, -0.288f, 0.0f, -0.043f, 0.748f, 1.0f, -0.285f, 0.0f, -0.042f, 0.742f, 1.0f,
+ -0.282f, 0.0f, -0.041f, 0.738f, 1.0f, -0.278f, 0.0f, -0.04f, 0.734f, 1.0f, -0.275f, 0.0f, -0.039f, 0.73f, 1.0f, -0.272f, 0.0f, -0.037f, 0.726f, 1.0f,
+ -0.269f, 0.0f, -0.036f, 0.723f, 1.0f, -0.266f, 0.0f, -0.035f, 0.72f, 1.0f, -0.263f, 0.0f, -0.034f, 0.717f, 1.0f, -0.26f, 0.0f, -0.032f, 0.713f, 1.0f,
+ -0.257f, 0.0f, -0.031f, 0.71f, 1.0f, -0.255f, 0.0f, -0.029f, 0.706f, 1.0f, -0.252f, 0.0f, -0.028f, 0.702f, 1.0f, -0.249f, 0.0f, -0.026f, 0.698f, 1.0f,
+ -0.247f, 0.0f, -0.025f, 0.693f, 1.0f, -0.244f, 0.0f, -0.023f, 0.688f, 1.0f, -0.242f, 0.0f, -0.021f, 0.684f, 1.0f, -0.239f, 0.0f, -0.02f, 0.679f, 1.0f,
+ -0.237f, 0.0f, -0.018f, 0.675f, 1.0f, -0.234f, 0.0f, -0.016f, 0.671f, 1.0f, -0.232f, 0.0f, -0.014f, 0.667f, 1.0f, -0.23f, 0.0f, -0.013f, 0.663f, 1.0f,
+ -0.228f, 0.0f, -0.011f, 0.66f, 1.0f, -0.225f, 0.0f, -0.009f, 0.657f, 1.0f, -0.223f, 0.0f, -0.007f, 0.654f, 1.0f, -0.221f, 0.0f, -0.005f, 0.651f, 1.0f,
+ -0.219f, 0.0f, -0.003f, 0.649f, 1.0f, -0.217f, 0.0f, -0.001f, 0.645f, 1.0f, -0.215f, 0.0f, 0.002f, 0.642f, 1.0f, -0.213f, 0.0f, 0.004f, 0.639f, 1.0f,
+ -0.211f, 0.0f, 0.006f, 0.635f, 1.0f, -0.209f, 0.0f, 0.008f, 0.631f, 1.0f, -0.207f, 0.0f, 0.011f, 0.627f, 1.0f, -0.206f, 0.0f, 0.013f, 0.623f, 1.0f,
+ -0.204f, 0.0f, 0.016f, 0.619f, 1.0f, -0.202f, 0.0f, 0.018f, 0.615f, 1.0f, -0.2f, 0.0f, 0.021f, 0.61f, 1.0f, -0.199f, 0.0f, 0.023f, 0.606f, 1.0f,
+ -0.197f, 0.0f, 0.026f, 0.602f, 1.0f, -0.195f, 0.0f, 0.029f, 0.598f, 1.0f, -0.194f, 0.0f, 0.032f, 0.595f, 1.0f, -0.192f, 0.0f, 0.034f, 0.592f, 1.0f,
+ -0.191f, 0.0f, 0.037f, 0.589f, 1.0f, -0.19f, 0.0f, 0.04f, 0.587f, 1.0f, -0.188f, 0.0f, 0.043f, 0.585f, 1.0f, -0.187f, 0.0f, 0.046f, 0.584f, 1.0f,
+ -0.186f, 0.0f, 0.05f, 0.583f, 1.0f, -0.185f, 0.0f, 0.053f, 0.582f, 1.0f, -0.183f, 0.0f, 0.056f, 0.581f, 1.0f, -0.182f, 0.0f, 0.059f, 0.581f, 1.0f,
+ -0.181f, 0.0f, 0.062f, 0.581f, 1.0f, -0.18f, 0.0f, 0.066f, 0.581f, 1.0f, -0.179f, 0.0f, 0.069f, 0.58f, 1.0f, -0.178f, 0.0f, 0.072f, 0.58f, 1.0f,
+ -0.177f, 0.0f, 0.076f, 0.58f, 1.0f, -0.177f, 0.0f, 0.079f, 0.58f, 1.0f, -0.176f, 0.0f, 0.083f, 0.58f, 1.0f, -0.175f, 0.0f, 0.086f, 0.58f, 1.0f,
+ -0.174f, 0.0f, 0.09f, 0.58f, 1.0f, -0.174f, 0.0f, 0.093f, 0.58f, 1.0f, -0.173f, 0.0f, 0.097f, 0.58f, 1.0f, -0.172f, 0.0f, 0.1f, 0.58f, 1.0f,
+ -0.172f, 0.0f, 0.104f, 0.58f, 1.0f, -0.171f, 0.0f, 0.108f, 0.579f, 1.0f, -0.171f, 0.0f, 0.111f, 0.579f, 1.0f, -0.17f, 0.0f, 0.115f, 0.578f, 1.0f,
+ -0.17f, 0.0f, 0.119f, 0.578f, 1.0f, -0.17f, 0.0f, 0.122f, 0.577f, 1.0f, -0.169f, 0.0f, 0.126f, 0.577f, 1.0f, -0.169f, 0.0f, 0.13f, 0.576f, 1.0f,
+ -0.169f, 0.0f, 0.134f, 0.576f, 1.0f, -0.169f, 0.0f, 0.137f, 0.575f, 1.0f, -0.169f, 0.0f, 0.141f, 0.575f, 1.0f, -0.169f, 0.0f, 0.145f, 0.574f, 1.0f,
+ -0.169f, 0.0f, 0.149f, 0.572f, 1.0f, -0.169f, 0.0f, 0.153f, 0.571f, 1.0f, -0.169f, 0.0f, 0.157f, 0.569f, 1.0f, -0.169f, 0.0f, 0.16f, 0.566f, 1.0f,
+ -0.169f, 0.0f, 0.164f, 0.562f, 1.0f, -0.17f, 0.0f, 0.168f, 0.558f, 1.0f, -0.17f, 0.0f, 0.172f, 0.553f, 1.0f, -0.17f, 0.0f, 0.176f, 0.547f, 1.0f,
+ -0.171f, 0.0f, 0.18f, 0.539f, 1.0f, -0.171f, 0.0f, 0.183f, 0.531f, 1.0f, -0.172f, 0.0f, 0.187f, 0.522f, 1.0f, -0.172f, 0.0f, 0.191f, 0.513f, 1.0f,
+ -0.173f, 0.0f, 0.194f, 0.503f, 1.0f, -0.173f, 0.0f, 0.198f, 0.493f, 1.0f, -0.174f, 0.0f, 0.202f, 0.483f, 1.0f, -0.175f, 0.0f, 0.205f, 0.473f, 1.0f,
+ -0.176f, 0.0f, 0.209f, 0.464f, 1.0f, -0.177f, 0.0f, 0.212f, 0.455f, 1.0f, -0.178f, 0.0f, 0.215f, 0.446f, 1.0f, -0.178f, 0.0f, 0.219f, 0.438f, 1.0f,
+ -0.179f, 0.0f, 0.222f, 0.428f, 1.0f, -0.18f, 0.0f, 0.226f, 0.418f, 1.0f, -0.182f, 0.0f, 0.229f, 0.407f, 1.0f, -0.183f, 0.0f, 0.232f, 0.394f, 1.0f,
+ -0.184f, 0.0f, 0.236f, 0.38f, 1.0f, -0.185f, 0.0f, 0.239f, 0.364f, 1.0f, -0.186f, 0.0f, 0.242f, 0.348f, 1.0f, -0.187f, 0.0f, 0.245f, 0.33f, 1.0f,
+ -0.188f, 0.0f, 0.249f, 0.311f, 1.0f, -0.19f, 0.0f, 0.252f, 0.293f, 1.0f, -0.191f, 0.0f, 0.255f, 0.275f, 1.0f, -0.192f, 0.0f, 0.258f, 0.258f, 1.0f,
+ -0.194f, 0.0f, 0.261f, 0.242f, 1.0f, -0.195f, 0.0f, 0.264f, 0.228f, 1.0f, -0.196f, 0.0f, 0.267f, 0.214f, 1.0f, -0.198f, 0.0f, 0.27f, 0.202f, 1.0f,
+ -0.199f, 0.0f, 0.273f, 0.191f, 1.0f, -0.201f, 0.0f, 0.276f, 0.181f, 1.0f, -0.202f, 0.0f, 0.279f, 0.171f, 1.0f, -0.204f, 0.0f, 0.282f, 0.162f, 1.0f,
+ -0.205f, 0.0f, 0.285f, 0.152f, 1.0f, -0.206f, 0.0f, 0.287f, 0.143f, 1.0f, -0.208f, 0.0f, 0.29f, 0.134f, 1.0f, -0.21f, 0.0f, 0.293f, 0.126f, 1.0f,
+ -0.211f, 0.0f, 0.295f, 0.117f, 1.0f, -0.213f, 0.0f, 0.298f, 0.109f, 1.0f, -0.214f, 0.0f, 0.301f, 0.101f, 1.0f, -0.216f, 0.0f, 0.303f, 0.094f, 1.0f,
+ -0.217f, 0.0f, 0.306f, 0.087f, 1.0f, -0.219f, 0.0f, 0.308f, 0.081f, 1.0f, -0.221f, 0.0f, 0.311f, 0.076f, 1.0f, -0.223f, 0.0f, 0.313f, 0.071f, 1.0f,
+ -0.224f, 0.0f, 0.316f, 0.067f, 1.0f, -0.226f, 0.0f, 0.318f, 0.065f, 1.0f, -0.228f, 0.0f, 0.321f, 0.062f, 1.0f, -0.23f, 0.0f, 0.323f, 0.061f, 1.0f,
+ -0.232f, 0.0f, 0.326f, 0.06f, 1.0f, -0.233f, 0.0f, 0.328f, 0.06f, 1.0f, -0.235f, 0.0f, 0.331f, 0.061f, 1.0f, -0.237f, 0.0f, 0.334f, 0.061f, 1.0f,
+ -0.239f, 0.0f, 0.336f, 0.062f, 1.0f, -0.241f, 0.0f, 0.339f, 0.063f, 1.0f, -0.243f, 0.0f, 0.341f, 0.064f, 1.0f, -0.245f, 0.0f, 0.344f, 0.065f, 1.0f,
+ -0.248f, 0.0f, 0.346f, 0.065f, 1.0f, -0.25f, 0.0f, 0.349f, 0.065f, 1.0f, -0.252f, 0.0f, 0.351f, 0.064f, 1.0f, -0.254f, 0.0f, 0.354f, 0.062f, 1.0f,
+ -0.256f, 0.0f, 0.356f, 0.06f, 1.0f, -0.258f, 0.0f, 0.359f, 0.058f, 1.0f, -0.261f, 0.0f, 0.361f, 0.055f, 1.0f, -0.263f, 0.0f, 0.364f, 0.051f, 1.0f,
+ -0.265f, 0.0f, 0.366f, 0.046f, 1.0f, -0.267f, 0.0f, 0.368f, 0.04f, 1.0f, -0.269f, 0.0f, 0.37f, 0.034f, 1.0f, -0.272f, 0.0f, 0.373f, 0.027f, 1.0f,
+ -0.274f, 0.0f, 0.375f, 0.019f, 1.0f, -0.276f, 0.0f, 0.377f, 0.012f, 1.0f, -0.278f, 0.0f, 0.379f, 0.007f, 1.0f, -0.28f, 0.0f, 0.381f, 0.003f, 1.0f,
+ -0.282f, 0.0f, 0.383f, 0.001f, 1.0f, -0.284f, 0.0f, 0.385f, 0.0f, 1.0f, -0.286f, 0.0f, 0.387f, 0.0f, 1.0f, -0.287f, 0.0f, 0.388f, 0.0f, 1.0f,
+ -0.289f, 0.0f, 0.39f, 0.0f, 1.0f,
+};
+
+static const float data22[309 * GP_PRIM_DATABUF_SIZE] = {
+ 0.294f, 0.0f, 0.372f, 0.0f, 1.0f, 0.291f, 0.0f, 0.37f, 0.001f, 1.0f, 0.289f, 0.0f, 0.368f, 0.002f, 1.0f, 0.286f, 0.0f, 0.366f, 0.003f, 1.0f,
+ 0.284f, 0.0f, 0.364f, 0.006f, 1.0f, 0.282f, 0.0f, 0.362f, 0.01f, 1.0f, 0.279f, 0.0f, 0.36f, 0.015f, 1.0f, 0.277f, 0.0f, 0.358f, 0.022f, 1.0f,
+ 0.274f, 0.0f, 0.356f, 0.03f, 1.0f, 0.272f, 0.0f, 0.353f, 0.04f, 1.0f, 0.269f, 0.0f, 0.351f, 0.051f, 1.0f, 0.267f, 0.0f, 0.349f, 0.062f, 1.0f,
+ 0.265f, 0.0f, 0.347f, 0.074f, 1.0f, 0.262f, 0.0f, 0.344f, 0.086f, 1.0f, 0.26f, 0.0f, 0.342f, 0.097f, 1.0f, 0.258f, 0.0f, 0.34f, 0.108f, 1.0f,
+ 0.256f, 0.0f, 0.337f, 0.119f, 1.0f, 0.253f, 0.0f, 0.335f, 0.128f, 1.0f, 0.251f, 0.0f, 0.333f, 0.137f, 1.0f, 0.249f, 0.0f, 0.33f, 0.145f, 1.0f,
+ 0.247f, 0.0f, 0.328f, 0.153f, 1.0f, 0.246f, 0.0f, 0.325f, 0.161f, 1.0f, 0.244f, 0.0f, 0.323f, 0.168f, 1.0f, 0.242f, 0.0f, 0.321f, 0.176f, 1.0f,
+ 0.24f, 0.0f, 0.318f, 0.183f, 1.0f, 0.239f, 0.0f, 0.316f, 0.191f, 1.0f, 0.237f, 0.0f, 0.314f, 0.198f, 1.0f, 0.235f, 0.0f, 0.311f, 0.206f, 1.0f,
+ 0.233f, 0.0f, 0.309f, 0.214f, 1.0f, 0.231f, 0.0f, 0.306f, 0.223f, 1.0f, 0.23f, 0.0f, 0.304f, 0.231f, 1.0f, 0.228f, 0.0f, 0.301f, 0.24f, 1.0f,
+ 0.226f, 0.0f, 0.299f, 0.248f, 1.0f, 0.224f, 0.0f, 0.296f, 0.256f, 1.0f, 0.223f, 0.0f, 0.294f, 0.264f, 1.0f, 0.221f, 0.0f, 0.291f, 0.272f, 1.0f,
+ 0.219f, 0.0f, 0.288f, 0.28f, 1.0f, 0.218f, 0.0f, 0.286f, 0.287f, 1.0f, 0.216f, 0.0f, 0.283f, 0.294f, 1.0f, 0.214f, 0.0f, 0.281f, 0.301f, 1.0f,
+ 0.213f, 0.0f, 0.278f, 0.307f, 1.0f, 0.211f, 0.0f, 0.275f, 0.314f, 1.0f, 0.21f, 0.0f, 0.273f, 0.32f, 1.0f, 0.208f, 0.0f, 0.27f, 0.327f, 1.0f,
+ 0.206f, 0.0f, 0.267f, 0.333f, 1.0f, 0.205f, 0.0f, 0.265f, 0.339f, 1.0f, 0.204f, 0.0f, 0.262f, 0.345f, 1.0f, 0.202f, 0.0f, 0.259f, 0.351f, 1.0f,
+ 0.201f, 0.0f, 0.256f, 0.357f, 1.0f, 0.199f, 0.0f, 0.253f, 0.362f, 1.0f, 0.198f, 0.0f, 0.25f, 0.368f, 1.0f, 0.197f, 0.0f, 0.247f, 0.373f, 1.0f,
+ 0.195f, 0.0f, 0.244f, 0.379f, 1.0f, 0.194f, 0.0f, 0.241f, 0.383f, 1.0f, 0.193f, 0.0f, 0.238f, 0.388f, 1.0f, 0.192f, 0.0f, 0.235f, 0.392f, 1.0f,
+ 0.191f, 0.0f, 0.232f, 0.396f, 1.0f, 0.19f, 0.0f, 0.229f, 0.399f, 1.0f, 0.189f, 0.0f, 0.226f, 0.402f, 1.0f, 0.188f, 0.0f, 0.222f, 0.405f, 1.0f,
+ 0.187f, 0.0f, 0.219f, 0.407f, 1.0f, 0.186f, 0.0f, 0.216f, 0.409f, 1.0f, 0.185f, 0.0f, 0.213f, 0.411f, 1.0f, 0.184f, 0.0f, 0.209f, 0.412f, 1.0f,
+ 0.183f, 0.0f, 0.206f, 0.413f, 1.0f, 0.183f, 0.0f, 0.203f, 0.414f, 1.0f, 0.182f, 0.0f, 0.199f, 0.415f, 1.0f, 0.181f, 0.0f, 0.196f, 0.416f, 1.0f,
+ 0.181f, 0.0f, 0.193f, 0.417f, 1.0f, 0.18f, 0.0f, 0.189f, 0.417f, 1.0f, 0.18f, 0.0f, 0.186f, 0.418f, 1.0f, 0.179f, 0.0f, 0.182f, 0.419f, 1.0f,
+ 0.179f, 0.0f, 0.179f, 0.421f, 1.0f, 0.179f, 0.0f, 0.176f, 0.422f, 1.0f, 0.178f, 0.0f, 0.172f, 0.423f, 1.0f, 0.178f, 0.0f, 0.169f, 0.425f, 1.0f,
+ 0.178f, 0.0f, 0.165f, 0.427f, 1.0f, 0.178f, 0.0f, 0.162f, 0.429f, 1.0f, 0.178f, 0.0f, 0.158f, 0.431f, 1.0f, 0.178f, 0.0f, 0.155f, 0.434f, 1.0f,
+ 0.178f, 0.0f, 0.152f, 0.436f, 1.0f, 0.178f, 0.0f, 0.148f, 0.439f, 1.0f, 0.178f, 0.0f, 0.145f, 0.442f, 1.0f, 0.178f, 0.0f, 0.141f, 0.446f, 1.0f,
+ 0.178f, 0.0f, 0.138f, 0.449f, 1.0f, 0.178f, 0.0f, 0.134f, 0.453f, 1.0f, 0.178f, 0.0f, 0.131f, 0.458f, 1.0f, 0.179f, 0.0f, 0.127f, 0.462f, 1.0f,
+ 0.179f, 0.0f, 0.124f, 0.467f, 1.0f, 0.179f, 0.0f, 0.12f, 0.472f, 1.0f, 0.18f, 0.0f, 0.117f, 0.478f, 1.0f, 0.18f, 0.0f, 0.113f, 0.483f, 1.0f,
+ 0.181f, 0.0f, 0.11f, 0.489f, 1.0f, 0.182f, 0.0f, 0.106f, 0.494f, 1.0f, 0.182f, 0.0f, 0.103f, 0.5f, 1.0f, 0.183f, 0.0f, 0.099f, 0.505f, 1.0f,
+ 0.184f, 0.0f, 0.096f, 0.511f, 1.0f, 0.185f, 0.0f, 0.092f, 0.516f, 1.0f, 0.185f, 0.0f, 0.089f, 0.521f, 1.0f, 0.186f, 0.0f, 0.086f, 0.525f, 1.0f,
+ 0.187f, 0.0f, 0.082f, 0.53f, 1.0f, 0.188f, 0.0f, 0.079f, 0.534f, 1.0f, 0.189f, 0.0f, 0.076f, 0.537f, 1.0f, 0.191f, 0.0f, 0.073f, 0.541f, 1.0f,
+ 0.192f, 0.0f, 0.069f, 0.544f, 1.0f, 0.193f, 0.0f, 0.066f, 0.547f, 1.0f, 0.194f, 0.0f, 0.063f, 0.55f, 1.0f, 0.196f, 0.0f, 0.061f, 0.553f, 1.0f,
+ 0.197f, 0.0f, 0.058f, 0.556f, 1.0f, 0.198f, 0.0f, 0.055f, 0.559f, 1.0f, 0.2f, 0.0f, 0.052f, 0.562f, 1.0f, 0.201f, 0.0f, 0.049f, 0.564f, 1.0f,
+ 0.203f, 0.0f, 0.047f, 0.566f, 1.0f, 0.205f, 0.0f, 0.044f, 0.569f, 1.0f, 0.206f, 0.0f, 0.042f, 0.571f, 1.0f, 0.208f, 0.0f, 0.039f, 0.573f, 1.0f,
+ 0.21f, 0.0f, 0.037f, 0.575f, 1.0f, 0.212f, 0.0f, 0.035f, 0.576f, 1.0f, 0.214f, 0.0f, 0.032f, 0.578f, 1.0f, 0.215f, 0.0f, 0.03f, 0.579f, 1.0f,
+ 0.217f, 0.0f, 0.028f, 0.581f, 1.0f, 0.22f, 0.0f, 0.025f, 0.582f, 1.0f, 0.222f, 0.0f, 0.023f, 0.583f, 1.0f, 0.224f, 0.0f, 0.021f, 0.585f, 1.0f,
+ 0.226f, 0.0f, 0.019f, 0.587f, 1.0f, 0.228f, 0.0f, 0.016f, 0.589f, 1.0f, 0.231f, 0.0f, 0.014f, 0.592f, 1.0f, 0.233f, 0.0f, 0.012f, 0.596f, 1.0f,
+ 0.236f, 0.0f, 0.01f, 0.599f, 1.0f, 0.238f, 0.0f, 0.008f, 0.604f, 1.0f, 0.241f, 0.0f, 0.006f, 0.608f, 1.0f, 0.243f, 0.0f, 0.004f, 0.612f, 1.0f,
+ 0.246f, 0.0f, 0.002f, 0.615f, 1.0f, 0.249f, 0.0f, 0.0f, 0.619f, 1.0f, 0.251f, 0.0f, -0.002f, 0.622f, 1.0f, 0.254f, 0.0f, -0.003f, 0.624f, 1.0f,
+ 0.257f, 0.0f, -0.005f, 0.626f, 1.0f, 0.26f, 0.0f, -0.007f, 0.628f, 1.0f, 0.263f, 0.0f, -0.008f, 0.63f, 1.0f, 0.266f, 0.0f, -0.01f, 0.632f, 1.0f,
+ 0.269f, 0.0f, -0.011f, 0.634f, 1.0f, 0.272f, 0.0f, -0.013f, 0.636f, 1.0f, 0.275f, 0.0f, -0.014f, 0.638f, 1.0f, 0.278f, 0.0f, -0.015f, 0.64f, 1.0f,
+ 0.281f, 0.0f, -0.017f, 0.642f, 1.0f, 0.284f, 0.0f, -0.018f, 0.644f, 1.0f, 0.288f, 0.0f, -0.019f, 0.647f, 1.0f, 0.291f, 0.0f, -0.02f, 0.649f, 1.0f,
+ 0.294f, 0.0f, -0.021f, 0.651f, 1.0f, 0.297f, 0.0f, -0.022f, 0.653f, 1.0f, 0.301f, 0.0f, -0.023f, 0.656f, 1.0f, 0.304f, 0.0f, -0.024f, 0.658f, 1.0f,
+ 0.307f, 0.0f, -0.025f, 0.659f, 1.0f, 0.31f, 0.0f, -0.026f, 0.661f, 1.0f, 0.314f, 0.0f, -0.027f, 0.662f, 1.0f, 0.317f, 0.0f, -0.027f, 0.664f, 1.0f,
+ 0.32f, 0.0f, -0.028f, 0.665f, 1.0f, 0.324f, 0.0f, -0.028f, 0.665f, 1.0f, 0.327f, 0.0f, -0.029f, 0.666f, 1.0f, 0.33f, 0.0f, -0.029f, 0.666f, 1.0f,
+ 0.334f, 0.0f, -0.029f, 0.667f, 1.0f, 0.337f, 0.0f, -0.03f, 0.667f, 1.0f, 0.341f, 0.0f, -0.03f, 0.668f, 1.0f, 0.344f, 0.0f, -0.03f, 0.668f, 1.0f,
+ 0.348f, 0.0f, -0.03f, 0.668f, 1.0f, 0.351f, 0.0f, -0.03f, 0.668f, 1.0f, 0.354f, 0.0f, -0.03f, 0.668f, 1.0f, 0.358f, 0.0f, -0.029f, 0.668f, 1.0f,
+ 0.361f, 0.0f, -0.029f, 0.668f, 1.0f, 0.365f, 0.0f, -0.029f, 0.668f, 1.0f, 0.368f, 0.0f, -0.028f, 0.668f, 1.0f, 0.372f, 0.0f, -0.028f, 0.668f, 1.0f,
+ 0.375f, 0.0f, -0.027f, 0.668f, 1.0f, 0.378f, 0.0f, -0.027f, 0.668f, 1.0f, 0.382f, 0.0f, -0.026f, 0.667f, 1.0f, 0.385f, 0.0f, -0.025f, 0.667f, 1.0f,
+ 0.388f, 0.0f, -0.025f, 0.666f, 1.0f, 0.392f, 0.0f, -0.024f, 0.666f, 1.0f, 0.395f, 0.0f, -0.023f, 0.665f, 1.0f, 0.398f, 0.0f, -0.022f, 0.664f, 1.0f,
+ 0.401f, 0.0f, -0.021f, 0.664f, 1.0f, 0.405f, 0.0f, -0.02f, 0.663f, 1.0f, 0.408f, 0.0f, -0.019f, 0.663f, 1.0f, 0.411f, 0.0f, -0.018f, 0.662f, 1.0f,
+ 0.414f, 0.0f, -0.017f, 0.662f, 1.0f, 0.417f, 0.0f, -0.016f, 0.662f, 1.0f, 0.42f, 0.0f, -0.015f, 0.662f, 1.0f, 0.423f, 0.0f, -0.014f, 0.661f, 1.0f,
+ 0.426f, 0.0f, -0.012f, 0.661f, 1.0f, 0.429f, 0.0f, -0.011f, 0.661f, 1.0f, 0.432f, 0.0f, -0.01f, 0.661f, 1.0f, 0.434f, 0.0f, -0.009f, 0.66f, 1.0f,
+ 0.437f, 0.0f, -0.007f, 0.66f, 1.0f, 0.44f, 0.0f, -0.006f, 0.659f, 1.0f, 0.442f, 0.0f, -0.005f, 0.659f, 1.0f, 0.445f, 0.0f, -0.003f, 0.658f, 1.0f,
+ 0.448f, 0.0f, -0.002f, 0.658f, 1.0f, 0.45f, 0.0f, -0.001f, 0.657f, 1.0f, 0.452f, 0.0f, 0.001f, 0.656f, 1.0f, 0.455f, 0.0f, 0.002f, 0.655f, 1.0f,
+ 0.457f, 0.0f, 0.004f, 0.654f, 1.0f, 0.459f, 0.0f, 0.005f, 0.653f, 1.0f, 0.462f, 0.0f, 0.007f, 0.652f, 1.0f, 0.464f, 0.0f, 0.009f, 0.651f, 1.0f,
+ 0.466f, 0.0f, 0.01f, 0.65f, 1.0f, 0.468f, 0.0f, 0.012f, 0.65f, 1.0f, 0.47f, 0.0f, 0.014f, 0.649f, 1.0f, 0.472f, 0.0f, 0.016f, 0.648f, 1.0f,
+ 0.474f, 0.0f, 0.018f, 0.647f, 1.0f, 0.476f, 0.0f, 0.019f, 0.646f, 1.0f, 0.478f, 0.0f, 0.021f, 0.645f, 1.0f, 0.479f, 0.0f, 0.023f, 0.644f, 1.0f,
+ 0.481f, 0.0f, 0.025f, 0.643f, 1.0f, 0.483f, 0.0f, 0.027f, 0.642f, 1.0f, 0.485f, 0.0f, 0.03f, 0.642f, 1.0f, 0.486f, 0.0f, 0.032f, 0.641f, 1.0f,
+ 0.488f, 0.0f, 0.034f, 0.64f, 1.0f, 0.49f, 0.0f, 0.036f, 0.639f, 1.0f, 0.491f, 0.0f, 0.038f, 0.638f, 1.0f, 0.493f, 0.0f, 0.041f, 0.637f, 1.0f,
+ 0.494f, 0.0f, 0.043f, 0.636f, 1.0f, 0.496f, 0.0f, 0.045f, 0.635f, 1.0f, 0.497f, 0.0f, 0.048f, 0.635f, 1.0f, 0.499f, 0.0f, 0.05f, 0.634f, 1.0f,
+ 0.5f, 0.0f, 0.053f, 0.633f, 1.0f, 0.502f, 0.0f, 0.055f, 0.632f, 1.0f, 0.503f, 0.0f, 0.058f, 0.631f, 1.0f, 0.505f, 0.0f, 0.06f, 0.63f, 1.0f,
+ 0.506f, 0.0f, 0.063f, 0.63f, 1.0f, 0.507f, 0.0f, 0.066f, 0.629f, 1.0f, 0.509f, 0.0f, 0.068f, 0.628f, 1.0f, 0.51f, 0.0f, 0.071f, 0.628f, 1.0f,
+ 0.511f, 0.0f, 0.074f, 0.627f, 1.0f, 0.513f, 0.0f, 0.077f, 0.626f, 1.0f, 0.514f, 0.0f, 0.079f, 0.625f, 1.0f, 0.515f, 0.0f, 0.082f, 0.625f, 1.0f,
+ 0.516f, 0.0f, 0.085f, 0.624f, 1.0f, 0.518f, 0.0f, 0.088f, 0.623f, 1.0f, 0.519f, 0.0f, 0.091f, 0.622f, 1.0f, 0.52f, 0.0f, 0.094f, 0.62f, 1.0f,
+ 0.521f, 0.0f, 0.098f, 0.619f, 1.0f, 0.522f, 0.0f, 0.101f, 0.617f, 1.0f, 0.523f, 0.0f, 0.104f, 0.615f, 1.0f, 0.524f, 0.0f, 0.107f, 0.613f, 1.0f,
+ 0.525f, 0.0f, 0.111f, 0.611f, 1.0f, 0.526f, 0.0f, 0.114f, 0.609f, 1.0f, 0.527f, 0.0f, 0.118f, 0.607f, 1.0f, 0.527f, 0.0f, 0.121f, 0.605f, 1.0f,
+ 0.528f, 0.0f, 0.124f, 0.603f, 1.0f, 0.529f, 0.0f, 0.128f, 0.602f, 1.0f, 0.529f, 0.0f, 0.132f, 0.6f, 1.0f, 0.53f, 0.0f, 0.135f, 0.599f, 1.0f,
+ 0.531f, 0.0f, 0.139f, 0.598f, 1.0f, 0.531f, 0.0f, 0.142f, 0.598f, 1.0f, 0.531f, 0.0f, 0.146f, 0.597f, 1.0f, 0.532f, 0.0f, 0.15f, 0.596f, 1.0f,
+ 0.532f, 0.0f, 0.154f, 0.596f, 1.0f, 0.532f, 0.0f, 0.157f, 0.595f, 1.0f, 0.532f, 0.0f, 0.161f, 0.595f, 1.0f, 0.532f, 0.0f, 0.165f, 0.594f, 1.0f,
+ 0.532f, 0.0f, 0.169f, 0.593f, 1.0f, 0.532f, 0.0f, 0.173f, 0.592f, 1.0f, 0.532f, 0.0f, 0.177f, 0.591f, 1.0f, 0.532f, 0.0f, 0.181f, 0.59f, 1.0f,
+ 0.531f, 0.0f, 0.185f, 0.589f, 1.0f, 0.531f, 0.0f, 0.189f, 0.588f, 1.0f, 0.53f, 0.0f, 0.194f, 0.587f, 1.0f, 0.529f, 0.0f, 0.198f, 0.586f, 1.0f,
+ 0.528f, 0.0f, 0.202f, 0.585f, 1.0f, 0.527f, 0.0f, 0.207f, 0.584f, 1.0f, 0.526f, 0.0f, 0.211f, 0.584f, 1.0f, 0.525f, 0.0f, 0.215f, 0.583f, 1.0f,
+ 0.523f, 0.0f, 0.22f, 0.583f, 1.0f, 0.522f, 0.0f, 0.224f, 0.583f, 1.0f, 0.52f, 0.0f, 0.229f, 0.582f, 1.0f, 0.518f, 0.0f, 0.234f, 0.582f, 1.0f,
+ 0.515f, 0.0f, 0.238f, 0.582f, 1.0f, 0.513f, 0.0f, 0.243f, 0.581f, 1.0f, 0.51f, 0.0f, 0.247f, 0.58f, 1.0f, 0.508f, 0.0f, 0.252f, 0.579f, 1.0f,
+ 0.505f, 0.0f, 0.257f, 0.578f, 1.0f, 0.502f, 0.0f, 0.261f, 0.576f, 1.0f, 0.499f, 0.0f, 0.266f, 0.573f, 1.0f, 0.496f, 0.0f, 0.27f, 0.57f, 1.0f,
+ 0.492f, 0.0f, 0.275f, 0.566f, 1.0f, 0.489f, 0.0f, 0.279f, 0.561f, 1.0f, 0.485f, 0.0f, 0.284f, 0.555f, 1.0f, 0.481f, 0.0f, 0.288f, 0.548f, 1.0f,
+ 0.478f, 0.0f, 0.293f, 0.54f, 1.0f, 0.473f, 0.0f, 0.297f, 0.531f, 1.0f, 0.469f, 0.0f, 0.301f, 0.521f, 1.0f, 0.465f, 0.0f, 0.305f, 0.509f, 1.0f,
+ 0.461f, 0.0f, 0.309f, 0.496f, 1.0f, 0.456f, 0.0f, 0.313f, 0.481f, 1.0f, 0.452f, 0.0f, 0.317f, 0.464f, 1.0f, 0.448f, 0.0f, 0.321f, 0.445f, 1.0f,
+ 0.443f, 0.0f, 0.324f, 0.424f, 1.0f, 0.438f, 0.0f, 0.328f, 0.401f, 1.0f, 0.434f, 0.0f, 0.331f, 0.374f, 1.0f, 0.429f, 0.0f, 0.334f, 0.346f, 1.0f,
+ 0.425f, 0.0f, 0.337f, 0.314f, 1.0f, 0.421f, 0.0f, 0.34f, 0.281f, 1.0f, 0.416f, 0.0f, 0.343f, 0.245f, 1.0f, 0.412f, 0.0f, 0.346f, 0.208f, 1.0f,
+ 0.408f, 0.0f, 0.349f, 0.169f, 1.0f, 0.404f, 0.0f, 0.351f, 0.13f, 1.0f, 0.401f, 0.0f, 0.354f, 0.089f, 1.0f, 0.398f, 0.0f, 0.356f, 0.054f, 1.0f,
+ 0.394f, 0.0f, 0.359f, 0.0f, 1.0f,
+};
+
+static const float data23[209 * GP_PRIM_DATABUF_SIZE] = {
+ -0.751f, 0.0f, 0.173f, 0.0f, 1.0f, -0.751f, 0.0f, 0.168f, 0.0f, 1.0f, -0.75f, 0.0f, 0.164f, 0.0f, 1.0f, -0.75f, 0.0f, 0.16f, 0.0f, 1.0f,
+ -0.75f, 0.0f, 0.156f, 0.0f, 1.0f, -0.749f, 0.0f, 0.152f, 0.0f, 1.0f, -0.749f, 0.0f, 0.148f, 0.0f, 1.0f, -0.748f, 0.0f, 0.144f, 0.0f, 1.0f,
+ -0.747f, 0.0f, 0.14f, 0.001f, 1.0f, -0.747f, 0.0f, 0.137f, 0.002f, 1.0f, -0.746f, 0.0f, 0.133f, 0.005f, 1.0f, -0.745f, 0.0f, 0.129f, 0.008f, 1.0f,
+ -0.745f, 0.0f, 0.125f, 0.013f, 1.0f, -0.744f, 0.0f, 0.122f, 0.02f, 1.0f, -0.743f, 0.0f, 0.118f, 0.028f, 1.0f, -0.742f, 0.0f, 0.115f, 0.038f, 1.0f,
+ -0.741f, 0.0f, 0.111f, 0.049f, 1.0f, -0.74f, 0.0f, 0.108f, 0.061f, 1.0f, -0.739f, 0.0f, 0.105f, 0.073f, 1.0f, -0.738f, 0.0f, 0.101f, 0.085f, 1.0f,
+ -0.736f, 0.0f, 0.098f, 0.097f, 1.0f, -0.735f, 0.0f, 0.095f, 0.109f, 1.0f, -0.734f, 0.0f, 0.091f, 0.119f, 1.0f, -0.732f, 0.0f, 0.088f, 0.129f, 1.0f,
+ -0.731f, 0.0f, 0.085f, 0.138f, 1.0f, -0.729f, 0.0f, 0.082f, 0.146f, 1.0f, -0.728f, 0.0f, 0.079f, 0.153f, 1.0f, -0.726f, 0.0f, 0.076f, 0.158f, 1.0f,
+ -0.725f, 0.0f, 0.073f, 0.163f, 1.0f, -0.723f, 0.0f, 0.07f, 0.167f, 1.0f, -0.722f, 0.0f, 0.067f, 0.17f, 1.0f, -0.72f, 0.0f, 0.065f, 0.173f, 1.0f,
+ -0.718f, 0.0f, 0.062f, 0.174f, 1.0f, -0.717f, 0.0f, 0.059f, 0.175f, 1.0f, -0.715f, 0.0f, 0.057f, 0.176f, 1.0f, -0.714f, 0.0f, 0.054f, 0.176f, 1.0f,
+ -0.712f, 0.0f, 0.051f, 0.176f, 1.0f, -0.71f, 0.0f, 0.049f, 0.176f, 1.0f, -0.709f, 0.0f, 0.046f, 0.176f, 1.0f, -0.707f, 0.0f, 0.043f, 0.176f, 1.0f,
+ -0.705f, 0.0f, 0.041f, 0.176f, 1.0f, -0.703f, 0.0f, 0.038f, 0.176f, 1.0f, -0.701f, 0.0f, 0.035f, 0.176f, 1.0f, -0.7f, 0.0f, 0.033f, 0.177f, 1.0f,
+ -0.698f, 0.0f, 0.03f, 0.177f, 1.0f, -0.696f, 0.0f, 0.027f, 0.178f, 1.0f, -0.694f, 0.0f, 0.024f, 0.179f, 1.0f, -0.692f, 0.0f, 0.022f, 0.18f, 1.0f,
+ -0.69f, 0.0f, 0.019f, 0.181f, 1.0f, -0.688f, 0.0f, 0.016f, 0.182f, 1.0f, -0.685f, 0.0f, 0.013f, 0.184f, 1.0f, -0.683f, 0.0f, 0.01f, 0.187f, 1.0f,
+ -0.681f, 0.0f, 0.007f, 0.19f, 1.0f, -0.679f, 0.0f, 0.004f, 0.194f, 1.0f, -0.677f, 0.0f, 0.001f, 0.198f, 1.0f, -0.675f, 0.0f, -0.002f, 0.203f, 1.0f,
+ -0.673f, 0.0f, -0.005f, 0.209f, 1.0f, -0.67f, 0.0f, -0.008f, 0.215f, 1.0f, -0.668f, 0.0f, -0.011f, 0.222f, 1.0f, -0.666f, 0.0f, -0.014f, 0.229f, 1.0f,
+ -0.664f, 0.0f, -0.017f, 0.237f, 1.0f, -0.661f, 0.0f, -0.02f, 0.246f, 1.0f, -0.659f, 0.0f, -0.023f, 0.255f, 1.0f, -0.657f, 0.0f, -0.025f, 0.264f, 1.0f,
+ -0.654f, 0.0f, -0.028f, 0.275f, 1.0f, -0.652f, 0.0f, -0.031f, 0.285f, 1.0f, -0.65f, 0.0f, -0.034f, 0.297f, 1.0f, -0.647f, 0.0f, -0.037f, 0.309f, 1.0f,
+ -0.644f, 0.0f, -0.04f, 0.322f, 1.0f, -0.642f, 0.0f, -0.043f, 0.335f, 1.0f, -0.639f, 0.0f, -0.046f, 0.348f, 1.0f, -0.636f, 0.0f, -0.049f, 0.361f, 1.0f,
+ -0.633f, 0.0f, -0.052f, 0.374f, 1.0f, -0.63f, 0.0f, -0.055f, 0.386f, 1.0f, -0.627f, 0.0f, -0.058f, 0.397f, 1.0f, -0.624f, 0.0f, -0.061f, 0.408f, 1.0f,
+ -0.62f, 0.0f, -0.064f, 0.418f, 1.0f, -0.617f, 0.0f, -0.067f, 0.427f, 1.0f, -0.614f, 0.0f, -0.07f, 0.435f, 1.0f, -0.611f, 0.0f, -0.073f, 0.443f, 1.0f,
+ -0.607f, 0.0f, -0.075f, 0.451f, 1.0f, -0.604f, 0.0f, -0.078f, 0.458f, 1.0f, -0.6f, 0.0f, -0.081f, 0.465f, 1.0f, -0.597f, 0.0f, -0.084f, 0.472f, 1.0f,
+ -0.593f, 0.0f, -0.086f, 0.479f, 1.0f, -0.59f, 0.0f, -0.089f, 0.486f, 1.0f, -0.586f, 0.0f, -0.092f, 0.492f, 1.0f, -0.583f, 0.0f, -0.094f, 0.499f, 1.0f,
+ -0.579f, 0.0f, -0.097f, 0.505f, 1.0f, -0.575f, 0.0f, -0.099f, 0.512f, 1.0f, -0.571f, 0.0f, -0.102f, 0.518f, 1.0f, -0.567f, 0.0f, -0.105f, 0.524f, 1.0f,
+ -0.563f, 0.0f, -0.107f, 0.53f, 1.0f, -0.559f, 0.0f, -0.11f, 0.536f, 1.0f, -0.555f, 0.0f, -0.112f, 0.541f, 1.0f, -0.551f, 0.0f, -0.115f, 0.546f, 1.0f,
+ -0.546f, 0.0f, -0.117f, 0.551f, 1.0f, -0.542f, 0.0f, -0.12f, 0.555f, 1.0f, -0.538f, 0.0f, -0.122f, 0.559f, 1.0f, -0.533f, 0.0f, -0.125f, 0.562f, 1.0f,
+ -0.529f, 0.0f, -0.127f, 0.565f, 1.0f, -0.525f, 0.0f, -0.129f, 0.568f, 1.0f, -0.52f, 0.0f, -0.132f, 0.57f, 1.0f, -0.516f, 0.0f, -0.134f, 0.572f, 1.0f,
+ -0.512f, 0.0f, -0.137f, 0.574f, 1.0f, -0.508f, 0.0f, -0.139f, 0.576f, 1.0f, -0.503f, 0.0f, -0.141f, 0.577f, 1.0f, -0.499f, 0.0f, -0.144f, 0.578f, 1.0f,
+ -0.495f, 0.0f, -0.146f, 0.579f, 1.0f, -0.491f, 0.0f, -0.148f, 0.579f, 1.0f, -0.487f, 0.0f, -0.151f, 0.578f, 1.0f, -0.483f, 0.0f, -0.153f, 0.577f, 1.0f,
+ -0.479f, 0.0f, -0.155f, 0.574f, 1.0f, -0.475f, 0.0f, -0.158f, 0.571f, 1.0f, -0.471f, 0.0f, -0.16f, 0.567f, 1.0f, -0.467f, 0.0f, -0.162f, 0.561f, 1.0f,
+ -0.463f, 0.0f, -0.165f, 0.555f, 1.0f, -0.459f, 0.0f, -0.167f, 0.548f, 1.0f, -0.456f, 0.0f, -0.169f, 0.54f, 1.0f, -0.452f, 0.0f, -0.172f, 0.532f, 1.0f,
+ -0.448f, 0.0f, -0.174f, 0.523f, 1.0f, -0.445f, 0.0f, -0.176f, 0.514f, 1.0f, -0.441f, 0.0f, -0.179f, 0.505f, 1.0f, -0.438f, 0.0f, -0.181f, 0.497f, 1.0f,
+ -0.435f, 0.0f, -0.183f, 0.488f, 1.0f, -0.431f, 0.0f, -0.185f, 0.48f, 1.0f, -0.428f, 0.0f, -0.188f, 0.472f, 1.0f, -0.425f, 0.0f, -0.19f, 0.464f, 1.0f,
+ -0.422f, 0.0f, -0.192f, 0.457f, 1.0f, -0.419f, 0.0f, -0.194f, 0.451f, 1.0f, -0.416f, 0.0f, -0.196f, 0.444f, 1.0f, -0.413f, 0.0f, -0.198f, 0.439f, 1.0f,
+ -0.41f, 0.0f, -0.2f, 0.434f, 1.0f, -0.407f, 0.0f, -0.202f, 0.429f, 1.0f, -0.404f, 0.0f, -0.204f, 0.426f, 1.0f, -0.401f, 0.0f, -0.206f, 0.422f, 1.0f,
+ -0.398f, 0.0f, -0.208f, 0.419f, 1.0f, -0.396f, 0.0f, -0.21f, 0.417f, 1.0f, -0.393f, 0.0f, -0.212f, 0.415f, 1.0f, -0.39f, 0.0f, -0.213f, 0.413f, 1.0f,
+ -0.388f, 0.0f, -0.215f, 0.412f, 1.0f, -0.385f, 0.0f, -0.217f, 0.411f, 1.0f, -0.382f, 0.0f, -0.219f, 0.41f, 1.0f, -0.38f, 0.0f, -0.221f, 0.41f, 1.0f,
+ -0.377f, 0.0f, -0.222f, 0.409f, 1.0f, -0.375f, 0.0f, -0.224f, 0.409f, 1.0f, -0.372f, 0.0f, -0.226f, 0.409f, 1.0f, -0.37f, 0.0f, -0.228f, 0.409f, 1.0f,
+ -0.367f, 0.0f, -0.229f, 0.409f, 1.0f, -0.365f, 0.0f, -0.231f, 0.409f, 1.0f, -0.362f, 0.0f, -0.233f, 0.409f, 1.0f, -0.36f, 0.0f, -0.235f, 0.409f, 1.0f,
+ -0.357f, 0.0f, -0.236f, 0.409f, 1.0f, -0.355f, 0.0f, -0.238f, 0.409f, 1.0f, -0.352f, 0.0f, -0.24f, 0.408f, 1.0f, -0.35f, 0.0f, -0.242f, 0.408f, 1.0f,
+ -0.348f, 0.0f, -0.243f, 0.407f, 1.0f, -0.345f, 0.0f, -0.245f, 0.406f, 1.0f, -0.343f, 0.0f, -0.247f, 0.405f, 1.0f, -0.34f, 0.0f, -0.249f, 0.404f, 1.0f,
+ -0.338f, 0.0f, -0.251f, 0.403f, 1.0f, -0.336f, 0.0f, -0.253f, 0.401f, 1.0f, -0.333f, 0.0f, -0.255f, 0.399f, 1.0f, -0.331f, 0.0f, -0.256f, 0.397f, 1.0f,
+ -0.329f, 0.0f, -0.258f, 0.394f, 1.0f, -0.327f, 0.0f, -0.26f, 0.391f, 1.0f, -0.324f, 0.0f, -0.262f, 0.387f, 1.0f, -0.322f, 0.0f, -0.264f, 0.383f, 1.0f,
+ -0.32f, 0.0f, -0.266f, 0.379f, 1.0f, -0.318f, 0.0f, -0.268f, 0.374f, 1.0f, -0.316f, 0.0f, -0.27f, 0.368f, 1.0f, -0.314f, 0.0f, -0.272f, 0.362f, 1.0f,
+ -0.312f, 0.0f, -0.275f, 0.356f, 1.0f, -0.309f, 0.0f, -0.277f, 0.349f, 1.0f, -0.307f, 0.0f, -0.279f, 0.341f, 1.0f, -0.305f, 0.0f, -0.281f, 0.333f, 1.0f,
+ -0.303f, 0.0f, -0.283f, 0.325f, 1.0f, -0.301f, 0.0f, -0.286f, 0.316f, 1.0f, -0.299f, 0.0f, -0.288f, 0.307f, 1.0f, -0.297f, 0.0f, -0.29f, 0.298f, 1.0f,
+ -0.295f, 0.0f, -0.293f, 0.289f, 1.0f, -0.293f, 0.0f, -0.295f, 0.279f, 1.0f, -0.291f, 0.0f, -0.298f, 0.269f, 1.0f, -0.29f, 0.0f, -0.3f, 0.259f, 1.0f,
+ -0.288f, 0.0f, -0.303f, 0.249f, 1.0f, -0.286f, 0.0f, -0.306f, 0.238f, 1.0f, -0.284f, 0.0f, -0.308f, 0.227f, 1.0f, -0.282f, 0.0f, -0.311f, 0.215f, 1.0f,
+ -0.28f, 0.0f, -0.314f, 0.203f, 1.0f, -0.278f, 0.0f, -0.317f, 0.191f, 1.0f, -0.277f, 0.0f, -0.32f, 0.178f, 1.0f, -0.275f, 0.0f, -0.323f, 0.165f, 1.0f,
+ -0.273f, 0.0f, -0.326f, 0.151f, 1.0f, -0.271f, 0.0f, -0.33f, 0.138f, 1.0f, -0.27f, 0.0f, -0.333f, 0.124f, 1.0f, -0.268f, 0.0f, -0.336f, 0.11f, 1.0f,
+ -0.267f, 0.0f, -0.34f, 0.097f, 1.0f, -0.265f, 0.0f, -0.343f, 0.085f, 1.0f, -0.264f, 0.0f, -0.346f, 0.073f, 1.0f, -0.262f, 0.0f, -0.35f, 0.062f, 1.0f,
+ -0.261f, 0.0f, -0.353f, 0.052f, 1.0f, -0.259f, 0.0f, -0.357f, 0.043f, 1.0f, -0.258f, 0.0f, -0.36f, 0.035f, 1.0f, -0.257f, 0.0f, -0.363f, 0.028f, 1.0f,
+ -0.255f, 0.0f, -0.366f, 0.021f, 1.0f, -0.254f, 0.0f, -0.369f, 0.016f, 1.0f, -0.253f, 0.0f, -0.372f, 0.01f, 1.0f, -0.252f, 0.0f, -0.375f, 0.006f, 1.0f,
+ -0.251f, 0.0f, -0.379f, 0.0f, 1.0f,
+};
+
+static const float data24[133 * GP_PRIM_DATABUF_SIZE] = {
+ 0.233f, 0.0f, -0.376f, 0.021f, 1.0f, 0.234f, 0.0f, -0.372f, 0.08f, 1.0f, 0.234f, 0.0f, -0.369f, 0.116f, 1.0f, 0.234f, 0.0f, -0.366f, 0.156f, 1.0f,
+ 0.235f, 0.0f, -0.362f, 0.191f, 1.0f, 0.236f, 0.0f, -0.359f, 0.222f, 1.0f, 0.236f, 0.0f, -0.356f, 0.248f, 1.0f, 0.237f, 0.0f, -0.353f, 0.27f, 1.0f,
+ 0.238f, 0.0f, -0.35f, 0.289f, 1.0f, 0.239f, 0.0f, -0.346f, 0.304f, 1.0f, 0.24f, 0.0f, -0.343f, 0.319f, 1.0f, 0.241f, 0.0f, -0.34f, 0.334f, 1.0f,
+ 0.242f, 0.0f, -0.337f, 0.35f, 1.0f, 0.243f, 0.0f, -0.335f, 0.367f, 1.0f, 0.244f, 0.0f, -0.332f, 0.385f, 1.0f, 0.245f, 0.0f, -0.329f, 0.401f, 1.0f,
+ 0.247f, 0.0f, -0.327f, 0.415f, 1.0f, 0.248f, 0.0f, -0.324f, 0.426f, 1.0f, 0.249f, 0.0f, -0.322f, 0.435f, 1.0f, 0.251f, 0.0f, -0.32f, 0.443f, 1.0f,
+ 0.252f, 0.0f, -0.318f, 0.449f, 1.0f, 0.254f, 0.0f, -0.316f, 0.455f, 1.0f, 0.255f, 0.0f, -0.314f, 0.461f, 1.0f, 0.257f, 0.0f, -0.312f, 0.467f, 1.0f,
+ 0.258f, 0.0f, -0.311f, 0.474f, 1.0f, 0.26f, 0.0f, -0.309f, 0.48f, 1.0f, 0.262f, 0.0f, -0.307f, 0.487f, 1.0f, 0.263f, 0.0f, -0.305f, 0.493f, 1.0f,
+ 0.265f, 0.0f, -0.303f, 0.499f, 1.0f, 0.267f, 0.0f, -0.3f, 0.505f, 1.0f, 0.269f, 0.0f, -0.298f, 0.511f, 1.0f, 0.271f, 0.0f, -0.296f, 0.518f, 1.0f,
+ 0.273f, 0.0f, -0.294f, 0.524f, 1.0f, 0.276f, 0.0f, -0.291f, 0.531f, 1.0f, 0.278f, 0.0f, -0.289f, 0.539f, 1.0f, 0.281f, 0.0f, -0.287f, 0.546f, 1.0f,
+ 0.283f, 0.0f, -0.284f, 0.552f, 1.0f, 0.286f, 0.0f, -0.281f, 0.557f, 1.0f, 0.289f, 0.0f, -0.279f, 0.561f, 1.0f, 0.292f, 0.0f, -0.276f, 0.565f, 1.0f,
+ 0.294f, 0.0f, -0.274f, 0.568f, 1.0f, 0.297f, 0.0f, -0.271f, 0.57f, 1.0f, 0.3f, 0.0f, -0.269f, 0.572f, 1.0f, 0.303f, 0.0f, -0.267f, 0.574f, 1.0f,
+ 0.306f, 0.0f, -0.264f, 0.575f, 1.0f, 0.308f, 0.0f, -0.262f, 0.576f, 1.0f, 0.311f, 0.0f, -0.26f, 0.577f, 1.0f, 0.314f, 0.0f, -0.257f, 0.578f, 1.0f,
+ 0.316f, 0.0f, -0.255f, 0.578f, 1.0f, 0.319f, 0.0f, -0.253f, 0.579f, 1.0f, 0.322f, 0.0f, -0.25f, 0.579f, 1.0f, 0.325f, 0.0f, -0.248f, 0.58f, 1.0f,
+ 0.328f, 0.0f, -0.246f, 0.58f, 1.0f, 0.331f, 0.0f, -0.243f, 0.58f, 1.0f, 0.334f, 0.0f, -0.241f, 0.58f, 1.0f, 0.337f, 0.0f, -0.239f, 0.58f, 1.0f,
+ 0.341f, 0.0f, -0.236f, 0.58f, 1.0f, 0.344f, 0.0f, -0.233f, 0.581f, 1.0f, 0.348f, 0.0f, -0.231f, 0.581f, 1.0f, 0.352f, 0.0f, -0.228f, 0.581f, 1.0f,
+ 0.356f, 0.0f, -0.225f, 0.582f, 1.0f, 0.36f, 0.0f, -0.222f, 0.582f, 1.0f, 0.365f, 0.0f, -0.219f, 0.582f, 1.0f, 0.369f, 0.0f, -0.216f, 0.582f, 1.0f,
+ 0.374f, 0.0f, -0.214f, 0.582f, 1.0f, 0.378f, 0.0f, -0.211f, 0.582f, 1.0f, 0.383f, 0.0f, -0.208f, 0.583f, 1.0f, 0.387f, 0.0f, -0.205f, 0.583f, 1.0f,
+ 0.392f, 0.0f, -0.202f, 0.583f, 1.0f, 0.397f, 0.0f, -0.199f, 0.583f, 1.0f, 0.401f, 0.0f, -0.197f, 0.583f, 1.0f, 0.406f, 0.0f, -0.194f, 0.583f, 1.0f,
+ 0.411f, 0.0f, -0.191f, 0.583f, 1.0f, 0.416f, 0.0f, -0.188f, 0.583f, 1.0f, 0.42f, 0.0f, -0.186f, 0.583f, 1.0f, 0.425f, 0.0f, -0.183f, 0.583f, 1.0f,
+ 0.43f, 0.0f, -0.18f, 0.583f, 1.0f, 0.434f, 0.0f, -0.178f, 0.583f, 1.0f, 0.439f, 0.0f, -0.175f, 0.583f, 1.0f, 0.444f, 0.0f, -0.172f, 0.583f, 1.0f,
+ 0.449f, 0.0f, -0.17f, 0.584f, 1.0f, 0.453f, 0.0f, -0.167f, 0.584f, 1.0f, 0.458f, 0.0f, -0.164f, 0.584f, 1.0f, 0.463f, 0.0f, -0.161f, 0.585f, 1.0f,
+ 0.468f, 0.0f, -0.158f, 0.585f, 1.0f, 0.473f, 0.0f, -0.155f, 0.585f, 1.0f, 0.478f, 0.0f, -0.152f, 0.585f, 1.0f, 0.483f, 0.0f, -0.149f, 0.585f, 1.0f,
+ 0.488f, 0.0f, -0.146f, 0.585f, 1.0f, 0.492f, 0.0f, -0.143f, 0.585f, 1.0f, 0.497f, 0.0f, -0.14f, 0.586f, 1.0f, 0.501f, 0.0f, -0.137f, 0.586f, 1.0f,
+ 0.506f, 0.0f, -0.134f, 0.586f, 1.0f, 0.51f, 0.0f, -0.13f, 0.586f, 1.0f, 0.515f, 0.0f, -0.127f, 0.586f, 1.0f, 0.52f, 0.0f, -0.124f, 0.586f, 1.0f,
+ 0.524f, 0.0f, -0.12f, 0.586f, 1.0f, 0.529f, 0.0f, -0.117f, 0.586f, 1.0f, 0.534f, 0.0f, -0.113f, 0.586f, 1.0f, 0.539f, 0.0f, -0.109f, 0.586f, 1.0f,
+ 0.544f, 0.0f, -0.105f, 0.586f, 1.0f, 0.55f, 0.0f, -0.1f, 0.586f, 1.0f, 0.555f, 0.0f, -0.095f, 0.586f, 1.0f, 0.561f, 0.0f, -0.09f, 0.586f, 1.0f,
+ 0.567f, 0.0f, -0.084f, 0.587f, 1.0f, 0.573f, 0.0f, -0.078f, 0.587f, 1.0f, 0.579f, 0.0f, -0.071f, 0.587f, 1.0f, 0.586f, 0.0f, -0.063f, 0.588f, 1.0f,
+ 0.593f, 0.0f, -0.055f, 0.588f, 1.0f, 0.6f, 0.0f, -0.047f, 0.588f, 1.0f, 0.607f, 0.0f, -0.038f, 0.589f, 1.0f, 0.614f, 0.0f, -0.028f, 0.589f, 1.0f,
+ 0.621f, 0.0f, -0.018f, 0.589f, 1.0f, 0.629f, 0.0f, -0.007f, 0.589f, 1.0f, 0.636f, 0.0f, 0.004f, 0.589f, 1.0f, 0.643f, 0.0f, 0.015f, 0.59f, 1.0f,
+ 0.65f, 0.0f, 0.026f, 0.589f, 1.0f, 0.656f, 0.0f, 0.038f, 0.589f, 1.0f, 0.663f, 0.0f, 0.049f, 0.588f, 1.0f, 0.669f, 0.0f, 0.06f, 0.587f, 1.0f,
+ 0.676f, 0.0f, 0.072f, 0.584f, 1.0f, 0.682f, 0.0f, 0.084f, 0.579f, 1.0f, 0.688f, 0.0f, 0.096f, 0.571f, 1.0f, 0.694f, 0.0f, 0.108f, 0.558f, 1.0f,
+ 0.7f, 0.0f, 0.12f, 0.54f, 1.0f, 0.706f, 0.0f, 0.133f, 0.514f, 1.0f, 0.712f, 0.0f, 0.145f, 0.478f, 1.0f, 0.718f, 0.0f, 0.158f, 0.431f, 1.0f,
+ 0.723f, 0.0f, 0.17f, 0.369f, 1.0f, 0.728f, 0.0f, 0.182f, 0.294f, 1.0f, 0.733f, 0.0f, 0.194f, 0.205f, 1.0f, 0.737f, 0.0f, 0.204f, 0.125f, 1.0f,
+ 0.743f, 0.0f, 0.218f, 0.0f, 1.0f,
+};
+
+static const float data25[389 * GP_PRIM_DATABUF_SIZE] = {
+ -0.284f, 0.0f, -0.444f, 0.0f, 1.0f, -0.285f, 0.0f, -0.448f, 0.0f, 1.0f, -0.285f, 0.0f, -0.45f, 0.0f, 1.0f, -0.286f, 0.0f, -0.454f, 0.0f, 1.0f,
+ -0.286f, 0.0f, -0.457f, 0.0f, 1.0f, -0.287f, 0.0f, -0.46f, 0.0f, 1.0f, -0.288f, 0.0f, -0.463f, 0.0f, 1.0f, -0.289f, 0.0f, -0.466f, 0.0f, 1.0f,
+ -0.289f, 0.0f, -0.47f, 0.0f, 1.0f, -0.29f, 0.0f, -0.473f, 0.0f, 1.0f, -0.291f, 0.0f, -0.476f, 0.0f, 1.0f, -0.292f, 0.0f, -0.48f, 0.0f, 1.0f,
+ -0.293f, 0.0f, -0.484f, 0.0f, 1.0f, -0.294f, 0.0f, -0.487f, 0.0f, 1.0f, -0.295f, 0.0f, -0.491f, 0.0f, 1.0f, -0.296f, 0.0f, -0.494f, 0.0f, 1.0f,
+ -0.297f, 0.0f, -0.498f, 0.0f, 1.0f, -0.298f, 0.0f, -0.502f, 0.0f, 1.0f, -0.299f, 0.0f, -0.505f, 0.0f, 1.0f, -0.3f, 0.0f, -0.509f, 0.0f, 1.0f,
+ -0.301f, 0.0f, -0.513f, 0.0f, 1.0f, -0.302f, 0.0f, -0.517f, 0.0f, 1.0f, -0.303f, 0.0f, -0.52f, 0.0f, 1.0f, -0.304f, 0.0f, -0.524f, 0.0f, 1.0f,
+ -0.305f, 0.0f, -0.528f, 0.0f, 1.0f, -0.306f, 0.0f, -0.532f, 0.0f, 1.0f, -0.307f, 0.0f, -0.535f, 0.0f, 1.0f, -0.308f, 0.0f, -0.539f, 0.0f, 1.0f,
+ -0.309f, 0.0f, -0.543f, 0.0f, 1.0f, -0.31f, 0.0f, -0.547f, 0.0f, 1.0f, -0.311f, 0.0f, -0.55f, 0.0f, 1.0f, -0.312f, 0.0f, -0.554f, 0.0f, 1.0f,
+ -0.313f, 0.0f, -0.558f, 0.0f, 1.0f, -0.314f, 0.0f, -0.562f, 0.0f, 1.0f, -0.315f, 0.0f, -0.565f, 0.0f, 1.0f, -0.316f, 0.0f, -0.569f, 0.0f, 1.0f,
+ -0.317f, 0.0f, -0.573f, 0.0f, 1.0f, -0.318f, 0.0f, -0.576f, 0.0f, 1.0f, -0.319f, 0.0f, -0.58f, 0.0f, 1.0f, -0.32f, 0.0f, -0.583f, 0.0f, 1.0f,
+ -0.321f, 0.0f, -0.587f, 0.0f, 1.0f, -0.322f, 0.0f, -0.591f, 0.0f, 1.0f, -0.323f, 0.0f, -0.594f, 0.0f, 1.0f, -0.323f, 0.0f, -0.598f, 0.0f, 1.0f,
+ -0.324f, 0.0f, -0.601f, 0.0f, 1.0f, -0.325f, 0.0f, -0.605f, 0.0f, 1.0f, -0.326f, 0.0f, -0.608f, 0.0f, 1.0f, -0.326f, 0.0f, -0.612f, 0.0f, 1.0f,
+ -0.327f, 0.0f, -0.615f, 0.0f, 1.0f, -0.328f, 0.0f, -0.619f, 0.0f, 1.0f, -0.328f, 0.0f, -0.622f, 0.0f, 1.0f, -0.329f, 0.0f, -0.625f, 0.0f, 1.0f,
+ -0.33f, 0.0f, -0.629f, 0.0f, 1.0f, -0.33f, 0.0f, -0.632f, 0.0f, 1.0f, -0.331f, 0.0f, -0.635f, 0.001f, 1.0f, -0.331f, 0.0f, -0.639f, 0.001f, 1.0f,
+ -0.332f, 0.0f, -0.642f, 0.002f, 1.0f, -0.332f, 0.0f, -0.645f, 0.002f, 1.0f, -0.333f, 0.0f, -0.649f, 0.003f, 1.0f, -0.333f, 0.0f, -0.652f, 0.005f, 1.0f,
+ -0.334f, 0.0f, -0.655f, 0.006f, 1.0f, -0.334f, 0.0f, -0.658f, 0.009f, 1.0f, -0.335f, 0.0f, -0.662f, 0.011f, 1.0f, -0.335f, 0.0f, -0.665f, 0.015f, 1.0f,
+ -0.335f, 0.0f, -0.668f, 0.019f, 1.0f, -0.336f, 0.0f, -0.672f, 0.024f, 1.0f, -0.336f, 0.0f, -0.675f, 0.031f, 1.0f, -0.337f, 0.0f, -0.678f, 0.038f, 1.0f,
+ -0.337f, 0.0f, -0.682f, 0.046f, 1.0f, -0.337f, 0.0f, -0.685f, 0.056f, 1.0f, -0.338f, 0.0f, -0.689f, 0.067f, 1.0f, -0.338f, 0.0f, -0.692f, 0.079f, 1.0f,
+ -0.338f, 0.0f, -0.696f, 0.093f, 1.0f, -0.339f, 0.0f, -0.699f, 0.107f, 1.0f, -0.339f, 0.0f, -0.703f, 0.123f, 1.0f, -0.34f, 0.0f, -0.706f, 0.139f, 1.0f,
+ -0.34f, 0.0f, -0.71f, 0.157f, 1.0f, -0.34f, 0.0f, -0.714f, 0.174f, 1.0f, -0.34f, 0.0f, -0.717f, 0.193f, 1.0f, -0.341f, 0.0f, -0.721f, 0.211f, 1.0f,
+ -0.341f, 0.0f, -0.725f, 0.23f, 1.0f, -0.341f, 0.0f, -0.729f, 0.248f, 1.0f, -0.342f, 0.0f, -0.732f, 0.266f, 1.0f, -0.342f, 0.0f, -0.736f, 0.284f, 1.0f,
+ -0.342f, 0.0f, -0.74f, 0.302f, 1.0f, -0.342f, 0.0f, -0.744f, 0.318f, 1.0f, -0.342f, 0.0f, -0.748f, 0.334f, 1.0f, -0.342f, 0.0f, -0.752f, 0.349f, 1.0f,
+ -0.343f, 0.0f, -0.756f, 0.364f, 1.0f, -0.343f, 0.0f, -0.76f, 0.377f, 1.0f, -0.343f, 0.0f, -0.763f, 0.389f, 1.0f, -0.343f, 0.0f, -0.767f, 0.401f, 1.0f,
+ -0.343f, 0.0f, -0.771f, 0.411f, 1.0f, -0.343f, 0.0f, -0.775f, 0.421f, 1.0f, -0.342f, 0.0f, -0.779f, 0.429f, 1.0f, -0.342f, 0.0f, -0.783f, 0.437f, 1.0f,
+ -0.342f, 0.0f, -0.786f, 0.444f, 1.0f, -0.342f, 0.0f, -0.79f, 0.451f, 1.0f, -0.342f, 0.0f, -0.794f, 0.456f, 1.0f, -0.341f, 0.0f, -0.797f, 0.461f, 1.0f,
+ -0.341f, 0.0f, -0.801f, 0.466f, 1.0f, -0.34f, 0.0f, -0.805f, 0.469f, 1.0f, -0.34f, 0.0f, -0.808f, 0.473f, 1.0f, -0.339f, 0.0f, -0.812f, 0.476f, 1.0f,
+ -0.339f, 0.0f, -0.815f, 0.478f, 1.0f, -0.338f, 0.0f, -0.818f, 0.48f, 1.0f, -0.338f, 0.0f, -0.822f, 0.482f, 1.0f, -0.337f, 0.0f, -0.825f, 0.483f, 1.0f,
+ -0.336f, 0.0f, -0.828f, 0.484f, 1.0f, -0.335f, 0.0f, -0.831f, 0.485f, 1.0f, -0.334f, 0.0f, -0.834f, 0.486f, 1.0f, -0.333f, 0.0f, -0.837f, 0.487f, 1.0f,
+ -0.332f, 0.0f, -0.84f, 0.487f, 1.0f, -0.331f, 0.0f, -0.843f, 0.487f, 1.0f, -0.33f, 0.0f, -0.846f, 0.488f, 1.0f, -0.329f, 0.0f, -0.849f, 0.488f, 1.0f,
+ -0.328f, 0.0f, -0.852f, 0.488f, 1.0f, -0.326f, 0.0f, -0.855f, 0.488f, 1.0f, -0.325f, 0.0f, -0.857f, 0.488f, 1.0f, -0.324f, 0.0f, -0.86f, 0.488f, 1.0f,
+ -0.322f, 0.0f, -0.863f, 0.488f, 1.0f, -0.321f, 0.0f, -0.865f, 0.488f, 1.0f, -0.319f, 0.0f, -0.868f, 0.488f, 1.0f, -0.318f, 0.0f, -0.871f, 0.488f, 1.0f,
+ -0.316f, 0.0f, -0.873f, 0.489f, 1.0f, -0.314f, 0.0f, -0.876f, 0.489f, 1.0f, -0.312f, 0.0f, -0.878f, 0.489f, 1.0f, -0.311f, 0.0f, -0.881f, 0.489f, 1.0f,
+ -0.309f, 0.0f, -0.883f, 0.489f, 1.0f, -0.307f, 0.0f, -0.885f, 0.489f, 1.0f, -0.305f, 0.0f, -0.888f, 0.49f, 1.0f, -0.303f, 0.0f, -0.89f, 0.491f, 1.0f,
+ -0.301f, 0.0f, -0.892f, 0.491f, 1.0f, -0.298f, 0.0f, -0.894f, 0.492f, 1.0f, -0.296f, 0.0f, -0.897f, 0.494f, 1.0f, -0.294f, 0.0f, -0.899f, 0.495f, 1.0f,
+ -0.292f, 0.0f, -0.901f, 0.497f, 1.0f, -0.289f, 0.0f, -0.903f, 0.5f, 1.0f, -0.287f, 0.0f, -0.905f, 0.502f, 1.0f, -0.284f, 0.0f, -0.907f, 0.505f, 1.0f,
+ -0.282f, 0.0f, -0.909f, 0.509f, 1.0f, -0.279f, 0.0f, -0.912f, 0.512f, 1.0f, -0.277f, 0.0f, -0.914f, 0.517f, 1.0f, -0.274f, 0.0f, -0.916f, 0.521f, 1.0f,
+ -0.271f, 0.0f, -0.918f, 0.526f, 1.0f, -0.269f, 0.0f, -0.919f, 0.531f, 1.0f, -0.266f, 0.0f, -0.921f, 0.537f, 1.0f, -0.263f, 0.0f, -0.923f, 0.543f, 1.0f,
+ -0.26f, 0.0f, -0.925f, 0.548f, 1.0f, -0.257f, 0.0f, -0.927f, 0.554f, 1.0f, -0.255f, 0.0f, -0.929f, 0.56f, 1.0f, -0.252f, 0.0f, -0.931f, 0.566f, 1.0f,
+ -0.249f, 0.0f, -0.932f, 0.571f, 1.0f, -0.246f, 0.0f, -0.934f, 0.577f, 1.0f, -0.243f, 0.0f, -0.936f, 0.582f, 1.0f, -0.24f, 0.0f, -0.938f, 0.587f, 1.0f,
+ -0.237f, 0.0f, -0.939f, 0.592f, 1.0f, -0.234f, 0.0f, -0.941f, 0.597f, 1.0f, -0.231f, 0.0f, -0.943f, 0.601f, 1.0f, -0.228f, 0.0f, -0.944f, 0.605f, 1.0f,
+ -0.225f, 0.0f, -0.946f, 0.609f, 1.0f, -0.222f, 0.0f, -0.948f, 0.613f, 1.0f, -0.219f, 0.0f, -0.949f, 0.617f, 1.0f, -0.216f, 0.0f, -0.951f, 0.62f, 1.0f,
+ -0.213f, 0.0f, -0.953f, 0.624f, 1.0f, -0.21f, 0.0f, -0.954f, 0.627f, 1.0f, -0.207f, 0.0f, -0.956f, 0.63f, 1.0f, -0.204f, 0.0f, -0.958f, 0.633f, 1.0f,
+ -0.201f, 0.0f, -0.959f, 0.636f, 1.0f, -0.198f, 0.0f, -0.961f, 0.639f, 1.0f, -0.195f, 0.0f, -0.962f, 0.641f, 1.0f, -0.191f, 0.0f, -0.964f, 0.643f, 1.0f,
+ -0.188f, 0.0f, -0.965f, 0.646f, 1.0f, -0.185f, 0.0f, -0.967f, 0.648f, 1.0f, -0.181f, 0.0f, -0.968f, 0.649f, 1.0f, -0.178f, 0.0f, -0.969f, 0.651f, 1.0f,
+ -0.175f, 0.0f, -0.971f, 0.653f, 1.0f, -0.171f, 0.0f, -0.972f, 0.654f, 1.0f, -0.168f, 0.0f, -0.973f, 0.655f, 1.0f, -0.165f, 0.0f, -0.974f, 0.657f, 1.0f,
+ -0.161f, 0.0f, -0.976f, 0.658f, 1.0f, -0.158f, 0.0f, -0.977f, 0.659f, 1.0f, -0.154f, 0.0f, -0.978f, 0.66f, 1.0f, -0.151f, 0.0f, -0.979f, 0.661f, 1.0f,
+ -0.148f, 0.0f, -0.98f, 0.662f, 1.0f, -0.144f, 0.0f, -0.981f, 0.664f, 1.0f, -0.141f, 0.0f, -0.982f, 0.665f, 1.0f, -0.137f, 0.0f, -0.983f, 0.667f, 1.0f,
+ -0.134f, 0.0f, -0.984f, 0.669f, 1.0f, -0.13f, 0.0f, -0.985f, 0.671f, 1.0f, -0.127f, 0.0f, -0.986f, 0.673f, 1.0f, -0.124f, 0.0f, -0.987f, 0.675f, 1.0f,
+ -0.12f, 0.0f, -0.988f, 0.678f, 1.0f, -0.117f, 0.0f, -0.989f, 0.68f, 1.0f, -0.113f, 0.0f, -0.99f, 0.683f, 1.0f, -0.11f, 0.0f, -0.991f, 0.685f, 1.0f,
+ -0.107f, 0.0f, -0.992f, 0.688f, 1.0f, -0.103f, 0.0f, -0.992f, 0.691f, 1.0f, -0.1f, 0.0f, -0.993f, 0.693f, 1.0f, -0.097f, 0.0f, -0.994f, 0.696f, 1.0f,
+ -0.093f, 0.0f, -0.995f, 0.698f, 1.0f, -0.09f, 0.0f, -0.996f, 0.701f, 1.0f, -0.087f, 0.0f, -0.997f, 0.703f, 1.0f, -0.084f, 0.0f, -0.997f, 0.705f, 1.0f,
+ -0.08f, 0.0f, -0.998f, 0.707f, 1.0f, -0.077f, 0.0f, -0.999f, 0.708f, 1.0f, -0.074f, 0.0f, -1.0f, 0.71f, 1.0f, -0.07f, 0.0f, -1.0f, 0.712f, 1.0f,
+ -0.067f, 0.0f, -1.001f, 0.713f, 1.0f, -0.063f, 0.0f, -1.002f, 0.715f, 1.0f, -0.06f, 0.0f, -1.002f, 0.717f, 1.0f, -0.056f, 0.0f, -1.003f, 0.718f, 1.0f,
+ -0.053f, 0.0f, -1.003f, 0.72f, 1.0f, -0.049f, 0.0f, -1.004f, 0.723f, 1.0f, -0.045f, 0.0f, -1.004f, 0.725f, 1.0f, -0.041f, 0.0f, -1.005f, 0.728f, 1.0f,
+ -0.038f, 0.0f, -1.005f, 0.73f, 1.0f, -0.034f, 0.0f, -1.006f, 0.733f, 1.0f, -0.03f, 0.0f, -1.006f, 0.736f, 1.0f, -0.026f, 0.0f, -1.007f, 0.738f, 1.0f,
+ -0.022f, 0.0f, -1.007f, 0.741f, 1.0f, -0.018f, 0.0f, -1.007f, 0.743f, 1.0f, -0.014f, 0.0f, -1.008f, 0.746f, 1.0f, -0.01f, 0.0f, -1.008f, 0.748f, 1.0f,
+ -0.006f, 0.0f, -1.009f, 0.75f, 1.0f, -0.001f, 0.0f, -1.009f, 0.752f, 1.0f, 0.003f, 0.0f, -1.009f, 0.754f, 1.0f, 0.007f, 0.0f, -1.01f, 0.755f, 1.0f,
+ 0.011f, 0.0f, -1.01f, 0.757f, 1.0f, 0.015f, 0.0f, -1.01f, 0.758f, 1.0f, 0.02f, 0.0f, -1.011f, 0.759f, 1.0f, 0.024f, 0.0f, -1.011f, 0.76f, 1.0f,
+ 0.028f, 0.0f, -1.011f, 0.761f, 1.0f, 0.033f, 0.0f, -1.011f, 0.761f, 1.0f, 0.037f, 0.0f, -1.012f, 0.762f, 1.0f, 0.041f, 0.0f, -1.012f, 0.762f, 1.0f,
+ 0.045f, 0.0f, -1.012f, 0.763f, 1.0f, 0.05f, 0.0f, -1.012f, 0.763f, 1.0f, 0.054f, 0.0f, -1.012f, 0.764f, 1.0f, 0.058f, 0.0f, -1.013f, 0.764f, 1.0f,
+ 0.062f, 0.0f, -1.013f, 0.764f, 1.0f, 0.066f, 0.0f, -1.013f, 0.764f, 1.0f, 0.071f, 0.0f, -1.013f, 0.764f, 1.0f, 0.075f, 0.0f, -1.013f, 0.765f, 1.0f,
+ 0.079f, 0.0f, -1.013f, 0.765f, 1.0f, 0.083f, 0.0f, -1.013f, 0.765f, 1.0f, 0.087f, 0.0f, -1.013f, 0.765f, 1.0f, 0.091f, 0.0f, -1.013f, 0.765f, 1.0f,
+ 0.095f, 0.0f, -1.013f, 0.765f, 1.0f, 0.099f, 0.0f, -1.013f, 0.766f, 1.0f, 0.103f, 0.0f, -1.013f, 0.766f, 1.0f, 0.108f, 0.0f, -1.012f, 0.766f, 1.0f,
+ 0.112f, 0.0f, -1.012f, 0.766f, 1.0f, 0.116f, 0.0f, -1.012f, 0.766f, 1.0f, 0.119f, 0.0f, -1.012f, 0.767f, 1.0f, 0.123f, 0.0f, -1.011f, 0.767f, 1.0f,
+ 0.127f, 0.0f, -1.011f, 0.767f, 1.0f, 0.131f, 0.0f, -1.01f, 0.767f, 1.0f, 0.135f, 0.0f, -1.01f, 0.767f, 1.0f, 0.139f, 0.0f, -1.009f, 0.768f, 1.0f,
+ 0.143f, 0.0f, -1.009f, 0.768f, 1.0f, 0.147f, 0.0f, -1.008f, 0.768f, 1.0f, 0.151f, 0.0f, -1.007f, 0.769f, 1.0f, 0.154f, 0.0f, -1.007f, 0.769f, 1.0f,
+ 0.158f, 0.0f, -1.006f, 0.769f, 1.0f, 0.162f, 0.0f, -1.005f, 0.769f, 1.0f, 0.166f, 0.0f, -1.004f, 0.77f, 1.0f, 0.17f, 0.0f, -1.003f, 0.77f, 1.0f,
+ 0.173f, 0.0f, -1.003f, 0.77f, 1.0f, 0.177f, 0.0f, -1.002f, 0.771f, 1.0f, 0.181f, 0.0f, -1.001f, 0.771f, 1.0f, 0.184f, 0.0f, -1.0f, 0.772f, 1.0f,
+ 0.188f, 0.0f, -0.999f, 0.772f, 1.0f, 0.192f, 0.0f, -0.998f, 0.773f, 1.0f, 0.195f, 0.0f, -0.997f, 0.773f, 1.0f, 0.199f, 0.0f, -0.996f, 0.774f, 1.0f,
+ 0.202f, 0.0f, -0.995f, 0.774f, 1.0f, 0.206f, 0.0f, -0.994f, 0.775f, 1.0f, 0.209f, 0.0f, -0.993f, 0.776f, 1.0f, 0.213f, 0.0f, -0.992f, 0.776f, 1.0f,
+ 0.216f, 0.0f, -0.991f, 0.777f, 1.0f, 0.22f, 0.0f, -0.99f, 0.777f, 1.0f, 0.223f, 0.0f, -0.988f, 0.778f, 1.0f, 0.227f, 0.0f, -0.987f, 0.778f, 1.0f,
+ 0.23f, 0.0f, -0.986f, 0.778f, 1.0f, 0.233f, 0.0f, -0.985f, 0.779f, 1.0f, 0.237f, 0.0f, -0.983f, 0.779f, 1.0f, 0.24f, 0.0f, -0.982f, 0.779f, 1.0f,
+ 0.243f, 0.0f, -0.981f, 0.779f, 1.0f, 0.246f, 0.0f, -0.979f, 0.778f, 1.0f, 0.249f, 0.0f, -0.978f, 0.778f, 1.0f, 0.252f, 0.0f, -0.976f, 0.777f, 1.0f,
+ 0.255f, 0.0f, -0.975f, 0.777f, 1.0f, 0.258f, 0.0f, -0.973f, 0.776f, 1.0f, 0.261f, 0.0f, -0.972f, 0.775f, 1.0f, 0.264f, 0.0f, -0.97f, 0.773f, 1.0f,
+ 0.267f, 0.0f, -0.968f, 0.772f, 1.0f, 0.269f, 0.0f, -0.967f, 0.77f, 1.0f, 0.272f, 0.0f, -0.965f, 0.769f, 1.0f, 0.275f, 0.0f, -0.963f, 0.767f, 1.0f,
+ 0.277f, 0.0f, -0.961f, 0.765f, 1.0f, 0.279f, 0.0f, -0.959f, 0.763f, 1.0f, 0.282f, 0.0f, -0.957f, 0.761f, 1.0f, 0.284f, 0.0f, -0.955f, 0.759f, 1.0f,
+ 0.286f, 0.0f, -0.953f, 0.756f, 1.0f, 0.288f, 0.0f, -0.951f, 0.754f, 1.0f, 0.29f, 0.0f, -0.948f, 0.752f, 1.0f, 0.292f, 0.0f, -0.946f, 0.749f, 1.0f,
+ 0.294f, 0.0f, -0.944f, 0.746f, 1.0f, 0.296f, 0.0f, -0.941f, 0.744f, 1.0f, 0.298f, 0.0f, -0.939f, 0.741f, 1.0f, 0.3f, 0.0f, -0.937f, 0.738f, 1.0f,
+ 0.302f, 0.0f, -0.934f, 0.736f, 1.0f, 0.303f, 0.0f, -0.932f, 0.733f, 1.0f, 0.305f, 0.0f, -0.929f, 0.73f, 1.0f, 0.306f, 0.0f, -0.926f, 0.727f, 1.0f,
+ 0.308f, 0.0f, -0.924f, 0.724f, 1.0f, 0.309f, 0.0f, -0.921f, 0.721f, 1.0f, 0.311f, 0.0f, -0.918f, 0.719f, 1.0f, 0.312f, 0.0f, -0.916f, 0.716f, 1.0f,
+ 0.313f, 0.0f, -0.913f, 0.713f, 1.0f, 0.315f, 0.0f, -0.91f, 0.71f, 1.0f, 0.316f, 0.0f, -0.907f, 0.707f, 1.0f, 0.317f, 0.0f, -0.904f, 0.704f, 1.0f,
+ 0.318f, 0.0f, -0.901f, 0.7f, 1.0f, 0.319f, 0.0f, -0.898f, 0.697f, 1.0f, 0.32f, 0.0f, -0.895f, 0.693f, 1.0f, 0.321f, 0.0f, -0.892f, 0.69f, 1.0f,
+ 0.322f, 0.0f, -0.889f, 0.686f, 1.0f, 0.323f, 0.0f, -0.886f, 0.681f, 1.0f, 0.324f, 0.0f, -0.883f, 0.677f, 1.0f, 0.325f, 0.0f, -0.88f, 0.672f, 1.0f,
+ 0.326f, 0.0f, -0.876f, 0.667f, 1.0f, 0.326f, 0.0f, -0.873f, 0.661f, 1.0f, 0.327f, 0.0f, -0.87f, 0.655f, 1.0f, 0.328f, 0.0f, -0.867f, 0.649f, 1.0f,
+ 0.329f, 0.0f, -0.864f, 0.643f, 1.0f, 0.329f, 0.0f, -0.861f, 0.637f, 1.0f, 0.33f, 0.0f, -0.857f, 0.63f, 1.0f, 0.331f, 0.0f, -0.854f, 0.624f, 1.0f,
+ 0.331f, 0.0f, -0.851f, 0.618f, 1.0f, 0.332f, 0.0f, -0.848f, 0.613f, 1.0f, 0.333f, 0.0f, -0.845f, 0.607f, 1.0f, 0.333f, 0.0f, -0.841f, 0.603f, 1.0f,
+ 0.334f, 0.0f, -0.838f, 0.598f, 1.0f, 0.334f, 0.0f, -0.835f, 0.594f, 1.0f, 0.335f, 0.0f, -0.832f, 0.591f, 1.0f, 0.335f, 0.0f, -0.828f, 0.588f, 1.0f,
+ 0.335f, 0.0f, -0.825f, 0.586f, 1.0f, 0.336f, 0.0f, -0.821f, 0.584f, 1.0f, 0.336f, 0.0f, -0.818f, 0.582f, 1.0f, 0.336f, 0.0f, -0.814f, 0.581f, 1.0f,
+ 0.337f, 0.0f, -0.811f, 0.58f, 1.0f, 0.337f, 0.0f, -0.807f, 0.58f, 1.0f, 0.337f, 0.0f, -0.803f, 0.579f, 1.0f, 0.337f, 0.0f, -0.799f, 0.579f, 1.0f,
+ 0.337f, 0.0f, -0.795f, 0.578f, 1.0f, 0.337f, 0.0f, -0.79f, 0.578f, 1.0f, 0.337f, 0.0f, -0.786f, 0.578f, 1.0f, 0.338f, 0.0f, -0.782f, 0.577f, 1.0f,
+ 0.338f, 0.0f, -0.777f, 0.576f, 1.0f, 0.337f, 0.0f, -0.772f, 0.574f, 1.0f, 0.337f, 0.0f, -0.767f, 0.572f, 1.0f, 0.337f, 0.0f, -0.762f, 0.569f, 1.0f,
+ 0.337f, 0.0f, -0.756f, 0.565f, 1.0f, 0.337f, 0.0f, -0.751f, 0.559f, 1.0f, 0.337f, 0.0f, -0.745f, 0.553f, 1.0f, 0.336f, 0.0f, -0.739f, 0.544f, 1.0f,
+ 0.336f, 0.0f, -0.732f, 0.534f, 1.0f, 0.335f, 0.0f, -0.725f, 0.521f, 1.0f, 0.334f, 0.0f, -0.718f, 0.505f, 1.0f, 0.333f, 0.0f, -0.711f, 0.487f, 1.0f,
+ 0.332f, 0.0f, -0.703f, 0.466f, 1.0f, 0.331f, 0.0f, -0.694f, 0.441f, 1.0f, 0.33f, 0.0f, -0.686f, 0.413f, 1.0f, 0.328f, 0.0f, -0.677f, 0.383f, 1.0f,
+ 0.326f, 0.0f, -0.667f, 0.35f, 1.0f, 0.325f, 0.0f, -0.657f, 0.316f, 1.0f, 0.323f, 0.0f, -0.647f, 0.281f, 1.0f, 0.32f, 0.0f, -0.636f, 0.246f, 1.0f,
+ 0.318f, 0.0f, -0.625f, 0.212f, 1.0f, 0.316f, 0.0f, -0.614f, 0.18f, 1.0f, 0.313f, 0.0f, -0.603f, 0.149f, 1.0f, 0.311f, 0.0f, -0.592f, 0.12f, 1.0f,
+ 0.308f, 0.0f, -0.581f, 0.093f, 1.0f, 0.306f, 0.0f, -0.57f, 0.069f, 1.0f, 0.303f, 0.0f, -0.559f, 0.046f, 1.0f, 0.301f, 0.0f, -0.55f, 0.027f, 1.0f,
+ 0.298f, 0.0f, -0.537f, 0.0f, 1.0f,
+};
+
+static const float data26[41 * GP_PRIM_DATABUF_SIZE] = {
+ -0.104f, 0.0f, -0.795f, 0.258f, 1.0f, -0.1f, 0.0f, -0.799f, 0.28f, 1.0f, -0.097f, 0.0f, -0.801f, 0.294f, 1.0f, -0.094f, 0.0f, -0.805f, 0.312f, 1.0f,
+ -0.09f, 0.0f, -0.808f, 0.328f, 1.0f, -0.086f, 0.0f, -0.811f, 0.345f, 1.0f, -0.082f, 0.0f, -0.815f, 0.361f, 1.0f, -0.078f, 0.0f, -0.818f, 0.377f, 1.0f,
+ -0.073f, 0.0f, -0.821f, 0.392f, 1.0f, -0.068f, 0.0f, -0.824f, 0.407f, 1.0f, -0.063f, 0.0f, -0.827f, 0.421f, 1.0f, -0.057f, 0.0f, -0.83f, 0.435f, 1.0f,
+ -0.051f, 0.0f, -0.833f, 0.448f, 1.0f, -0.045f, 0.0f, -0.835f, 0.46f, 1.0f, -0.039f, 0.0f, -0.837f, 0.471f, 1.0f, -0.033f, 0.0f, -0.839f, 0.481f, 1.0f,
+ -0.026f, 0.0f, -0.841f, 0.491f, 1.0f, -0.019f, 0.0f, -0.842f, 0.5f, 1.0f, -0.012f, 0.0f, -0.843f, 0.508f, 1.0f, -0.005f, 0.0f, -0.843f, 0.515f, 1.0f,
+ 0.002f, 0.0f, -0.843f, 0.522f, 1.0f, 0.009f, 0.0f, -0.843f, 0.527f, 1.0f, 0.016f, 0.0f, -0.842f, 0.532f, 1.0f, 0.023f, 0.0f, -0.841f, 0.535f, 1.0f,
+ 0.03f, 0.0f, -0.839f, 0.538f, 1.0f, 0.037f, 0.0f, -0.837f, 0.538f, 1.0f, 0.044f, 0.0f, -0.835f, 0.537f, 1.0f, 0.05f, 0.0f, -0.833f, 0.532f, 1.0f,
+ 0.056f, 0.0f, -0.83f, 0.524f, 1.0f, 0.062f, 0.0f, -0.827f, 0.513f, 1.0f, 0.068f, 0.0f, -0.823f, 0.496f, 1.0f, 0.074f, 0.0f, -0.82f, 0.474f, 1.0f,
+ 0.079f, 0.0f, -0.817f, 0.446f, 1.0f, 0.084f, 0.0f, -0.813f, 0.411f, 1.0f, 0.089f, 0.0f, -0.809f, 0.37f, 1.0f, 0.093f, 0.0f, -0.806f, 0.323f, 1.0f,
+ 0.098f, 0.0f, -0.802f, 0.269f, 1.0f, 0.102f, 0.0f, -0.798f, 0.211f, 1.0f, 0.106f, 0.0f, -0.795f, 0.146f, 1.0f, 0.109f, 0.0f, -0.792f, 0.089f, 1.0f,
+ 0.114f, 0.0f, -0.787f, 0.0f, 1.0f,
+};
+
+static const float data27[77 * GP_PRIM_DATABUF_SIZE] = {
+ -0.105f, 0.0f, -0.259f, 0.214f, 1.0f, -0.103f, 0.0f, -0.253f, 0.263f, 1.0f, -0.101f, 0.0f, -0.249f, 0.291f, 1.0f, -0.099f, 0.0f, -0.244f, 0.324f, 1.0f,
+ -0.098f, 0.0f, -0.24f, 0.351f, 1.0f, -0.096f, 0.0f, -0.235f, 0.376f, 1.0f, -0.094f, 0.0f, -0.231f, 0.397f, 1.0f, -0.092f, 0.0f, -0.227f, 0.416f, 1.0f,
+ -0.09f, 0.0f, -0.222f, 0.432f, 1.0f, -0.088f, 0.0f, -0.218f, 0.446f, 1.0f, -0.086f, 0.0f, -0.215f, 0.458f, 1.0f, -0.084f, 0.0f, -0.211f, 0.469f, 1.0f,
+ -0.082f, 0.0f, -0.208f, 0.478f, 1.0f, -0.079f, 0.0f, -0.205f, 0.486f, 1.0f, -0.077f, 0.0f, -0.203f, 0.494f, 1.0f, -0.075f, 0.0f, -0.2f, 0.501f, 1.0f,
+ -0.073f, 0.0f, -0.198f, 0.508f, 1.0f, -0.071f, 0.0f, -0.197f, 0.515f, 1.0f, -0.068f, 0.0f, -0.195f, 0.521f, 1.0f, -0.066f, 0.0f, -0.194f, 0.528f, 1.0f,
+ -0.064f, 0.0f, -0.194f, 0.534f, 1.0f, -0.061f, 0.0f, -0.194f, 0.54f, 1.0f, -0.059f, 0.0f, -0.194f, 0.546f, 1.0f, -0.056f, 0.0f, -0.194f, 0.551f, 1.0f,
+ -0.054f, 0.0f, -0.195f, 0.555f, 1.0f, -0.051f, 0.0f, -0.196f, 0.559f, 1.0f, -0.049f, 0.0f, -0.198f, 0.562f, 1.0f, -0.046f, 0.0f, -0.2f, 0.565f, 1.0f,
+ -0.044f, 0.0f, -0.201f, 0.567f, 1.0f, -0.041f, 0.0f, -0.204f, 0.568f, 1.0f, -0.039f, 0.0f, -0.206f, 0.569f, 1.0f, -0.036f, 0.0f, -0.208f, 0.57f, 1.0f,
+ -0.034f, 0.0f, -0.21f, 0.571f, 1.0f, -0.032f, 0.0f, -0.213f, 0.571f, 1.0f, -0.029f, 0.0f, -0.215f, 0.571f, 1.0f, -0.027f, 0.0f, -0.217f, 0.572f, 1.0f,
+ -0.024f, 0.0f, -0.219f, 0.572f, 1.0f, -0.022f, 0.0f, -0.221f, 0.572f, 1.0f, -0.019f, 0.0f, -0.222f, 0.572f, 1.0f, -0.016f, 0.0f, -0.224f, 0.572f, 1.0f,
+ -0.013f, 0.0f, -0.225f, 0.572f, 1.0f, -0.01f, 0.0f, -0.226f, 0.573f, 1.0f, -0.007f, 0.0f, -0.227f, 0.573f, 1.0f, -0.004f, 0.0f, -0.227f, 0.573f, 1.0f,
+ -0.001f, 0.0f, -0.227f, 0.574f, 1.0f, 0.002f, 0.0f, -0.227f, 0.575f, 1.0f, 0.005f, 0.0f, -0.227f, 0.576f, 1.0f, 0.008f, 0.0f, -0.226f, 0.577f, 1.0f,
+ 0.011f, 0.0f, -0.225f, 0.578f, 1.0f, 0.015f, 0.0f, -0.224f, 0.579f, 1.0f, 0.018f, 0.0f, -0.222f, 0.58f, 1.0f, 0.021f, 0.0f, -0.221f, 0.581f, 1.0f,
+ 0.024f, 0.0f, -0.219f, 0.582f, 1.0f, 0.027f, 0.0f, -0.217f, 0.582f, 1.0f, 0.03f, 0.0f, -0.215f, 0.583f, 1.0f, 0.033f, 0.0f, -0.213f, 0.583f, 1.0f,
+ 0.036f, 0.0f, -0.212f, 0.583f, 1.0f, 0.039f, 0.0f, -0.21f, 0.583f, 1.0f, 0.042f, 0.0f, -0.208f, 0.583f, 1.0f, 0.045f, 0.0f, -0.207f, 0.583f, 1.0f,
+ 0.048f, 0.0f, -0.205f, 0.583f, 1.0f, 0.051f, 0.0f, -0.204f, 0.583f, 1.0f, 0.054f, 0.0f, -0.203f, 0.583f, 1.0f, 0.058f, 0.0f, -0.203f, 0.583f, 1.0f,
+ 0.061f, 0.0f, -0.202f, 0.583f, 1.0f, 0.064f, 0.0f, -0.202f, 0.574f, 1.0f, 0.067f, 0.0f, -0.202f, 0.565f, 1.0f, 0.07f, 0.0f, -0.203f, 0.556f, 1.0f,
+ 0.073f, 0.0f, -0.203f, 0.547f, 1.0f, 0.075f, 0.0f, -0.204f, 0.515f, 1.0f, 0.078f, 0.0f, -0.204f, 0.483f, 1.0f, 0.08f, 0.0f, -0.205f, 0.451f, 1.0f,
+ 0.083f, 0.0f, -0.206f, 0.419f, 1.0f, 0.085f, 0.0f, -0.207f, 0.314f, 1.0f, 0.087f, 0.0f, -0.208f, 0.21f, 1.0f, 0.089f, 0.0f, -0.209f, 0.105f, 1.0f,
+ 0.091f, 0.0f, -0.21f, 0.0f, 1.0f,
+};
+
+static const float data28[257 * GP_PRIM_DATABUF_SIZE] = {
+ -0.637f, 0.0f, -0.172f, 0.0f, 1.0f, -0.641f, 0.0f, -0.172f, 0.0f, 1.0f, -0.643f, 0.0f, -0.172f, 0.0f, 1.0f, -0.646f, 0.0f, -0.172f, 0.0f, 1.0f,
+ -0.65f, 0.0f, -0.172f, 0.0f, 1.0f, -0.653f, 0.0f, -0.172f, 0.0f, 1.0f, -0.657f, 0.0f, -0.172f, 0.0f, 1.0f, -0.66f, 0.0f, -0.172f, 0.0f, 1.0f,
+ -0.664f, 0.0f, -0.171f, 0.0f, 1.0f, -0.668f, 0.0f, -0.171f, 0.0f, 1.0f, -0.672f, 0.0f, -0.171f, 0.0f, 1.0f, -0.677f, 0.0f, -0.171f, 0.0f, 1.0f,
+ -0.681f, 0.0f, -0.171f, 0.0f, 1.0f, -0.685f, 0.0f, -0.171f, 0.0f, 1.0f, -0.69f, 0.0f, -0.17f, 0.0f, 1.0f, -0.694f, 0.0f, -0.17f, 0.0f, 1.0f,
+ -0.699f, 0.0f, -0.17f, 0.0f, 1.0f, -0.704f, 0.0f, -0.169f, 0.0f, 1.0f, -0.708f, 0.0f, -0.169f, 0.0f, 1.0f, -0.713f, 0.0f, -0.168f, 0.0f, 1.0f,
+ -0.717f, 0.0f, -0.168f, 0.0f, 1.0f, -0.722f, 0.0f, -0.167f, 0.0f, 1.0f, -0.727f, 0.0f, -0.167f, 0.0f, 1.0f, -0.731f, 0.0f, -0.166f, 0.0f, 1.0f,
+ -0.735f, 0.0f, -0.166f, 0.0f, 1.0f, -0.74f, 0.0f, -0.165f, 0.0f, 1.0f, -0.744f, 0.0f, -0.164f, 0.0f, 1.0f, -0.749f, 0.0f, -0.163f, 0.0f, 1.0f,
+ -0.753f, 0.0f, -0.163f, 0.0f, 1.0f, -0.757f, 0.0f, -0.162f, 0.0f, 1.0f, -0.761f, 0.0f, -0.161f, 0.0f, 1.0f, -0.765f, 0.0f, -0.16f, 0.0f, 1.0f,
+ -0.769f, 0.0f, -0.159f, 0.0f, 1.0f, -0.773f, 0.0f, -0.158f, 0.0f, 1.0f, -0.777f, 0.0f, -0.157f, 0.0f, 1.0f, -0.781f, 0.0f, -0.156f, 0.001f, 1.0f,
+ -0.785f, 0.0f, -0.155f, 0.001f, 1.0f, -0.789f, 0.0f, -0.154f, 0.002f, 1.0f, -0.793f, 0.0f, -0.153f, 0.003f, 1.0f, -0.797f, 0.0f, -0.152f, 0.004f, 1.0f,
+ -0.801f, 0.0f, -0.15f, 0.005f, 1.0f, -0.805f, 0.0f, -0.149f, 0.006f, 1.0f, -0.81f, 0.0f, -0.147f, 0.008f, 1.0f, -0.814f, 0.0f, -0.146f, 0.009f, 1.0f,
+ -0.818f, 0.0f, -0.144f, 0.011f, 1.0f, -0.823f, 0.0f, -0.143f, 0.014f, 1.0f, -0.827f, 0.0f, -0.141f, 0.016f, 1.0f, -0.831f, 0.0f, -0.139f, 0.019f, 1.0f,
+ -0.836f, 0.0f, -0.138f, 0.022f, 1.0f, -0.84f, 0.0f, -0.136f, 0.024f, 1.0f, -0.844f, 0.0f, -0.135f, 0.026f, 1.0f, -0.849f, 0.0f, -0.133f, 0.027f, 1.0f,
+ -0.853f, 0.0f, -0.131f, 0.027f, 1.0f, -0.857f, 0.0f, -0.13f, 0.027f, 1.0f, -0.861f, 0.0f, -0.128f, 0.027f, 1.0f, -0.865f, 0.0f, -0.126f, 0.027f, 1.0f,
+ -0.868f, 0.0f, -0.125f, 0.026f, 1.0f, -0.872f, 0.0f, -0.123f, 0.025f, 1.0f, -0.876f, 0.0f, -0.121f, 0.025f, 1.0f, -0.879f, 0.0f, -0.119f, 0.024f, 1.0f,
+ -0.883f, 0.0f, -0.118f, 0.023f, 1.0f, -0.886f, 0.0f, -0.116f, 0.022f, 1.0f, -0.89f, 0.0f, -0.114f, 0.022f, 1.0f, -0.894f, 0.0f, -0.112f, 0.021f, 1.0f,
+ -0.898f, 0.0f, -0.11f, 0.022f, 1.0f, -0.901f, 0.0f, -0.107f, 0.022f, 1.0f, -0.905f, 0.0f, -0.105f, 0.024f, 1.0f, -0.909f, 0.0f, -0.103f, 0.026f, 1.0f,
+ -0.913f, 0.0f, -0.1f, 0.029f, 1.0f, -0.917f, 0.0f, -0.098f, 0.032f, 1.0f, -0.921f, 0.0f, -0.095f, 0.035f, 1.0f, -0.926f, 0.0f, -0.092f, 0.039f, 1.0f,
+ -0.93f, 0.0f, -0.09f, 0.043f, 1.0f, -0.934f, 0.0f, -0.087f, 0.047f, 1.0f, -0.938f, 0.0f, -0.084f, 0.051f, 1.0f, -0.942f, 0.0f, -0.081f, 0.055f, 1.0f,
+ -0.946f, 0.0f, -0.078f, 0.06f, 1.0f, -0.95f, 0.0f, -0.075f, 0.065f, 1.0f, -0.954f, 0.0f, -0.073f, 0.07f, 1.0f, -0.958f, 0.0f, -0.07f, 0.075f, 1.0f,
+ -0.961f, 0.0f, -0.067f, 0.081f, 1.0f, -0.965f, 0.0f, -0.064f, 0.087f, 1.0f, -0.968f, 0.0f, -0.061f, 0.092f, 1.0f, -0.972f, 0.0f, -0.058f, 0.098f, 1.0f,
+ -0.975f, 0.0f, -0.055f, 0.103f, 1.0f, -0.979f, 0.0f, -0.053f, 0.108f, 1.0f, -0.982f, 0.0f, -0.05f, 0.112f, 1.0f, -0.985f, 0.0f, -0.047f, 0.116f, 1.0f,
+ -0.988f, 0.0f, -0.045f, 0.12f, 1.0f, -0.991f, 0.0f, -0.042f, 0.123f, 1.0f, -0.994f, 0.0f, -0.039f, 0.126f, 1.0f, -0.997f, 0.0f, -0.037f, 0.129f, 1.0f,
+ -1.0f, 0.0f, -0.034f, 0.131f, 1.0f, -1.003f, 0.0f, -0.031f, 0.133f, 1.0f, -1.005f, 0.0f, -0.029f, 0.135f, 1.0f, -1.008f, 0.0f, -0.026f, 0.137f, 1.0f,
+ -1.01f, 0.0f, -0.024f, 0.139f, 1.0f, -1.013f, 0.0f, -0.021f, 0.141f, 1.0f, -1.016f, 0.0f, -0.018f, 0.143f, 1.0f, -1.018f, 0.0f, -0.016f, 0.144f, 1.0f,
+ -1.02f, 0.0f, -0.013f, 0.146f, 1.0f, -1.023f, 0.0f, -0.011f, 0.148f, 1.0f, -1.025f, 0.0f, -0.008f, 0.149f, 1.0f, -1.027f, 0.0f, -0.006f, 0.151f, 1.0f,
+ -1.029f, 0.0f, -0.003f, 0.152f, 1.0f, -1.032f, 0.0f, -0.001f, 0.154f, 1.0f, -1.034f, 0.0f, 0.001f, 0.154f, 1.0f, -1.036f, 0.0f, 0.004f, 0.155f, 1.0f,
+ -1.038f, 0.0f, 0.006f, 0.156f, 1.0f, -1.041f, 0.0f, 0.008f, 0.156f, 1.0f, -1.043f, 0.0f, 0.01f, 0.157f, 1.0f, -1.045f, 0.0f, 0.013f, 0.157f, 1.0f,
+ -1.047f, 0.0f, 0.015f, 0.157f, 1.0f, -1.049f, 0.0f, 0.018f, 0.158f, 1.0f, -1.051f, 0.0f, 0.02f, 0.158f, 1.0f, -1.053f, 0.0f, 0.023f, 0.158f, 1.0f,
+ -1.055f, 0.0f, 0.025f, 0.158f, 1.0f, -1.057f, 0.0f, 0.028f, 0.158f, 1.0f, -1.059f, 0.0f, 0.03f, 0.158f, 1.0f, -1.061f, 0.0f, 0.033f, 0.158f, 1.0f,
+ -1.063f, 0.0f, 0.036f, 0.158f, 1.0f, -1.065f, 0.0f, 0.038f, 0.158f, 1.0f, -1.067f, 0.0f, 0.041f, 0.158f, 1.0f, -1.069f, 0.0f, 0.044f, 0.157f, 1.0f,
+ -1.071f, 0.0f, 0.047f, 0.157f, 1.0f, -1.073f, 0.0f, 0.049f, 0.156f, 1.0f, -1.074f, 0.0f, 0.052f, 0.155f, 1.0f, -1.076f, 0.0f, 0.055f, 0.154f, 1.0f,
+ -1.078f, 0.0f, 0.058f, 0.153f, 1.0f, -1.08f, 0.0f, 0.061f, 0.152f, 1.0f, -1.082f, 0.0f, 0.064f, 0.15f, 1.0f, -1.083f, 0.0f, 0.067f, 0.148f, 1.0f,
+ -1.085f, 0.0f, 0.07f, 0.146f, 1.0f, -1.087f, 0.0f, 0.073f, 0.144f, 1.0f, -1.089f, 0.0f, 0.076f, 0.142f, 1.0f, -1.091f, 0.0f, 0.08f, 0.14f, 1.0f,
+ -1.092f, 0.0f, 0.083f, 0.138f, 1.0f, -1.094f, 0.0f, 0.086f, 0.136f, 1.0f, -1.096f, 0.0f, 0.09f, 0.135f, 1.0f, -1.097f, 0.0f, 0.093f, 0.134f, 1.0f,
+ -1.099f, 0.0f, 0.096f, 0.134f, 1.0f, -1.101f, 0.0f, 0.1f, 0.134f, 1.0f, -1.103f, 0.0f, 0.103f, 0.136f, 1.0f, -1.104f, 0.0f, 0.107f, 0.139f, 1.0f,
+ -1.106f, 0.0f, 0.111f, 0.144f, 1.0f, -1.107f, 0.0f, 0.114f, 0.15f, 1.0f, -1.109f, 0.0f, 0.118f, 0.158f, 1.0f, -1.11f, 0.0f, 0.122f, 0.167f, 1.0f,
+ -1.111f, 0.0f, 0.126f, 0.178f, 1.0f, -1.113f, 0.0f, 0.13f, 0.191f, 1.0f, -1.114f, 0.0f, 0.134f, 0.205f, 1.0f, -1.115f, 0.0f, 0.138f, 0.22f, 1.0f,
+ -1.116f, 0.0f, 0.142f, 0.237f, 1.0f, -1.117f, 0.0f, 0.146f, 0.254f, 1.0f, -1.118f, 0.0f, 0.15f, 0.272f, 1.0f, -1.119f, 0.0f, 0.155f, 0.291f, 1.0f,
+ -1.119f, 0.0f, 0.159f, 0.31f, 1.0f, -1.12f, 0.0f, 0.163f, 0.329f, 1.0f, -1.121f, 0.0f, 0.167f, 0.348f, 1.0f, -1.121f, 0.0f, 0.172f, 0.367f, 1.0f,
+ -1.122f, 0.0f, 0.176f, 0.386f, 1.0f, -1.122f, 0.0f, 0.18f, 0.405f, 1.0f, -1.123f, 0.0f, 0.184f, 0.423f, 1.0f, -1.123f, 0.0f, 0.189f, 0.441f, 1.0f,
+ -1.124f, 0.0f, 0.193f, 0.458f, 1.0f, -1.124f, 0.0f, 0.197f, 0.475f, 1.0f, -1.124f, 0.0f, 0.202f, 0.492f, 1.0f, -1.124f, 0.0f, 0.206f, 0.508f, 1.0f,
+ -1.125f, 0.0f, 0.21f, 0.524f, 1.0f, -1.125f, 0.0f, 0.214f, 0.539f, 1.0f, -1.125f, 0.0f, 0.218f, 0.554f, 1.0f, -1.124f, 0.0f, 0.223f, 0.568f, 1.0f,
+ -1.124f, 0.0f, 0.227f, 0.581f, 1.0f, -1.124f, 0.0f, 0.231f, 0.593f, 1.0f, -1.124f, 0.0f, 0.235f, 0.604f, 1.0f, -1.123f, 0.0f, 0.239f, 0.614f, 1.0f,
+ -1.123f, 0.0f, 0.243f, 0.624f, 1.0f, -1.122f, 0.0f, 0.247f, 0.632f, 1.0f, -1.122f, 0.0f, 0.251f, 0.64f, 1.0f, -1.121f, 0.0f, 0.255f, 0.646f, 1.0f,
+ -1.121f, 0.0f, 0.258f, 0.653f, 1.0f, -1.12f, 0.0f, 0.262f, 0.658f, 1.0f, -1.119f, 0.0f, 0.266f, 0.663f, 1.0f, -1.118f, 0.0f, 0.269f, 0.668f, 1.0f,
+ -1.117f, 0.0f, 0.272f, 0.673f, 1.0f, -1.117f, 0.0f, 0.276f, 0.678f, 1.0f, -1.116f, 0.0f, 0.279f, 0.682f, 1.0f, -1.115f, 0.0f, 0.282f, 0.687f, 1.0f,
+ -1.113f, 0.0f, 0.285f, 0.692f, 1.0f, -1.112f, 0.0f, 0.289f, 0.697f, 1.0f, -1.111f, 0.0f, 0.292f, 0.702f, 1.0f, -1.11f, 0.0f, 0.294f, 0.708f, 1.0f,
+ -1.109f, 0.0f, 0.297f, 0.713f, 1.0f, -1.108f, 0.0f, 0.3f, 0.718f, 1.0f, -1.106f, 0.0f, 0.303f, 0.724f, 1.0f, -1.105f, 0.0f, 0.306f, 0.73f, 1.0f,
+ -1.104f, 0.0f, 0.309f, 0.735f, 1.0f, -1.102f, 0.0f, 0.312f, 0.741f, 1.0f, -1.101f, 0.0f, 0.315f, 0.746f, 1.0f, -1.099f, 0.0f, 0.318f, 0.751f, 1.0f,
+ -1.098f, 0.0f, 0.321f, 0.756f, 1.0f, -1.096f, 0.0f, 0.323f, 0.761f, 1.0f, -1.094f, 0.0f, 0.326f, 0.766f, 1.0f, -1.093f, 0.0f, 0.329f, 0.771f, 1.0f,
+ -1.091f, 0.0f, 0.332f, 0.776f, 1.0f, -1.089f, 0.0f, 0.335f, 0.781f, 1.0f, -1.087f, 0.0f, 0.338f, 0.786f, 1.0f, -1.085f, 0.0f, 0.341f, 0.791f, 1.0f,
+ -1.082f, 0.0f, 0.344f, 0.797f, 1.0f, -1.08f, 0.0f, 0.347f, 0.802f, 1.0f, -1.078f, 0.0f, 0.349f, 0.808f, 1.0f, -1.075f, 0.0f, 0.352f, 0.814f, 1.0f,
+ -1.072f, 0.0f, 0.355f, 0.82f, 1.0f, -1.069f, 0.0f, 0.358f, 0.826f, 1.0f, -1.066f, 0.0f, 0.36f, 0.831f, 1.0f, -1.063f, 0.0f, 0.363f, 0.837f, 1.0f,
+ -1.059f, 0.0f, 0.366f, 0.842f, 1.0f, -1.055f, 0.0f, 0.368f, 0.847f, 1.0f, -1.051f, 0.0f, 0.371f, 0.851f, 1.0f, -1.047f, 0.0f, 0.373f, 0.856f, 1.0f,
+ -1.042f, 0.0f, 0.375f, 0.86f, 1.0f, -1.037f, 0.0f, 0.378f, 0.863f, 1.0f, -1.031f, 0.0f, 0.38f, 0.866f, 1.0f, -1.026f, 0.0f, 0.382f, 0.869f, 1.0f,
+ -1.02f, 0.0f, 0.384f, 0.871f, 1.0f, -1.014f, 0.0f, 0.386f, 0.873f, 1.0f, -1.007f, 0.0f, 0.387f, 0.875f, 1.0f, -1.0f, 0.0f, 0.389f, 0.876f, 1.0f,
+ -0.994f, 0.0f, 0.39f, 0.877f, 1.0f, -0.987f, 0.0f, 0.392f, 0.878f, 1.0f, -0.979f, 0.0f, 0.393f, 0.879f, 1.0f, -0.972f, 0.0f, 0.394f, 0.88f, 1.0f,
+ -0.964f, 0.0f, 0.395f, 0.881f, 1.0f, -0.956f, 0.0f, 0.395f, 0.881f, 1.0f, -0.948f, 0.0f, 0.395f, 0.882f, 1.0f, -0.94f, 0.0f, 0.395f, 0.882f, 1.0f,
+ -0.932f, 0.0f, 0.395f, 0.883f, 1.0f, -0.923f, 0.0f, 0.394f, 0.883f, 1.0f, -0.915f, 0.0f, 0.393f, 0.883f, 1.0f, -0.906f, 0.0f, 0.391f, 0.883f, 1.0f,
+ -0.896f, 0.0f, 0.389f, 0.881f, 1.0f, -0.887f, 0.0f, 0.386f, 0.876f, 1.0f, -0.877f, 0.0f, 0.382f, 0.866f, 1.0f, -0.867f, 0.0f, 0.378f, 0.85f, 1.0f,
+ -0.857f, 0.0f, 0.373f, 0.828f, 1.0f, -0.848f, 0.0f, 0.368f, 0.799f, 1.0f, -0.838f, 0.0f, 0.363f, 0.764f, 1.0f, -0.829f, 0.0f, 0.357f, 0.723f, 1.0f,
+ -0.819f, 0.0f, 0.352f, 0.679f, 1.0f, -0.811f, 0.0f, 0.347f, 0.631f, 1.0f, -0.802f, 0.0f, 0.342f, 0.579f, 1.0f, -0.794f, 0.0f, 0.338f, 0.525f, 1.0f,
+ -0.786f, 0.0f, 0.333f, 0.469f, 1.0f, -0.779f, 0.0f, 0.329f, 0.412f, 1.0f, -0.772f, 0.0f, 0.325f, 0.351f, 1.0f, -0.766f, 0.0f, 0.321f, 0.3f, 1.0f,
+ -0.757f, 0.0f, 0.317f, 0.219f, 1.0f,
+};
+
+static const float data29[205 * GP_PRIM_DATABUF_SIZE] = {
+ 0.816f, 0.0f, 0.326f, 0.285f, 1.0f, 0.819f, 0.0f, 0.328f, 0.287f, 1.0f, 0.821f, 0.0f, 0.33f, 0.29f, 1.0f, 0.823f, 0.0f, 0.331f, 0.295f, 1.0f,
+ 0.825f, 0.0f, 0.333f, 0.304f, 1.0f, 0.828f, 0.0f, 0.335f, 0.315f, 1.0f, 0.83f, 0.0f, 0.337f, 0.328f, 1.0f, 0.833f, 0.0f, 0.339f, 0.341f, 1.0f,
+ 0.836f, 0.0f, 0.341f, 0.355f, 1.0f, 0.839f, 0.0f, 0.343f, 0.368f, 1.0f, 0.842f, 0.0f, 0.345f, 0.38f, 1.0f, 0.845f, 0.0f, 0.347f, 0.392f, 1.0f,
+ 0.848f, 0.0f, 0.349f, 0.402f, 1.0f, 0.851f, 0.0f, 0.351f, 0.412f, 1.0f, 0.854f, 0.0f, 0.352f, 0.421f, 1.0f, 0.857f, 0.0f, 0.354f, 0.429f, 1.0f,
+ 0.861f, 0.0f, 0.356f, 0.437f, 1.0f, 0.865f, 0.0f, 0.357f, 0.444f, 1.0f, 0.869f, 0.0f, 0.359f, 0.452f, 1.0f, 0.872f, 0.0f, 0.36f, 0.46f, 1.0f,
+ 0.876f, 0.0f, 0.361f, 0.47f, 1.0f, 0.881f, 0.0f, 0.363f, 0.481f, 1.0f, 0.885f, 0.0f, 0.364f, 0.491f, 1.0f, 0.889f, 0.0f, 0.365f, 0.501f, 1.0f,
+ 0.893f, 0.0f, 0.366f, 0.511f, 1.0f, 0.898f, 0.0f, 0.367f, 0.52f, 1.0f, 0.902f, 0.0f, 0.368f, 0.528f, 1.0f, 0.906f, 0.0f, 0.37f, 0.535f, 1.0f,
+ 0.911f, 0.0f, 0.371f, 0.542f, 1.0f, 0.915f, 0.0f, 0.372f, 0.548f, 1.0f, 0.92f, 0.0f, 0.373f, 0.554f, 1.0f, 0.924f, 0.0f, 0.374f, 0.559f, 1.0f,
+ 0.929f, 0.0f, 0.375f, 0.564f, 1.0f, 0.933f, 0.0f, 0.376f, 0.567f, 1.0f, 0.938f, 0.0f, 0.377f, 0.57f, 1.0f, 0.943f, 0.0f, 0.378f, 0.572f, 1.0f,
+ 0.947f, 0.0f, 0.378f, 0.574f, 1.0f, 0.952f, 0.0f, 0.379f, 0.576f, 1.0f, 0.956f, 0.0f, 0.38f, 0.577f, 1.0f, 0.961f, 0.0f, 0.38f, 0.579f, 1.0f,
+ 0.966f, 0.0f, 0.381f, 0.581f, 1.0f, 0.971f, 0.0f, 0.381f, 0.585f, 1.0f, 0.975f, 0.0f, 0.382f, 0.588f, 1.0f, 0.98f, 0.0f, 0.382f, 0.591f, 1.0f,
+ 0.985f, 0.0f, 0.382f, 0.595f, 1.0f, 0.989f, 0.0f, 0.382f, 0.597f, 1.0f, 0.994f, 0.0f, 0.382f, 0.6f, 1.0f, 0.999f, 0.0f, 0.382f, 0.603f, 1.0f,
+ 1.003f, 0.0f, 0.382f, 0.605f, 1.0f, 1.008f, 0.0f, 0.381f, 0.607f, 1.0f, 1.013f, 0.0f, 0.381f, 0.61f, 1.0f, 1.017f, 0.0f, 0.381f, 0.611f, 1.0f,
+ 1.021f, 0.0f, 0.381f, 0.613f, 1.0f, 1.025f, 0.0f, 0.38f, 0.613f, 1.0f, 1.029f, 0.0f, 0.38f, 0.614f, 1.0f, 1.033f, 0.0f, 0.379f, 0.614f, 1.0f,
+ 1.037f, 0.0f, 0.379f, 0.614f, 1.0f, 1.041f, 0.0f, 0.378f, 0.614f, 1.0f, 1.044f, 0.0f, 0.378f, 0.614f, 1.0f, 1.048f, 0.0f, 0.377f, 0.614f, 1.0f,
+ 1.051f, 0.0f, 0.376f, 0.613f, 1.0f, 1.054f, 0.0f, 0.375f, 0.612f, 1.0f, 1.057f, 0.0f, 0.374f, 0.611f, 1.0f, 1.06f, 0.0f, 0.373f, 0.61f, 1.0f,
+ 1.063f, 0.0f, 0.372f, 0.609f, 1.0f, 1.066f, 0.0f, 0.371f, 0.609f, 1.0f, 1.068f, 0.0f, 0.37f, 0.608f, 1.0f, 1.071f, 0.0f, 0.368f, 0.608f, 1.0f,
+ 1.073f, 0.0f, 0.367f, 0.608f, 1.0f, 1.076f, 0.0f, 0.365f, 0.608f, 1.0f, 1.078f, 0.0f, 0.364f, 0.607f, 1.0f, 1.081f, 0.0f, 0.362f, 0.607f, 1.0f,
+ 1.083f, 0.0f, 0.36f, 0.607f, 1.0f, 1.085f, 0.0f, 0.358f, 0.606f, 1.0f, 1.087f, 0.0f, 0.356f, 0.606f, 1.0f, 1.09f, 0.0f, 0.354f, 0.606f, 1.0f,
+ 1.092f, 0.0f, 0.352f, 0.606f, 1.0f, 1.094f, 0.0f, 0.35f, 0.606f, 1.0f, 1.096f, 0.0f, 0.348f, 0.606f, 1.0f, 1.097f, 0.0f, 0.346f, 0.606f, 1.0f,
+ 1.099f, 0.0f, 0.344f, 0.606f, 1.0f, 1.101f, 0.0f, 0.341f, 0.606f, 1.0f, 1.103f, 0.0f, 0.339f, 0.606f, 1.0f, 1.104f, 0.0f, 0.337f, 0.607f, 1.0f,
+ 1.106f, 0.0f, 0.335f, 0.607f, 1.0f, 1.108f, 0.0f, 0.332f, 0.607f, 1.0f, 1.109f, 0.0f, 0.33f, 0.608f, 1.0f, 1.111f, 0.0f, 0.327f, 0.608f, 1.0f,
+ 1.113f, 0.0f, 0.324f, 0.608f, 1.0f, 1.114f, 0.0f, 0.322f, 0.609f, 1.0f, 1.116f, 0.0f, 0.319f, 0.609f, 1.0f, 1.117f, 0.0f, 0.316f, 0.609f, 1.0f,
+ 1.118f, 0.0f, 0.313f, 0.609f, 1.0f, 1.12f, 0.0f, 0.31f, 0.609f, 1.0f, 1.121f, 0.0f, 0.307f, 0.609f, 1.0f, 1.123f, 0.0f, 0.304f, 0.608f, 1.0f,
+ 1.124f, 0.0f, 0.301f, 0.608f, 1.0f, 1.125f, 0.0f, 0.297f, 0.607f, 1.0f, 1.126f, 0.0f, 0.294f, 0.606f, 1.0f, 1.127f, 0.0f, 0.29f, 0.605f, 1.0f,
+ 1.129f, 0.0f, 0.287f, 0.603f, 1.0f, 1.13f, 0.0f, 0.283f, 0.601f, 1.0f, 1.131f, 0.0f, 0.279f, 0.599f, 1.0f, 1.132f, 0.0f, 0.276f, 0.597f, 1.0f,
+ 1.132f, 0.0f, 0.272f, 0.595f, 1.0f, 1.133f, 0.0f, 0.268f, 0.593f, 1.0f, 1.134f, 0.0f, 0.264f, 0.592f, 1.0f, 1.135f, 0.0f, 0.26f, 0.591f, 1.0f,
+ 1.135f, 0.0f, 0.256f, 0.59f, 1.0f, 1.136f, 0.0f, 0.252f, 0.589f, 1.0f, 1.136f, 0.0f, 0.248f, 0.588f, 1.0f, 1.137f, 0.0f, 0.244f, 0.587f, 1.0f,
+ 1.137f, 0.0f, 0.24f, 0.586f, 1.0f, 1.138f, 0.0f, 0.236f, 0.585f, 1.0f, 1.138f, 0.0f, 0.232f, 0.584f, 1.0f, 1.138f, 0.0f, 0.228f, 0.582f, 1.0f,
+ 1.138f, 0.0f, 0.224f, 0.581f, 1.0f, 1.138f, 0.0f, 0.22f, 0.579f, 1.0f, 1.138f, 0.0f, 0.216f, 0.578f, 1.0f, 1.138f, 0.0f, 0.212f, 0.576f, 1.0f,
+ 1.138f, 0.0f, 0.208f, 0.575f, 1.0f, 1.138f, 0.0f, 0.204f, 0.573f, 1.0f, 1.137f, 0.0f, 0.2f, 0.572f, 1.0f, 1.137f, 0.0f, 0.196f, 0.571f, 1.0f,
+ 1.137f, 0.0f, 0.192f, 0.569f, 1.0f, 1.136f, 0.0f, 0.188f, 0.568f, 1.0f, 1.136f, 0.0f, 0.184f, 0.567f, 1.0f, 1.135f, 0.0f, 0.18f, 0.566f, 1.0f,
+ 1.134f, 0.0f, 0.176f, 0.565f, 1.0f, 1.133f, 0.0f, 0.172f, 0.563f, 1.0f, 1.132f, 0.0f, 0.168f, 0.561f, 1.0f, 1.131f, 0.0f, 0.164f, 0.559f, 1.0f,
+ 1.13f, 0.0f, 0.16f, 0.556f, 1.0f, 1.129f, 0.0f, 0.156f, 0.552f, 1.0f, 1.128f, 0.0f, 0.152f, 0.548f, 1.0f, 1.127f, 0.0f, 0.148f, 0.543f, 1.0f,
+ 1.126f, 0.0f, 0.144f, 0.537f, 1.0f, 1.124f, 0.0f, 0.14f, 0.53f, 1.0f, 1.123f, 0.0f, 0.136f, 0.522f, 1.0f, 1.122f, 0.0f, 0.132f, 0.514f, 1.0f,
+ 1.12f, 0.0f, 0.128f, 0.505f, 1.0f, 1.118f, 0.0f, 0.123f, 0.495f, 1.0f, 1.117f, 0.0f, 0.119f, 0.486f, 1.0f, 1.115f, 0.0f, 0.115f, 0.476f, 1.0f,
+ 1.113f, 0.0f, 0.111f, 0.466f, 1.0f, 1.111f, 0.0f, 0.107f, 0.456f, 1.0f, 1.11f, 0.0f, 0.102f, 0.446f, 1.0f, 1.108f, 0.0f, 0.098f, 0.436f, 1.0f,
+ 1.105f, 0.0f, 0.094f, 0.425f, 1.0f, 1.103f, 0.0f, 0.09f, 0.414f, 1.0f, 1.101f, 0.0f, 0.085f, 0.402f, 1.0f, 1.099f, 0.0f, 0.081f, 0.389f, 1.0f,
+ 1.096f, 0.0f, 0.077f, 0.377f, 1.0f, 1.094f, 0.0f, 0.072f, 0.364f, 1.0f, 1.091f, 0.0f, 0.068f, 0.351f, 1.0f, 1.088f, 0.0f, 0.063f, 0.338f, 1.0f,
+ 1.085f, 0.0f, 0.059f, 0.325f, 1.0f, 1.082f, 0.0f, 0.054f, 0.313f, 1.0f, 1.079f, 0.0f, 0.05f, 0.301f, 1.0f, 1.075f, 0.0f, 0.045f, 0.29f, 1.0f,
+ 1.071f, 0.0f, 0.04f, 0.281f, 1.0f, 1.067f, 0.0f, 0.035f, 0.272f, 1.0f, 1.063f, 0.0f, 0.031f, 0.266f, 1.0f, 1.059f, 0.0f, 0.026f, 0.261f, 1.0f,
+ 1.054f, 0.0f, 0.021f, 0.258f, 1.0f, 1.049f, 0.0f, 0.016f, 0.257f, 1.0f, 1.043f, 0.0f, 0.011f, 0.259f, 1.0f, 1.037f, 0.0f, 0.006f, 0.264f, 1.0f,
+ 1.031f, 0.0f, 0.0f, 0.272f, 1.0f, 1.025f, 0.0f, -0.005f, 0.283f, 1.0f, 1.018f, 0.0f, -0.01f, 0.296f, 1.0f, 1.011f, 0.0f, -0.015f, 0.313f, 1.0f,
+ 1.003f, 0.0f, -0.021f, 0.33f, 1.0f, 0.996f, 0.0f, -0.026f, 0.348f, 1.0f, 0.988f, 0.0f, -0.032f, 0.365f, 1.0f, 0.979f, 0.0f, -0.038f, 0.379f, 1.0f,
+ 0.971f, 0.0f, -0.044f, 0.389f, 1.0f, 0.962f, 0.0f, -0.05f, 0.394f, 1.0f, 0.953f, 0.0f, -0.057f, 0.392f, 1.0f, 0.944f, 0.0f, -0.063f, 0.384f, 1.0f,
+ 0.934f, 0.0f, -0.069f, 0.368f, 1.0f, 0.924f, 0.0f, -0.075f, 0.347f, 1.0f, 0.914f, 0.0f, -0.081f, 0.32f, 1.0f, 0.903f, 0.0f, -0.087f, 0.289f, 1.0f,
+ 0.893f, 0.0f, -0.092f, 0.256f, 1.0f, 0.882f, 0.0f, -0.098f, 0.223f, 1.0f, 0.871f, 0.0f, -0.103f, 0.191f, 1.0f, 0.86f, 0.0f, -0.108f, 0.162f, 1.0f,
+ 0.849f, 0.0f, -0.112f, 0.136f, 1.0f, 0.838f, 0.0f, -0.117f, 0.112f, 1.0f, 0.827f, 0.0f, -0.121f, 0.091f, 1.0f, 0.815f, 0.0f, -0.125f, 0.074f, 1.0f,
+ 0.804f, 0.0f, -0.128f, 0.059f, 1.0f, 0.793f, 0.0f, -0.132f, 0.046f, 1.0f, 0.782f, 0.0f, -0.135f, 0.036f, 1.0f, 0.771f, 0.0f, -0.138f, 0.028f, 1.0f,
+ 0.76f, 0.0f, -0.141f, 0.021f, 1.0f, 0.749f, 0.0f, -0.144f, 0.016f, 1.0f, 0.738f, 0.0f, -0.147f, 0.012f, 1.0f, 0.728f, 0.0f, -0.149f, 0.009f, 1.0f,
+ 0.718f, 0.0f, -0.152f, 0.006f, 1.0f, 0.708f, 0.0f, -0.154f, 0.004f, 1.0f, 0.699f, 0.0f, -0.157f, 0.003f, 1.0f, 0.691f, 0.0f, -0.159f, 0.002f, 1.0f,
+ 0.68f, 0.0f, -0.162f, 0.0f, 1.0f,
+};
+
+static const float data30[33 * GP_PRIM_DATABUF_SIZE] = {
+ -1.02f, 0.0f, 0.179f, 0.21f, 1.0f, -1.014f, 0.0f, 0.182f, 0.301f, 1.0f, -1.01f, 0.0f, 0.184f, 0.36f, 1.0f, -1.004f, 0.0f, 0.186f, 0.426f, 1.0f,
+ -0.999f, 0.0f, 0.188f, 0.479f, 1.0f, -0.993f, 0.0f, 0.19f, 0.519f, 1.0f, -0.987f, 0.0f, 0.191f, 0.545f, 1.0f, -0.981f, 0.0f, 0.192f, 0.562f, 1.0f,
+ -0.975f, 0.0f, 0.193f, 0.575f, 1.0f, -0.968f, 0.0f, 0.193f, 0.582f, 1.0f, -0.961f, 0.0f, 0.193f, 0.587f, 1.0f, -0.954f, 0.0f, 0.191f, 0.592f, 1.0f,
+ -0.946f, 0.0f, 0.19f, 0.597f, 1.0f, -0.938f, 0.0f, 0.187f, 0.6f, 1.0f, -0.93f, 0.0f, 0.183f, 0.603f, 1.0f, -0.922f, 0.0f, 0.178f, 0.606f, 1.0f,
+ -0.913f, 0.0f, 0.173f, 0.608f, 1.0f, -0.905f, 0.0f, 0.168f, 0.61f, 1.0f, -0.898f, 0.0f, 0.162f, 0.612f, 1.0f, -0.89f, 0.0f, 0.156f, 0.613f, 1.0f,
+ -0.883f, 0.0f, 0.15f, 0.612f, 1.0f, -0.877f, 0.0f, 0.143f, 0.608f, 1.0f, -0.871f, 0.0f, 0.137f, 0.602f, 1.0f, -0.865f, 0.0f, 0.131f, 0.593f, 1.0f,
+ -0.86f, 0.0f, 0.125f, 0.577f, 1.0f, -0.855f, 0.0f, 0.12f, 0.554f, 1.0f, -0.85f, 0.0f, 0.114f, 0.524f, 1.0f, -0.846f, 0.0f, 0.109f, 0.487f, 1.0f,
+ -0.842f, 0.0f, 0.104f, 0.443f, 1.0f, -0.838f, 0.0f, 0.1f, 0.394f, 1.0f, -0.835f, 0.0f, 0.095f, 0.339f, 1.0f, -0.832f, 0.0f, 0.091f, 0.295f, 1.0f,
+ -0.828f, 0.0f, 0.086f, 0.227f, 1.0f,
+};
+
+static const float data31[37 * GP_PRIM_DATABUF_SIZE] = {
+ 0.777f, 0.0f, 0.096f, 0.278f, 1.0f, 0.779f, 0.0f, 0.1f, 0.307f, 1.0f, 0.781f, 0.0f, 0.103f, 0.326f, 1.0f, 0.782f, 0.0f, 0.106f, 0.349f, 1.0f,
+ 0.784f, 0.0f, 0.109f, 0.372f, 1.0f, 0.786f, 0.0f, 0.112f, 0.395f, 1.0f, 0.789f, 0.0f, 0.116f, 0.418f, 1.0f, 0.791f, 0.0f, 0.119f, 0.44f, 1.0f,
+ 0.794f, 0.0f, 0.123f, 0.462f, 1.0f, 0.798f, 0.0f, 0.127f, 0.484f, 1.0f, 0.801f, 0.0f, 0.13f, 0.504f, 1.0f, 0.806f, 0.0f, 0.134f, 0.522f, 1.0f,
+ 0.81f, 0.0f, 0.138f, 0.54f, 1.0f, 0.815f, 0.0f, 0.142f, 0.556f, 1.0f, 0.82f, 0.0f, 0.146f, 0.571f, 1.0f, 0.826f, 0.0f, 0.15f, 0.584f, 1.0f,
+ 0.832f, 0.0f, 0.154f, 0.596f, 1.0f, 0.839f, 0.0f, 0.159f, 0.607f, 1.0f, 0.846f, 0.0f, 0.163f, 0.616f, 1.0f, 0.854f, 0.0f, 0.166f, 0.623f, 1.0f,
+ 0.862f, 0.0f, 0.17f, 0.628f, 1.0f, 0.87f, 0.0f, 0.174f, 0.632f, 1.0f, 0.878f, 0.0f, 0.177f, 0.632f, 1.0f, 0.887f, 0.0f, 0.18f, 0.63f, 1.0f,
+ 0.895f, 0.0f, 0.183f, 0.623f, 1.0f, 0.903f, 0.0f, 0.186f, 0.611f, 1.0f, 0.912f, 0.0f, 0.188f, 0.592f, 1.0f, 0.92f, 0.0f, 0.19f, 0.567f, 1.0f,
+ 0.928f, 0.0f, 0.192f, 0.533f, 1.0f, 0.935f, 0.0f, 0.193f, 0.492f, 1.0f, 0.943f, 0.0f, 0.194f, 0.442f, 1.0f, 0.95f, 0.0f, 0.196f, 0.385f, 1.0f,
+ 0.957f, 0.0f, 0.197f, 0.321f, 1.0f, 0.963f, 0.0f, 0.197f, 0.253f, 1.0f, 0.97f, 0.0f, 0.198f, 0.175f, 1.0f, 0.975f, 0.0f, 0.199f, 0.107f, 1.0f,
+ 0.983f, 0.0f, 0.199f, 0.0f, 1.0f,
+};
+
+static const float data32[201 * GP_PRIM_DATABUF_SIZE] = {
+ -0.437f, 0.0f, 0.508f, 0.0f, 1.0f, -0.435f, 0.0f, 0.51f, 0.0f, 1.0f, -0.434f, 0.0f, 0.511f, 0.0f, 1.0f, -0.432f, 0.0f, 0.512f, 0.0f, 1.0f,
+ -0.43f, 0.0f, 0.513f, 0.0f, 1.0f, -0.428f, 0.0f, 0.514f, 0.001f, 1.0f, -0.426f, 0.0f, 0.515f, 0.002f, 1.0f, -0.424f, 0.0f, 0.517f, 0.004f, 1.0f,
+ -0.422f, 0.0f, 0.518f, 0.007f, 1.0f, -0.42f, 0.0f, 0.519f, 0.012f, 1.0f, -0.418f, 0.0f, 0.521f, 0.018f, 1.0f, -0.416f, 0.0f, 0.522f, 0.025f, 1.0f,
+ -0.414f, 0.0f, 0.523f, 0.034f, 1.0f, -0.411f, 0.0f, 0.525f, 0.043f, 1.0f, -0.409f, 0.0f, 0.526f, 0.053f, 1.0f, -0.407f, 0.0f, 0.528f, 0.063f, 1.0f,
+ -0.404f, 0.0f, 0.529f, 0.073f, 1.0f, -0.402f, 0.0f, 0.531f, 0.083f, 1.0f, -0.399f, 0.0f, 0.532f, 0.092f, 1.0f, -0.396f, 0.0f, 0.534f, 0.101f, 1.0f,
+ -0.394f, 0.0f, 0.535f, 0.11f, 1.0f, -0.391f, 0.0f, 0.536f, 0.118f, 1.0f, -0.388f, 0.0f, 0.538f, 0.126f, 1.0f, -0.386f, 0.0f, 0.539f, 0.133f, 1.0f,
+ -0.383f, 0.0f, 0.54f, 0.14f, 1.0f, -0.38f, 0.0f, 0.542f, 0.147f, 1.0f, -0.377f, 0.0f, 0.543f, 0.153f, 1.0f, -0.374f, 0.0f, 0.544f, 0.159f, 1.0f,
+ -0.37f, 0.0f, 0.545f, 0.166f, 1.0f, -0.367f, 0.0f, 0.546f, 0.172f, 1.0f, -0.364f, 0.0f, 0.547f, 0.179f, 1.0f, -0.361f, 0.0f, 0.548f, 0.186f, 1.0f,
+ -0.357f, 0.0f, 0.549f, 0.193f, 1.0f, -0.354f, 0.0f, 0.55f, 0.202f, 1.0f, -0.35f, 0.0f, 0.551f, 0.211f, 1.0f, -0.347f, 0.0f, 0.552f, 0.221f, 1.0f,
+ -0.343f, 0.0f, 0.552f, 0.233f, 1.0f, -0.339f, 0.0f, 0.553f, 0.245f, 1.0f, -0.336f, 0.0f, 0.553f, 0.258f, 1.0f, -0.332f, 0.0f, 0.554f, 0.272f, 1.0f,
+ -0.328f, 0.0f, 0.554f, 0.286f, 1.0f, -0.324f, 0.0f, 0.554f, 0.301f, 1.0f, -0.321f, 0.0f, 0.555f, 0.317f, 1.0f, -0.317f, 0.0f, 0.555f, 0.332f, 1.0f,
+ -0.313f, 0.0f, 0.555f, 0.348f, 1.0f, -0.309f, 0.0f, 0.555f, 0.364f, 1.0f, -0.305f, 0.0f, 0.555f, 0.38f, 1.0f, -0.302f, 0.0f, 0.555f, 0.396f, 1.0f,
+ -0.298f, 0.0f, 0.555f, 0.411f, 1.0f, -0.294f, 0.0f, 0.555f, 0.426f, 1.0f, -0.29f, 0.0f, 0.554f, 0.44f, 1.0f, -0.287f, 0.0f, 0.554f, 0.454f, 1.0f,
+ -0.283f, 0.0f, 0.554f, 0.467f, 1.0f, -0.28f, 0.0f, 0.553f, 0.479f, 1.0f, -0.276f, 0.0f, 0.553f, 0.49f, 1.0f, -0.273f, 0.0f, 0.552f, 0.5f, 1.0f,
+ -0.269f, 0.0f, 0.552f, 0.51f, 1.0f, -0.266f, 0.0f, 0.551f, 0.519f, 1.0f, -0.263f, 0.0f, 0.55f, 0.527f, 1.0f, -0.26f, 0.0f, 0.549f, 0.534f, 1.0f,
+ -0.256f, 0.0f, 0.549f, 0.541f, 1.0f, -0.253f, 0.0f, 0.548f, 0.547f, 1.0f, -0.25f, 0.0f, 0.547f, 0.552f, 1.0f, -0.247f, 0.0f, 0.546f, 0.557f, 1.0f,
+ -0.244f, 0.0f, 0.545f, 0.561f, 1.0f, -0.241f, 0.0f, 0.544f, 0.564f, 1.0f, -0.238f, 0.0f, 0.543f, 0.567f, 1.0f, -0.235f, 0.0f, 0.542f, 0.57f, 1.0f,
+ -0.233f, 0.0f, 0.541f, 0.572f, 1.0f, -0.23f, 0.0f, 0.54f, 0.574f, 1.0f, -0.227f, 0.0f, 0.539f, 0.575f, 1.0f, -0.224f, 0.0f, 0.538f, 0.576f, 1.0f,
+ -0.221f, 0.0f, 0.537f, 0.577f, 1.0f, -0.219f, 0.0f, 0.535f, 0.578f, 1.0f, -0.216f, 0.0f, 0.534f, 0.578f, 1.0f, -0.213f, 0.0f, 0.533f, 0.579f, 1.0f,
+ -0.211f, 0.0f, 0.532f, 0.579f, 1.0f, -0.208f, 0.0f, 0.53f, 0.579f, 1.0f, -0.206f, 0.0f, 0.529f, 0.578f, 1.0f, -0.203f, 0.0f, 0.528f, 0.578f, 1.0f,
+ -0.2f, 0.0f, 0.526f, 0.577f, 1.0f, -0.198f, 0.0f, 0.525f, 0.576f, 1.0f, -0.195f, 0.0f, 0.523f, 0.575f, 1.0f, -0.193f, 0.0f, 0.522f, 0.574f, 1.0f,
+ -0.19f, 0.0f, 0.52f, 0.572f, 1.0f, -0.188f, 0.0f, 0.518f, 0.571f, 1.0f, -0.185f, 0.0f, 0.517f, 0.569f, 1.0f, -0.182f, 0.0f, 0.515f, 0.568f, 1.0f,
+ -0.18f, 0.0f, 0.513f, 0.567f, 1.0f, -0.177f, 0.0f, 0.512f, 0.565f, 1.0f, -0.174f, 0.0f, 0.51f, 0.564f, 1.0f, -0.172f, 0.0f, 0.508f, 0.562f, 1.0f,
+ -0.169f, 0.0f, 0.506f, 0.56f, 1.0f, -0.166f, 0.0f, 0.504f, 0.559f, 1.0f, -0.164f, 0.0f, 0.502f, 0.556f, 1.0f, -0.161f, 0.0f, 0.501f, 0.554f, 1.0f,
+ -0.158f, 0.0f, 0.499f, 0.552f, 1.0f, -0.155f, 0.0f, 0.497f, 0.55f, 1.0f, -0.153f, 0.0f, 0.495f, 0.547f, 1.0f, -0.15f, 0.0f, 0.493f, 0.545f, 1.0f,
+ -0.147f, 0.0f, 0.491f, 0.543f, 1.0f, -0.144f, 0.0f, 0.489f, 0.54f, 1.0f, -0.142f, 0.0f, 0.487f, 0.538f, 1.0f, -0.139f, 0.0f, 0.485f, 0.536f, 1.0f,
+ -0.136f, 0.0f, 0.483f, 0.533f, 1.0f, -0.133f, 0.0f, 0.481f, 0.53f, 1.0f, -0.13f, 0.0f, 0.479f, 0.527f, 1.0f, -0.127f, 0.0f, 0.477f, 0.524f, 1.0f,
+ -0.124f, 0.0f, 0.475f, 0.521f, 1.0f, -0.121f, 0.0f, 0.473f, 0.519f, 1.0f, -0.118f, 0.0f, 0.471f, 0.516f, 1.0f, -0.115f, 0.0f, 0.469f, 0.514f, 1.0f,
+ -0.112f, 0.0f, 0.467f, 0.511f, 1.0f, -0.109f, 0.0f, 0.465f, 0.509f, 1.0f, -0.106f, 0.0f, 0.463f, 0.506f, 1.0f, -0.103f, 0.0f, 0.461f, 0.503f, 1.0f,
+ -0.099f, 0.0f, 0.458f, 0.501f, 1.0f, -0.096f, 0.0f, 0.456f, 0.5f, 1.0f, -0.093f, 0.0f, 0.454f, 0.498f, 1.0f, -0.09f, 0.0f, 0.452f, 0.497f, 1.0f,
+ -0.086f, 0.0f, 0.45f, 0.496f, 1.0f, -0.083f, 0.0f, 0.448f, 0.496f, 1.0f, -0.079f, 0.0f, 0.446f, 0.495f, 1.0f, -0.076f, 0.0f, 0.444f, 0.495f, 1.0f,
+ -0.072f, 0.0f, 0.442f, 0.494f, 1.0f, -0.069f, 0.0f, 0.44f, 0.494f, 1.0f, -0.065f, 0.0f, 0.438f, 0.494f, 1.0f, -0.062f, 0.0f, 0.436f, 0.494f, 1.0f,
+ -0.058f, 0.0f, 0.435f, 0.494f, 1.0f, -0.054f, 0.0f, 0.433f, 0.494f, 1.0f, -0.05f, 0.0f, 0.431f, 0.494f, 1.0f, -0.046f, 0.0f, 0.43f, 0.494f, 1.0f,
+ -0.042f, 0.0f, 0.428f, 0.494f, 1.0f, -0.038f, 0.0f, 0.427f, 0.494f, 1.0f, -0.033f, 0.0f, 0.426f, 0.494f, 1.0f, -0.029f, 0.0f, 0.425f, 0.494f, 1.0f,
+ -0.025f, 0.0f, 0.424f, 0.494f, 1.0f, -0.02f, 0.0f, 0.423f, 0.494f, 1.0f, -0.015f, 0.0f, 0.422f, 0.494f, 1.0f, -0.011f, 0.0f, 0.422f, 0.494f, 1.0f,
+ -0.006f, 0.0f, 0.421f, 0.494f, 1.0f, -0.001f, 0.0f, 0.421f, 0.495f, 1.0f, 0.004f, 0.0f, 0.421f, 0.495f, 1.0f, 0.009f, 0.0f, 0.421f, 0.495f, 1.0f,
+ 0.014f, 0.0f, 0.422f, 0.495f, 1.0f, 0.019f, 0.0f, 0.422f, 0.495f, 1.0f, 0.024f, 0.0f, 0.423f, 0.495f, 1.0f, 0.029f, 0.0f, 0.424f, 0.495f, 1.0f,
+ 0.034f, 0.0f, 0.426f, 0.495f, 1.0f, 0.039f, 0.0f, 0.427f, 0.495f, 1.0f, 0.044f, 0.0f, 0.429f, 0.496f, 1.0f, 0.049f, 0.0f, 0.43f, 0.497f, 1.0f,
+ 0.054f, 0.0f, 0.432f, 0.498f, 1.0f, 0.059f, 0.0f, 0.435f, 0.5f, 1.0f, 0.064f, 0.0f, 0.438f, 0.502f, 1.0f, 0.069f, 0.0f, 0.44f, 0.506f, 1.0f,
+ 0.074f, 0.0f, 0.443f, 0.51f, 1.0f, 0.08f, 0.0f, 0.446f, 0.516f, 1.0f, 0.085f, 0.0f, 0.45f, 0.522f, 1.0f, 0.09f, 0.0f, 0.453f, 0.528f, 1.0f,
+ 0.095f, 0.0f, 0.456f, 0.533f, 1.0f, 0.101f, 0.0f, 0.46f, 0.537f, 1.0f, 0.107f, 0.0f, 0.463f, 0.539f, 1.0f, 0.112f, 0.0f, 0.467f, 0.542f, 1.0f,
+ 0.118f, 0.0f, 0.471f, 0.543f, 1.0f, 0.124f, 0.0f, 0.475f, 0.545f, 1.0f, 0.13f, 0.0f, 0.478f, 0.546f, 1.0f, 0.137f, 0.0f, 0.482f, 0.546f, 1.0f,
+ 0.143f, 0.0f, 0.486f, 0.547f, 1.0f, 0.149f, 0.0f, 0.49f, 0.546f, 1.0f, 0.156f, 0.0f, 0.493f, 0.544f, 1.0f, 0.163f, 0.0f, 0.497f, 0.54f, 1.0f,
+ 0.17f, 0.0f, 0.5f, 0.533f, 1.0f, 0.176f, 0.0f, 0.503f, 0.525f, 1.0f, 0.183f, 0.0f, 0.507f, 0.515f, 1.0f, 0.191f, 0.0f, 0.509f, 0.503f, 1.0f,
+ 0.198f, 0.0f, 0.512f, 0.491f, 1.0f, 0.205f, 0.0f, 0.515f, 0.477f, 1.0f, 0.214f, 0.0f, 0.518f, 0.462f, 1.0f, 0.222f, 0.0f, 0.521f, 0.445f, 1.0f,
+ 0.23f, 0.0f, 0.524f, 0.427f, 1.0f, 0.238f, 0.0f, 0.527f, 0.409f, 1.0f, 0.245f, 0.0f, 0.529f, 0.388f, 1.0f, 0.254f, 0.0f, 0.531f, 0.366f, 1.0f,
+ 0.262f, 0.0f, 0.532f, 0.343f, 1.0f, 0.272f, 0.0f, 0.533f, 0.317f, 1.0f, 0.282f, 0.0f, 0.534f, 0.289f, 1.0f, 0.292f, 0.0f, 0.535f, 0.258f, 1.0f,
+ 0.301f, 0.0f, 0.535f, 0.224f, 1.0f, 0.311f, 0.0f, 0.536f, 0.189f, 1.0f, 0.32f, 0.0f, 0.536f, 0.153f, 1.0f, 0.328f, 0.0f, 0.536f, 0.117f, 1.0f,
+ 0.338f, 0.0f, 0.537f, 0.084f, 1.0f, 0.346f, 0.0f, 0.537f, 0.057f, 1.0f, 0.353f, 0.0f, 0.536f, 0.037f, 1.0f, 0.361f, 0.0f, 0.536f, 0.022f, 1.0f,
+ 0.37f, 0.0f, 0.537f, 0.013f, 1.0f, 0.376f, 0.0f, 0.536f, 0.007f, 1.0f, 0.384f, 0.0f, 0.536f, 0.004f, 1.0f, 0.39f, 0.0f, 0.536f, 0.002f, 1.0f,
+ 0.399f, 0.0f, 0.535f, 0.0f, 1.0f,
+};
+
+static const float data33[69 * GP_PRIM_DATABUF_SIZE] = {
+ -0.308f, 0.0f, 0.151f, 0.363f, 1.0f, -0.31f, 0.0f, 0.15f, 0.377f, 1.0f, -0.311f, 0.0f, 0.149f, 0.386f, 1.0f, -0.313f, 0.0f, 0.149f, 0.397f, 1.0f,
+ -0.314f, 0.0f, 0.149f, 0.408f, 1.0f, -0.316f, 0.0f, 0.148f, 0.42f, 1.0f, -0.318f, 0.0f, 0.148f, 0.431f, 1.0f, -0.32f, 0.0f, 0.148f, 0.443f, 1.0f,
+ -0.322f, 0.0f, 0.148f, 0.455f, 1.0f, -0.325f, 0.0f, 0.149f, 0.467f, 1.0f, -0.327f, 0.0f, 0.149f, 0.478f, 1.0f, -0.33f, 0.0f, 0.151f, 0.49f, 1.0f,
+ -0.333f, 0.0f, 0.152f, 0.501f, 1.0f, -0.336f, 0.0f, 0.154f, 0.512f, 1.0f, -0.34f, 0.0f, 0.157f, 0.522f, 1.0f, -0.343f, 0.0f, 0.161f, 0.533f, 1.0f,
+ -0.346f, 0.0f, 0.166f, 0.543f, 1.0f, -0.349f, 0.0f, 0.171f, 0.553f, 1.0f, -0.351f, 0.0f, 0.178f, 0.563f, 1.0f, -0.352f, 0.0f, 0.186f, 0.572f, 1.0f,
+ -0.353f, 0.0f, 0.193f, 0.582f, 1.0f, -0.352f, 0.0f, 0.2f, 0.591f, 1.0f, -0.351f, 0.0f, 0.206f, 0.6f, 1.0f, -0.349f, 0.0f, 0.211f, 0.608f, 1.0f,
+ -0.347f, 0.0f, 0.215f, 0.616f, 1.0f, -0.345f, 0.0f, 0.219f, 0.623f, 1.0f, -0.343f, 0.0f, 0.222f, 0.63f, 1.0f, -0.341f, 0.0f, 0.224f, 0.637f, 1.0f,
+ -0.339f, 0.0f, 0.226f, 0.642f, 1.0f, -0.337f, 0.0f, 0.228f, 0.647f, 1.0f, -0.335f, 0.0f, 0.229f, 0.652f, 1.0f, -0.333f, 0.0f, 0.23f, 0.656f, 1.0f,
+ -0.332f, 0.0f, 0.231f, 0.66f, 1.0f, -0.33f, 0.0f, 0.232f, 0.663f, 1.0f, -0.328f, 0.0f, 0.232f, 0.666f, 1.0f, -0.327f, 0.0f, 0.233f, 0.669f, 1.0f,
+ -0.325f, 0.0f, 0.233f, 0.672f, 1.0f, -0.324f, 0.0f, 0.234f, 0.676f, 1.0f, -0.322f, 0.0f, 0.234f, 0.679f, 1.0f, -0.321f, 0.0f, 0.234f, 0.682f, 1.0f,
+ -0.319f, 0.0f, 0.234f, 0.686f, 1.0f, -0.317f, 0.0f, 0.234f, 0.689f, 1.0f, -0.316f, 0.0f, 0.234f, 0.693f, 1.0f, -0.314f, 0.0f, 0.234f, 0.697f, 1.0f,
+ -0.312f, 0.0f, 0.233f, 0.701f, 1.0f, -0.31f, 0.0f, 0.232f, 0.705f, 1.0f, -0.307f, 0.0f, 0.231f, 0.709f, 1.0f, -0.305f, 0.0f, 0.23f, 0.713f, 1.0f,
+ -0.302f, 0.0f, 0.228f, 0.716f, 1.0f, -0.299f, 0.0f, 0.225f, 0.719f, 1.0f, -0.295f, 0.0f, 0.222f, 0.722f, 1.0f, -0.292f, 0.0f, 0.217f, 0.725f, 1.0f,
+ -0.289f, 0.0f, 0.21f, 0.727f, 1.0f, -0.287f, 0.0f, 0.202f, 0.728f, 1.0f, -0.285f, 0.0f, 0.194f, 0.729f, 1.0f, -0.286f, 0.0f, 0.185f, 0.729f, 1.0f,
+ -0.287f, 0.0f, 0.178f, 0.728f, 1.0f, -0.289f, 0.0f, 0.171f, 0.726f, 1.0f, -0.292f, 0.0f, 0.166f, 0.723f, 1.0f, -0.294f, 0.0f, 0.162f, 0.717f, 1.0f,
+ -0.297f, 0.0f, 0.159f, 0.71f, 1.0f, -0.299f, 0.0f, 0.157f, 0.701f, 1.0f, -0.301f, 0.0f, 0.155f, 0.689f, 1.0f, -0.303f, 0.0f, 0.154f, 0.675f, 1.0f,
+ -0.305f, 0.0f, 0.152f, 0.659f, 1.0f, -0.306f, 0.0f, 0.151f, 0.641f, 1.0f, -0.308f, 0.0f, 0.151f, 0.62f, 1.0f, -0.309f, 0.0f, 0.15f, 0.602f, 1.0f,
+ -0.31f, 0.0f, 0.15f, 0.572f, 1.0f,
+};
+
+static const float data34[57 * GP_PRIM_DATABUF_SIZE] = {
+ 0.302f, 0.0f, 0.166f, 0.25f, 1.0f, 0.301f, 0.0f, 0.167f, 0.319f, 1.0f, 0.3f, 0.0f, 0.167f, 0.363f, 1.0f, 0.299f, 0.0f, 0.167f, 0.414f, 1.0f,
+ 0.298f, 0.0f, 0.167f, 0.459f, 1.0f, 0.296f, 0.0f, 0.168f, 0.501f, 1.0f, 0.295f, 0.0f, 0.168f, 0.539f, 1.0f, 0.293f, 0.0f, 0.169f, 0.573f, 1.0f,
+ 0.291f, 0.0f, 0.17f, 0.603f, 1.0f, 0.289f, 0.0f, 0.171f, 0.629f, 1.0f, 0.286f, 0.0f, 0.173f, 0.652f, 1.0f, 0.283f, 0.0f, 0.176f, 0.672f, 1.0f,
+ 0.279f, 0.0f, 0.18f, 0.69f, 1.0f, 0.276f, 0.0f, 0.186f, 0.705f, 1.0f, 0.272f, 0.0f, 0.195f, 0.719f, 1.0f, 0.271f, 0.0f, 0.205f, 0.73f, 1.0f,
+ 0.272f, 0.0f, 0.217f, 0.741f, 1.0f, 0.275f, 0.0f, 0.227f, 0.75f, 1.0f, 0.279f, 0.0f, 0.234f, 0.758f, 1.0f, 0.283f, 0.0f, 0.24f, 0.765f, 1.0f,
+ 0.287f, 0.0f, 0.243f, 0.771f, 1.0f, 0.291f, 0.0f, 0.245f, 0.776f, 1.0f, 0.294f, 0.0f, 0.247f, 0.781f, 1.0f, 0.296f, 0.0f, 0.248f, 0.785f, 1.0f,
+ 0.299f, 0.0f, 0.249f, 0.789f, 1.0f, 0.301f, 0.0f, 0.249f, 0.793f, 1.0f, 0.303f, 0.0f, 0.249f, 0.796f, 1.0f, 0.305f, 0.0f, 0.25f, 0.799f, 1.0f,
+ 0.306f, 0.0f, 0.25f, 0.802f, 1.0f, 0.308f, 0.0f, 0.249f, 0.805f, 1.0f, 0.31f, 0.0f, 0.249f, 0.808f, 1.0f, 0.311f, 0.0f, 0.249f, 0.81f, 1.0f,
+ 0.313f, 0.0f, 0.249f, 0.813f, 1.0f, 0.314f, 0.0f, 0.248f, 0.816f, 1.0f, 0.316f, 0.0f, 0.248f, 0.819f, 1.0f, 0.317f, 0.0f, 0.247f, 0.822f, 1.0f,
+ 0.319f, 0.0f, 0.246f, 0.825f, 1.0f, 0.321f, 0.0f, 0.245f, 0.828f, 1.0f, 0.323f, 0.0f, 0.244f, 0.832f, 1.0f, 0.325f, 0.0f, 0.243f, 0.835f, 1.0f,
+ 0.328f, 0.0f, 0.24f, 0.838f, 1.0f, 0.33f, 0.0f, 0.237f, 0.841f, 1.0f, 0.333f, 0.0f, 0.233f, 0.844f, 1.0f, 0.337f, 0.0f, 0.228f, 0.847f, 1.0f,
+ 0.339f, 0.0f, 0.219f, 0.849f, 1.0f, 0.341f, 0.0f, 0.209f, 0.852f, 1.0f, 0.34f, 0.0f, 0.197f, 0.854f, 1.0f, 0.336f, 0.0f, 0.186f, 0.856f, 1.0f,
+ 0.331f, 0.0f, 0.178f, 0.858f, 1.0f, 0.325f, 0.0f, 0.173f, 0.86f, 1.0f, 0.321f, 0.0f, 0.17f, 0.861f, 1.0f, 0.318f, 0.0f, 0.169f, 0.862f, 1.0f,
+ 0.315f, 0.0f, 0.168f, 0.864f, 1.0f, 0.312f, 0.0f, 0.167f, 0.865f, 1.0f, 0.311f, 0.0f, 0.167f, 0.866f, 1.0f, 0.309f, 0.0f, 0.166f, 0.867f, 1.0f,
+ 0.308f, 0.0f, 0.166f, 0.868f, 1.0f,
+};
+
+static const float data35[261 * GP_PRIM_DATABUF_SIZE] = {
+ -0.685f, 0.0f, 0.408f, 0.0f, 1.0f, -0.683f, 0.0f, 0.41f, 0.023f, 1.0f, -0.681f, 0.0f, 0.412f, 0.051f, 1.0f, -0.679f, 0.0f, 0.414f, 0.092f, 1.0f,
+ -0.678f, 0.0f, 0.415f, 0.125f, 1.0f, -0.676f, 0.0f, 0.417f, 0.149f, 1.0f, -0.674f, 0.0f, 0.419f, 0.167f, 1.0f, -0.672f, 0.0f, 0.42f, 0.183f, 1.0f,
+ -0.67f, 0.0f, 0.422f, 0.199f, 1.0f, -0.668f, 0.0f, 0.424f, 0.218f, 1.0f, -0.666f, 0.0f, 0.426f, 0.237f, 1.0f, -0.664f, 0.0f, 0.429f, 0.257f, 1.0f,
+ -0.661f, 0.0f, 0.431f, 0.275f, 1.0f, -0.659f, 0.0f, 0.434f, 0.291f, 1.0f, -0.657f, 0.0f, 0.436f, 0.305f, 1.0f, -0.655f, 0.0f, 0.439f, 0.315f, 1.0f,
+ -0.653f, 0.0f, 0.442f, 0.322f, 1.0f, -0.65f, 0.0f, 0.444f, 0.327f, 1.0f, -0.648f, 0.0f, 0.447f, 0.331f, 1.0f, -0.646f, 0.0f, 0.45f, 0.334f, 1.0f,
+ -0.643f, 0.0f, 0.453f, 0.334f, 1.0f, -0.641f, 0.0f, 0.456f, 0.334f, 1.0f, -0.639f, 0.0f, 0.459f, 0.334f, 1.0f, -0.636f, 0.0f, 0.462f, 0.333f, 1.0f,
+ -0.634f, 0.0f, 0.466f, 0.332f, 1.0f, -0.631f, 0.0f, 0.469f, 0.332f, 1.0f, -0.628f, 0.0f, 0.473f, 0.332f, 1.0f, -0.625f, 0.0f, 0.476f, 0.333f, 1.0f,
+ -0.622f, 0.0f, 0.48f, 0.335f, 1.0f, -0.618f, 0.0f, 0.483f, 0.338f, 1.0f, -0.615f, 0.0f, 0.488f, 0.342f, 1.0f, -0.611f, 0.0f, 0.492f, 0.347f, 1.0f,
+ -0.608f, 0.0f, 0.495f, 0.352f, 1.0f, -0.605f, 0.0f, 0.5f, 0.358f, 1.0f, -0.601f, 0.0f, 0.505f, 0.363f, 1.0f, -0.597f, 0.0f, 0.509f, 0.366f, 1.0f,
+ -0.593f, 0.0f, 0.514f, 0.367f, 1.0f, -0.589f, 0.0f, 0.518f, 0.367f, 1.0f, -0.585f, 0.0f, 0.522f, 0.369f, 1.0f, -0.582f, 0.0f, 0.526f, 0.372f, 1.0f,
+ -0.578f, 0.0f, 0.531f, 0.376f, 1.0f, -0.575f, 0.0f, 0.535f, 0.382f, 1.0f, -0.571f, 0.0f, 0.539f, 0.388f, 1.0f, -0.567f, 0.0f, 0.543f, 0.394f, 1.0f,
+ -0.563f, 0.0f, 0.547f, 0.4f, 1.0f, -0.56f, 0.0f, 0.551f, 0.406f, 1.0f, -0.556f, 0.0f, 0.555f, 0.411f, 1.0f, -0.552f, 0.0f, 0.559f, 0.415f, 1.0f,
+ -0.548f, 0.0f, 0.563f, 0.418f, 1.0f, -0.544f, 0.0f, 0.566f, 0.419f, 1.0f, -0.54f, 0.0f, 0.569f, 0.42f, 1.0f, -0.537f, 0.0f, 0.572f, 0.421f, 1.0f,
+ -0.533f, 0.0f, 0.576f, 0.421f, 1.0f, -0.529f, 0.0f, 0.579f, 0.421f, 1.0f, -0.526f, 0.0f, 0.582f, 0.422f, 1.0f, -0.523f, 0.0f, 0.585f, 0.422f, 1.0f,
+ -0.52f, 0.0f, 0.588f, 0.423f, 1.0f, -0.516f, 0.0f, 0.591f, 0.426f, 1.0f, -0.513f, 0.0f, 0.594f, 0.43f, 1.0f, -0.51f, 0.0f, 0.597f, 0.435f, 1.0f,
+ -0.507f, 0.0f, 0.6f, 0.441f, 1.0f, -0.504f, 0.0f, 0.603f, 0.447f, 1.0f, -0.501f, 0.0f, 0.606f, 0.453f, 1.0f, -0.498f, 0.0f, 0.609f, 0.458f, 1.0f,
+ -0.496f, 0.0f, 0.611f, 0.461f, 1.0f, -0.493f, 0.0f, 0.614f, 0.465f, 1.0f, -0.49f, 0.0f, 0.616f, 0.468f, 1.0f, -0.487f, 0.0f, 0.619f, 0.472f, 1.0f,
+ -0.484f, 0.0f, 0.621f, 0.476f, 1.0f, -0.482f, 0.0f, 0.624f, 0.48f, 1.0f, -0.479f, 0.0f, 0.627f, 0.484f, 1.0f, -0.476f, 0.0f, 0.629f, 0.487f, 1.0f,
+ -0.473f, 0.0f, 0.632f, 0.491f, 1.0f, -0.471f, 0.0f, 0.634f, 0.495f, 1.0f, -0.468f, 0.0f, 0.637f, 0.499f, 1.0f, -0.465f, 0.0f, 0.639f, 0.504f, 1.0f,
+ -0.462f, 0.0f, 0.641f, 0.508f, 1.0f, -0.459f, 0.0f, 0.643f, 0.513f, 1.0f, -0.456f, 0.0f, 0.646f, 0.519f, 1.0f, -0.453f, 0.0f, 0.648f, 0.525f, 1.0f,
+ -0.45f, 0.0f, 0.65f, 0.533f, 1.0f, -0.447f, 0.0f, 0.652f, 0.54f, 1.0f, -0.444f, 0.0f, 0.655f, 0.546f, 1.0f, -0.441f, 0.0f, 0.657f, 0.553f, 1.0f,
+ -0.438f, 0.0f, 0.659f, 0.56f, 1.0f, -0.435f, 0.0f, 0.662f, 0.567f, 1.0f, -0.432f, 0.0f, 0.664f, 0.574f, 1.0f, -0.429f, 0.0f, 0.666f, 0.58f, 1.0f,
+ -0.426f, 0.0f, 0.669f, 0.585f, 1.0f, -0.423f, 0.0f, 0.671f, 0.591f, 1.0f, -0.419f, 0.0f, 0.673f, 0.595f, 1.0f, -0.416f, 0.0f, 0.675f, 0.6f, 1.0f,
+ -0.412f, 0.0f, 0.678f, 0.604f, 1.0f, -0.409f, 0.0f, 0.68f, 0.609f, 1.0f, -0.405f, 0.0f, 0.682f, 0.613f, 1.0f, -0.401f, 0.0f, 0.684f, 0.618f, 1.0f,
+ -0.398f, 0.0f, 0.687f, 0.622f, 1.0f, -0.394f, 0.0f, 0.689f, 0.627f, 1.0f, -0.39f, 0.0f, 0.692f, 0.632f, 1.0f, -0.386f, 0.0f, 0.694f, 0.638f, 1.0f,
+ -0.381f, 0.0f, 0.697f, 0.643f, 1.0f, -0.377f, 0.0f, 0.7f, 0.649f, 1.0f, -0.373f, 0.0f, 0.702f, 0.654f, 1.0f, -0.368f, 0.0f, 0.705f, 0.659f, 1.0f,
+ -0.363f, 0.0f, 0.707f, 0.663f, 1.0f, -0.359f, 0.0f, 0.71f, 0.667f, 1.0f, -0.354f, 0.0f, 0.712f, 0.671f, 1.0f, -0.349f, 0.0f, 0.715f, 0.674f, 1.0f,
+ -0.345f, 0.0f, 0.717f, 0.677f, 1.0f, -0.34f, 0.0f, 0.72f, 0.68f, 1.0f, -0.335f, 0.0f, 0.722f, 0.683f, 1.0f, -0.33f, 0.0f, 0.725f, 0.685f, 1.0f,
+ -0.326f, 0.0f, 0.727f, 0.687f, 1.0f, -0.321f, 0.0f, 0.73f, 0.689f, 1.0f, -0.316f, 0.0f, 0.732f, 0.691f, 1.0f, -0.312f, 0.0f, 0.734f, 0.693f, 1.0f,
+ -0.307f, 0.0f, 0.736f, 0.694f, 1.0f, -0.302f, 0.0f, 0.738f, 0.696f, 1.0f, -0.298f, 0.0f, 0.74f, 0.697f, 1.0f, -0.293f, 0.0f, 0.741f, 0.698f, 1.0f,
+ -0.288f, 0.0f, 0.743f, 0.699f, 1.0f, -0.284f, 0.0f, 0.745f, 0.699f, 1.0f, -0.279f, 0.0f, 0.746f, 0.7f, 1.0f, -0.275f, 0.0f, 0.748f, 0.701f, 1.0f,
+ -0.27f, 0.0f, 0.749f, 0.702f, 1.0f, -0.265f, 0.0f, 0.751f, 0.702f, 1.0f, -0.261f, 0.0f, 0.752f, 0.704f, 1.0f, -0.256f, 0.0f, 0.753f, 0.705f, 1.0f,
+ -0.252f, 0.0f, 0.755f, 0.706f, 1.0f, -0.247f, 0.0f, 0.756f, 0.707f, 1.0f, -0.242f, 0.0f, 0.757f, 0.709f, 1.0f, -0.237f, 0.0f, 0.758f, 0.711f, 1.0f,
+ -0.233f, 0.0f, 0.759f, 0.713f, 1.0f, -0.228f, 0.0f, 0.761f, 0.715f, 1.0f, -0.223f, 0.0f, 0.762f, 0.717f, 1.0f, -0.218f, 0.0f, 0.763f, 0.719f, 1.0f,
+ -0.213f, 0.0f, 0.764f, 0.721f, 1.0f, -0.209f, 0.0f, 0.765f, 0.723f, 1.0f, -0.204f, 0.0f, 0.765f, 0.726f, 1.0f, -0.199f, 0.0f, 0.766f, 0.728f, 1.0f,
+ -0.194f, 0.0f, 0.767f, 0.73f, 1.0f, -0.189f, 0.0f, 0.768f, 0.731f, 1.0f, -0.183f, 0.0f, 0.769f, 0.733f, 1.0f, -0.178f, 0.0f, 0.77f, 0.735f, 1.0f,
+ -0.173f, 0.0f, 0.77f, 0.736f, 1.0f, -0.168f, 0.0f, 0.771f, 0.738f, 1.0f, -0.163f, 0.0f, 0.772f, 0.739f, 1.0f, -0.158f, 0.0f, 0.772f, 0.741f, 1.0f,
+ -0.152f, 0.0f, 0.773f, 0.742f, 1.0f, -0.147f, 0.0f, 0.774f, 0.744f, 1.0f, -0.142f, 0.0f, 0.774f, 0.746f, 1.0f, -0.137f, 0.0f, 0.775f, 0.748f, 1.0f,
+ -0.132f, 0.0f, 0.775f, 0.749f, 1.0f, -0.127f, 0.0f, 0.776f, 0.751f, 1.0f, -0.122f, 0.0f, 0.776f, 0.752f, 1.0f, -0.117f, 0.0f, 0.776f, 0.753f, 1.0f,
+ -0.112f, 0.0f, 0.777f, 0.754f, 1.0f, -0.108f, 0.0f, 0.777f, 0.755f, 1.0f, -0.103f, 0.0f, 0.777f, 0.755f, 1.0f, -0.099f, 0.0f, 0.777f, 0.756f, 1.0f,
+ -0.095f, 0.0f, 0.778f, 0.757f, 1.0f, -0.09f, 0.0f, 0.778f, 0.758f, 1.0f, -0.086f, 0.0f, 0.778f, 0.759f, 1.0f, -0.082f, 0.0f, 0.778f, 0.759f, 1.0f,
+ -0.077f, 0.0f, 0.778f, 0.76f, 1.0f, -0.073f, 0.0f, 0.779f, 0.76f, 1.0f, -0.069f, 0.0f, 0.779f, 0.761f, 1.0f, -0.064f, 0.0f, 0.779f, 0.761f, 1.0f,
+ -0.06f, 0.0f, 0.779f, 0.761f, 1.0f, -0.055f, 0.0f, 0.78f, 0.762f, 1.0f, -0.051f, 0.0f, 0.78f, 0.762f, 1.0f, -0.046f, 0.0f, 0.78f, 0.762f, 1.0f,
+ -0.041f, 0.0f, 0.78f, 0.762f, 1.0f, -0.037f, 0.0f, 0.781f, 0.762f, 1.0f, -0.032f, 0.0f, 0.781f, 0.763f, 1.0f, -0.027f, 0.0f, 0.781f, 0.763f, 1.0f,
+ -0.022f, 0.0f, 0.781f, 0.763f, 1.0f, -0.017f, 0.0f, 0.781f, 0.764f, 1.0f, -0.012f, 0.0f, 0.782f, 0.764f, 1.0f, -0.006f, 0.0f, 0.782f, 0.764f, 1.0f,
+ -0.001f, 0.0f, 0.782f, 0.765f, 1.0f, 0.004f, 0.0f, 0.782f, 0.766f, 1.0f, 0.009f, 0.0f, 0.782f, 0.766f, 1.0f, 0.015f, 0.0f, 0.782f, 0.767f, 1.0f,
+ 0.02f, 0.0f, 0.782f, 0.768f, 1.0f, 0.025f, 0.0f, 0.782f, 0.769f, 1.0f, 0.031f, 0.0f, 0.782f, 0.77f, 1.0f, 0.036f, 0.0f, 0.782f, 0.771f, 1.0f,
+ 0.042f, 0.0f, 0.782f, 0.772f, 1.0f, 0.048f, 0.0f, 0.782f, 0.773f, 1.0f, 0.053f, 0.0f, 0.782f, 0.774f, 1.0f, 0.059f, 0.0f, 0.782f, 0.775f, 1.0f,
+ 0.065f, 0.0f, 0.782f, 0.775f, 1.0f, 0.07f, 0.0f, 0.782f, 0.776f, 1.0f, 0.076f, 0.0f, 0.782f, 0.776f, 1.0f, 0.082f, 0.0f, 0.782f, 0.776f, 1.0f,
+ 0.088f, 0.0f, 0.782f, 0.776f, 1.0f, 0.094f, 0.0f, 0.782f, 0.777f, 1.0f, 0.1f, 0.0f, 0.781f, 0.777f, 1.0f, 0.106f, 0.0f, 0.781f, 0.778f, 1.0f,
+ 0.111f, 0.0f, 0.781f, 0.779f, 1.0f, 0.117f, 0.0f, 0.781f, 0.779f, 1.0f, 0.123f, 0.0f, 0.781f, 0.78f, 1.0f, 0.129f, 0.0f, 0.78f, 0.78f, 1.0f,
+ 0.135f, 0.0f, 0.78f, 0.781f, 1.0f, 0.141f, 0.0f, 0.779f, 0.781f, 1.0f, 0.147f, 0.0f, 0.779f, 0.782f, 1.0f, 0.153f, 0.0f, 0.778f, 0.783f, 1.0f,
+ 0.159f, 0.0f, 0.777f, 0.784f, 1.0f, 0.165f, 0.0f, 0.776f, 0.785f, 1.0f, 0.171f, 0.0f, 0.775f, 0.786f, 1.0f, 0.178f, 0.0f, 0.774f, 0.787f, 1.0f,
+ 0.185f, 0.0f, 0.773f, 0.788f, 1.0f, 0.192f, 0.0f, 0.772f, 0.789f, 1.0f, 0.2f, 0.0f, 0.771f, 0.79f, 1.0f, 0.208f, 0.0f, 0.77f, 0.791f, 1.0f,
+ 0.218f, 0.0f, 0.768f, 0.793f, 1.0f, 0.228f, 0.0f, 0.766f, 0.796f, 1.0f, 0.239f, 0.0f, 0.764f, 0.799f, 1.0f, 0.25f, 0.0f, 0.762f, 0.802f, 1.0f,
+ 0.261f, 0.0f, 0.759f, 0.806f, 1.0f, 0.271f, 0.0f, 0.755f, 0.81f, 1.0f, 0.282f, 0.0f, 0.752f, 0.815f, 1.0f, 0.293f, 0.0f, 0.748f, 0.819f, 1.0f,
+ 0.304f, 0.0f, 0.744f, 0.825f, 1.0f, 0.315f, 0.0f, 0.74f, 0.83f, 1.0f, 0.326f, 0.0f, 0.736f, 0.836f, 1.0f, 0.337f, 0.0f, 0.731f, 0.843f, 1.0f,
+ 0.349f, 0.0f, 0.727f, 0.85f, 1.0f, 0.361f, 0.0f, 0.722f, 0.858f, 1.0f, 0.372f, 0.0f, 0.718f, 0.866f, 1.0f, 0.384f, 0.0f, 0.712f, 0.874f, 1.0f,
+ 0.395f, 0.0f, 0.706f, 0.882f, 1.0f, 0.407f, 0.0f, 0.7f, 0.89f, 1.0f, 0.418f, 0.0f, 0.693f, 0.898f, 1.0f, 0.43f, 0.0f, 0.685f, 0.905f, 1.0f,
+ 0.442f, 0.0f, 0.677f, 0.912f, 1.0f, 0.458f, 0.0f, 0.666f, 0.918f, 1.0f, 0.473f, 0.0f, 0.654f, 0.924f, 1.0f, 0.49f, 0.0f, 0.64f, 0.93f, 1.0f,
+ 0.506f, 0.0f, 0.625f, 0.935f, 1.0f, 0.522f, 0.0f, 0.611f, 0.939f, 1.0f, 0.538f, 0.0f, 0.596f, 0.941f, 1.0f, 0.554f, 0.0f, 0.58f, 0.942f, 1.0f,
+ 0.569f, 0.0f, 0.564f, 0.941f, 1.0f, 0.584f, 0.0f, 0.548f, 0.935f, 1.0f, 0.598f, 0.0f, 0.533f, 0.925f, 1.0f, 0.612f, 0.0f, 0.517f, 0.91f, 1.0f,
+ 0.625f, 0.0f, 0.501f, 0.891f, 1.0f, 0.638f, 0.0f, 0.484f, 0.868f, 1.0f, 0.65f, 0.0f, 0.468f, 0.839f, 1.0f, 0.662f, 0.0f, 0.452f, 0.806f, 1.0f,
+ 0.671f, 0.0f, 0.437f, 0.766f, 1.0f, 0.679f, 0.0f, 0.423f, 0.718f, 1.0f, 0.685f, 0.0f, 0.412f, 0.661f, 1.0f, 0.691f, 0.0f, 0.403f, 0.595f, 1.0f,
+ 0.697f, 0.0f, 0.396f, 0.519f, 1.0f, 0.701f, 0.0f, 0.391f, 0.44f, 1.0f, 0.704f, 0.0f, 0.387f, 0.344f, 1.0f, 0.707f, 0.0f, 0.384f, 0.264f, 1.0f,
+ 0.711f, 0.0f, 0.38f, 0.133f, 1.0f,
+};
+
+/* ***************************************************************** */
+/* Monkey Color Data */
+
+static const ColorTemplate gp_monkey_pct_black = {
+ "Black",
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_monkey_pct_skin = {
+ "Skin",
+ {0.553f, 0.39f, 0.266f, 0.0f},
+ {0.733f, 0.567f, 0.359f, 1.0f},
+};
+
+static const ColorTemplate gp_monkey_pct_skin_light = {
+ "Skin_Light",
+ {0.553f, 0.39f, 0.266f, 0.0f},
+ {0.913f, 0.828f, 0.637f, 1.0f},
+};
+
+static const ColorTemplate gp_monkey_pct_skin_shadow = {
+ "Skin_Shadow",
+ {0.553f, 0.39f, 0.266f, 0.0f},
+ {0.32f, 0.29f, 0.223f, 1.0f},
+};
+
+static const ColorTemplate gp_monkey_pct_eyes = {
+ "Eyes",
+ {0.553f, 0.39f, 0.266f, 0.0f},
+ {0.773f, 0.762f, 0.73f, 1.0f},
+};
+
+static const ColorTemplate gp_monkey_pct_pupils = {
+ "Pupils",
+ {0.107f, 0.075f, 0.051f, 0.0f},
+ {0.153f, 0.057f, 0.063f, 1.0f},
+};
+
+/* ***************************************************************** */
+/* Monkey API */
+
+/* add a 2D Suzanne (original model created by Matias Mendiola) */
+void ED_gpencil_create_monkey(bContext *C, float mat[4][4])
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDstroke *gps;
+
+ /* create colors */
+ int color_Black = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_black);
+ int color_Skin = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin);
+ int color_Skin_Light = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_light);
+ int color_Skin_Shadow = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_skin_shadow);
+ int color_Eyes = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_eyes);
+ int color_Pupils = gpencil_monkey_color(bmain, ob, &gp_monkey_pct_pupils);
+
+ /* layers */
+ /* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */
+ bGPDlayer *Colors = BKE_gpencil_layer_addnew(gpd, "Colors", false);
+ bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+
+ /* frames */
+ /* NOTE: No need to check for existing, as this will tkae care of it for us */
+ bGPDframe *frameColor = BKE_gpencil_frame_addnew(Colors, cfra_eval);
+ bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, cfra_eval);
+
+ /* generate strokes */
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin, 538, 3);
+ BKE_gpencil_stroke_add_points(gps, data0, 538, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Eyes, 136, 3);
+ BKE_gpencil_stroke_add_points(gps, data1, 136, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin, 2, 3);
+ BKE_gpencil_stroke_add_points(gps, data2, 2, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 1, 3);
+ BKE_gpencil_stroke_add_points(gps, data3, 1, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 1, 3);
+ BKE_gpencil_stroke_add_points(gps, data4, 1, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 48, 3);
+ BKE_gpencil_stroke_add_points(gps, data5, 48, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 47, 3);
+ BKE_gpencil_stroke_add_points(gps, data6, 47, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 162, 3);
+ BKE_gpencil_stroke_add_points(gps, data7, 162, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 55, 3);
+ BKE_gpencil_stroke_add_points(gps, data8, 55, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 70, 3);
+ BKE_gpencil_stroke_add_points(gps, data9, 70, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Light, 227, 3);
+ BKE_gpencil_stroke_add_points(gps, data10, 227, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 1, 3);
+ BKE_gpencil_stroke_add_points(gps, data11, 1, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 123, 3);
+ BKE_gpencil_stroke_add_points(gps, data12, 123, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 125, 3);
+ BKE_gpencil_stroke_add_points(gps, data13, 125, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 45, 3);
+ BKE_gpencil_stroke_add_points(gps, data14, 45, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 44, 3);
+ BKE_gpencil_stroke_add_points(gps, data15, 44, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 84, 3);
+ BKE_gpencil_stroke_add_points(gps, data16, 84, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 56, 3);
+ BKE_gpencil_stroke_add_points(gps, data17, 56, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 59, 3);
+ BKE_gpencil_stroke_add_points(gps, data18, 59, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Skin_Shadow, 100, 3);
+ BKE_gpencil_stroke_add_points(gps, data19, 100, mat);
+
+ gps = BKE_gpencil_add_stroke(frameColor, color_Eyes, 136, 3);
+ BKE_gpencil_stroke_add_points(gps, data20, 136, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 353, 3);
+ BKE_gpencil_stroke_add_points(gps, data21, 353, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 309, 3);
+ BKE_gpencil_stroke_add_points(gps, data22, 309, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 209, 3);
+ BKE_gpencil_stroke_add_points(gps, data23, 209, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 133, 3);
+ BKE_gpencil_stroke_add_points(gps, data24, 133, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 389, 3);
+ BKE_gpencil_stroke_add_points(gps, data25, 389, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 41, 3);
+ BKE_gpencil_stroke_add_points(gps, data26, 41, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 77, 3);
+ BKE_gpencil_stroke_add_points(gps, data27, 77, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 257, 3);
+ BKE_gpencil_stroke_add_points(gps, data28, 257, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 205, 3);
+ BKE_gpencil_stroke_add_points(gps, data29, 205, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 3);
+ BKE_gpencil_stroke_add_points(gps, data30, 33, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 37, 3);
+ BKE_gpencil_stroke_add_points(gps, data31, 37, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 201, 3);
+ BKE_gpencil_stroke_add_points(gps, data32, 201, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 69, 3);
+ BKE_gpencil_stroke_add_points(gps, data33, 69, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 57, 3);
+ BKE_gpencil_stroke_add_points(gps, data34, 57, mat);
+
+ gps = BKE_gpencil_add_stroke(frameLines, color_Black, 261, 3);
+ BKE_gpencil_stroke_add_points(gps, data35, 261, mat);
+
+ /* update depsgraph */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+}
+
+
+/* ***************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
new file mode 100644
index 00000000000..c5020593bcb
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -0,0 +1,248 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Matias Mendiola
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_add_stroke.c
+ * \ingroup edgpencil
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+
+/* Definition of the most important info from a color */
+typedef struct ColorTemplate {
+ const char *name;
+ float line[4];
+ float fill[4];
+} ColorTemplate;
+
+/* Add color an ensure duplications (matched by name) */
+static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct)
+{
+ short *totcol = give_totcolp(ob);
+ Material *ma = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (STREQ(ma->id.name, pct->name)) {
+ return i;
+ }
+ }
+
+ /* create a new one */
+ BKE_object_material_slot_add(bmain, ob);
+ ma = BKE_material_add_gpencil(bmain, pct->name);
+ assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+
+ copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+
+ return BKE_gpencil_get_material_index(ob, ma) - 1;
+}
+
+/* ***************************************************************** */
+/* Stroke Geometry */
+
+static const float data0[175 * GP_PRIM_DATABUF_SIZE] = {
+ -1.281f, 0.0f, -0.315f, 0.038f, 1.0f, -1.269f, 0.0f, -0.302f, 0.069f, 1.0f,
+ -1.261f, 0.0f, -0.293f, 0.089f, 1.0f, -1.251f, 0.0f, -0.282f, 0.112f, 1.0f,
+ -1.241f, 0.0f, -0.271f, 0.134f, 1.0f, -1.23f, 0.0f, -0.259f, 0.155f, 1.0f,
+ -1.219f, 0.0f, -0.247f, 0.175f, 1.0f, -1.208f, 0.0f, -0.234f, 0.194f, 1.0f,
+ -1.196f, 0.0f, -0.221f, 0.211f, 1.0f, -1.184f, 0.0f, -0.208f, 0.227f, 1.0f,
+ -1.172f, 0.0f, -0.194f, 0.242f, 1.0f, -1.159f, 0.0f, -0.18f, 0.256f, 1.0f,
+ -1.147f, 0.0f, -0.165f, 0.268f, 1.0f, -1.134f, 0.0f, -0.151f, 0.28f, 1.0f,
+ -1.121f, 0.0f, -0.136f, 0.29f, 1.0f, -1.108f, 0.0f, -0.121f, 0.299f, 1.0f,
+ -1.094f, 0.0f, -0.106f, 0.307f, 1.0f, -1.08f, 0.0f, -0.091f, 0.315f, 1.0f,
+ -1.066f, 0.0f, -0.076f, 0.322f, 1.0f, -1.052f, 0.0f, -0.061f, 0.329f, 1.0f,
+ -1.037f, 0.0f, -0.047f, 0.335f, 1.0f, -1.022f, 0.0f, -0.032f, 0.341f, 1.0f,
+ -1.007f, 0.0f, -0.017f, 0.346f, 1.0f, -0.991f, 0.0f, -0.003f, 0.351f, 1.0f,
+ -0.975f, 0.0f, 0.012f, 0.355f, 1.0f, -0.959f, 0.0f, 0.027f, 0.36f, 1.0f,
+ -0.942f, 0.0f, 0.041f, 0.364f, 1.0f, -0.926f, 0.0f, 0.056f, 0.368f, 1.0f,
+ -0.909f, 0.0f, 0.071f, 0.371f, 1.0f, -0.893f, 0.0f, 0.086f, 0.373f, 1.0f,
+ -0.876f, 0.0f, 0.1f, 0.376f, 1.0f, -0.859f, 0.0f, 0.115f, 0.377f, 1.0f,
+ -0.842f, 0.0f, 0.129f, 0.378f, 1.0f, -0.824f, 0.0f, 0.144f, 0.379f, 1.0f,
+ -0.807f, 0.0f, 0.158f, 0.379f, 1.0f, -0.79f, 0.0f, 0.172f, 0.379f, 1.0f,
+ -0.773f, 0.0f, 0.186f, 0.38f, 1.0f, -0.755f, 0.0f, 0.199f, 0.38f, 1.0f,
+ -0.738f, 0.0f, 0.212f, 0.381f, 1.0f, -0.721f, 0.0f, 0.224f, 0.382f, 1.0f,
+ -0.703f, 0.0f, 0.236f, 0.384f, 1.0f, -0.686f, 0.0f, 0.248f, 0.386f, 1.0f,
+ -0.67f, 0.0f, 0.26f, 0.388f, 1.0f, -0.653f, 0.0f, 0.27f, 0.39f, 1.0f,
+ -0.637f, 0.0f, 0.28f, 0.393f, 1.0f, -0.621f, 0.0f, 0.29f, 0.396f, 1.0f,
+ -0.605f, 0.0f, 0.298f, 0.399f, 1.0f, -0.589f, 0.0f, 0.306f, 0.403f, 1.0f,
+ -0.574f, 0.0f, 0.313f, 0.407f, 1.0f, -0.559f, 0.0f, 0.319f, 0.411f, 1.0f,
+ -0.544f, 0.0f, 0.325f, 0.415f, 1.0f, -0.53f, 0.0f, 0.331f, 0.42f, 1.0f,
+ -0.516f, 0.0f, 0.336f, 0.425f, 1.0f, -0.503f, 0.0f, 0.34f, 0.431f, 1.0f,
+ -0.489f, 0.0f, 0.344f, 0.437f, 1.0f, -0.477f, 0.0f, 0.347f, 0.443f, 1.0f,
+ -0.464f, 0.0f, 0.35f, 0.45f, 1.0f, -0.452f, 0.0f, 0.352f, 0.457f, 1.0f,
+ -0.44f, 0.0f, 0.354f, 0.464f, 1.0f, -0.429f, 0.0f, 0.355f, 0.471f, 1.0f,
+ -0.418f, 0.0f, 0.355f, 0.479f, 1.0f, -0.407f, 0.0f, 0.355f, 0.487f, 1.0f,
+ -0.397f, 0.0f, 0.354f, 0.495f, 1.0f, -0.387f, 0.0f, 0.353f, 0.503f, 1.0f,
+ -0.378f, 0.0f, 0.351f, 0.512f, 1.0f, -0.368f, 0.0f, 0.348f, 0.52f, 1.0f,
+ -0.36f, 0.0f, 0.344f, 0.528f, 1.0f, -0.351f, 0.0f, 0.34f, 0.537f, 1.0f,
+ -0.344f, 0.0f, 0.336f, 0.545f, 1.0f, -0.336f, 0.0f, 0.33f, 0.553f, 1.0f,
+ -0.329f, 0.0f, 0.324f, 0.562f, 1.0f, -0.322f, 0.0f, 0.318f, 0.57f, 1.0f,
+ -0.316f, 0.0f, 0.31f, 0.579f, 1.0f, -0.311f, 0.0f, 0.303f, 0.588f, 1.0f,
+ -0.306f, 0.0f, 0.294f, 0.597f, 1.0f, -0.301f, 0.0f, 0.285f, 0.606f, 1.0f,
+ -0.297f, 0.0f, 0.275f, 0.615f, 1.0f, -0.293f, 0.0f, 0.264f, 0.625f, 1.0f,
+ -0.29f, 0.0f, 0.253f, 0.635f, 1.0f, -0.288f, 0.0f, 0.241f, 0.644f, 1.0f,
+ -0.286f, 0.0f, 0.229f, 0.654f, 1.0f, -0.285f, 0.0f, 0.216f, 0.664f, 1.0f,
+ -0.284f, 0.0f, 0.202f, 0.675f, 1.0f, -0.283f, 0.0f, 0.188f, 0.685f, 1.0f,
+ -0.283f, 0.0f, 0.173f, 0.696f, 1.0f, -0.284f, 0.0f, 0.158f, 0.707f, 1.0f,
+ -0.285f, 0.0f, 0.142f, 0.718f, 1.0f, -0.286f, 0.0f, 0.125f, 0.729f, 1.0f,
+ -0.288f, 0.0f, 0.108f, 0.74f, 1.0f, -0.29f, 0.0f, 0.091f, 0.751f, 1.0f,
+ -0.293f, 0.0f, 0.073f, 0.761f, 1.0f, -0.295f, 0.0f, 0.054f, 0.772f, 1.0f,
+ -0.298f, 0.0f, 0.035f, 0.782f, 1.0f, -0.302f, 0.0f, 0.016f, 0.793f, 1.0f,
+ -0.305f, 0.0f, -0.004f, 0.804f, 1.0f, -0.309f, 0.0f, -0.024f, 0.815f, 1.0f,
+ -0.313f, 0.0f, -0.044f, 0.828f, 1.0f, -0.317f, 0.0f, -0.065f, 0.843f, 1.0f,
+ -0.321f, 0.0f, -0.085f, 0.86f, 1.0f, -0.326f, 0.0f, -0.106f, 0.879f, 1.0f,
+ -0.33f, 0.0f, -0.127f, 0.897f, 1.0f, -0.335f, 0.0f, -0.148f, 0.915f, 1.0f,
+ -0.339f, 0.0f, -0.168f, 0.932f, 1.0f, -0.344f, 0.0f, -0.189f, 0.947f, 1.0f,
+ -0.348f, 0.0f, -0.21f, 0.962f, 1.0f, -0.353f, 0.0f, -0.23f, 0.974f, 1.0f,
+ -0.357f, 0.0f, -0.25f, 0.985f, 1.0f, -0.361f, 0.0f, -0.27f, 0.995f, 1.0f,
+ -0.365f, 0.0f, -0.29f, 1.004f, 1.0f, -0.369f, 0.0f, -0.309f, 1.011f, 1.0f,
+ -0.372f, 0.0f, -0.328f, 1.018f, 1.0f, -0.375f, 0.0f, -0.347f, 1.024f, 1.0f,
+ -0.377f, 0.0f, -0.365f, 1.029f, 1.0f, -0.379f, 0.0f, -0.383f, 1.033f, 1.0f,
+ -0.38f, 0.0f, -0.4f, 1.036f, 1.0f, -0.38f, 0.0f, -0.417f, 1.037f, 1.0f,
+ -0.38f, 0.0f, -0.434f, 1.037f, 1.0f, -0.379f, 0.0f, -0.449f, 1.035f, 1.0f,
+ -0.377f, 0.0f, -0.464f, 1.032f, 1.0f, -0.374f, 0.0f, -0.478f, 1.029f, 1.0f,
+ -0.371f, 0.0f, -0.491f, 1.026f, 1.0f, -0.366f, 0.0f, -0.503f, 1.023f, 1.0f,
+ -0.361f, 0.0f, -0.513f, 1.021f, 1.0f, -0.354f, 0.0f, -0.523f, 1.019f, 1.0f,
+ -0.347f, 0.0f, -0.531f, 1.017f, 1.0f, -0.339f, 0.0f, -0.538f, 1.016f, 1.0f,
+ -0.33f, 0.0f, -0.543f, 1.016f, 1.0f, -0.32f, 0.0f, -0.547f, 1.016f, 1.0f,
+ -0.31f, 0.0f, -0.549f, 1.016f, 1.0f, -0.298f, 0.0f, -0.55f, 1.017f, 1.0f,
+ -0.286f, 0.0f, -0.55f, 1.017f, 1.0f, -0.274f, 0.0f, -0.548f, 1.018f, 1.0f,
+ -0.261f, 0.0f, -0.544f, 1.017f, 1.0f, -0.247f, 0.0f, -0.539f, 1.017f, 1.0f,
+ -0.232f, 0.0f, -0.533f, 1.016f, 1.0f, -0.218f, 0.0f, -0.525f, 1.015f, 1.0f,
+ -0.202f, 0.0f, -0.515f, 1.013f, 1.0f, -0.186f, 0.0f, -0.503f, 1.009f, 1.0f,
+ -0.169f, 0.0f, -0.49f, 1.005f, 1.0f, -0.151f, 0.0f, -0.475f, 0.998f, 1.0f,
+ -0.132f, 0.0f, -0.458f, 0.99f, 1.0f, -0.112f, 0.0f, -0.44f, 0.98f, 1.0f,
+ -0.091f, 0.0f, -0.42f, 0.968f, 1.0f, -0.069f, 0.0f, -0.398f, 0.955f, 1.0f,
+ -0.045f, 0.0f, -0.375f, 0.939f, 1.0f, -0.021f, 0.0f, -0.35f, 0.923f, 1.0f,
+ 0.005f, 0.0f, -0.324f, 0.908f, 1.0f, 0.031f, 0.0f, -0.297f, 0.895f, 1.0f,
+ 0.06f, 0.0f, -0.268f, 0.882f, 1.0f, 0.089f, 0.0f, -0.238f, 0.87f, 1.0f,
+ 0.12f, 0.0f, -0.207f, 0.858f, 1.0f, 0.153f, 0.0f, -0.175f, 0.844f, 1.0f,
+ 0.187f, 0.0f, -0.14f, 0.828f, 1.0f, 0.224f, 0.0f, -0.104f, 0.81f, 1.0f,
+ 0.262f, 0.0f, -0.067f, 0.79f, 1.0f, 0.302f, 0.0f, -0.027f, 0.769f, 1.0f,
+ 0.344f, 0.0f, 0.014f, 0.747f, 1.0f, 0.388f, 0.0f, 0.056f, 0.724f, 1.0f,
+ 0.434f, 0.0f, 0.1f, 0.7f, 1.0f, 0.483f, 0.0f, 0.145f, 0.676f, 1.0f,
+ 0.533f, 0.0f, 0.191f, 0.651f, 1.0f, 0.585f, 0.0f, 0.238f, 0.625f, 1.0f,
+ 0.637f, 0.0f, 0.284f, 0.599f, 1.0f, 0.69f, 0.0f, 0.33f, 0.573f, 1.0f,
+ 0.746f, 0.0f, 0.376f, 0.546f, 1.0f, 0.802f, 0.0f, 0.421f, 0.516f, 1.0f,
+ 0.859f, 0.0f, 0.464f, 0.483f, 1.0f, 0.915f, 0.0f, 0.506f, 0.446f, 1.0f,
+ 0.97f, 0.0f, 0.545f, 0.407f, 1.0f, 1.023f, 0.0f, 0.581f, 0.365f, 1.0f,
+ 1.075f, 0.0f, 0.614f, 0.322f, 1.0f, 1.122f, 0.0f, 0.643f, 0.28f, 1.0f,
+ 1.169f, 0.0f, 0.671f, 0.236f, 1.0f, 1.207f, 0.0f, 0.693f, 0.202f, 1.0f,
+ 1.264f, 0.0f, 0.725f, 0.155f, 1.0f,
+};
+
+/* ***************************************************************** */
+/* Color Data */
+
+static const ColorTemplate gp_stroke_material_black = {
+ "Black",
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_stroke_material_white = {
+ "White",
+ {1.0f, 1.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_stroke_material_red = {
+ "Red",
+ {1.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_stroke_material_green = {
+ "Green",
+ {0.0f, 1.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_stroke_material_blue = {
+ "Blue",
+ {0.0f, 0.0f, 1.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+static const ColorTemplate gp_stroke_material_grey = {
+ "Grey",
+ {0.358f, 0.358f, 0.358f, 1.0f},
+ {0.5f, 0.5f, 0.5f, 1.0f},
+};
+
+/* ***************************************************************** */
+/* Stroke API */
+
+/* add a Simple stroke with colors (original design created by Daniel M. Lara and Matias Mendiola) */
+void ED_gpencil_create_stroke(bContext *C, float mat[4][4])
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDstroke *gps;
+
+ /* create colors */
+ int color_black = gp_stroke_material(bmain, ob, &gp_stroke_material_black);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_white);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_red);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_green);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_blue);
+ gp_stroke_material(bmain, ob, &gp_stroke_material_grey);
+
+ /* layers */
+ bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false);
+ bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", false);
+
+ /* frames */
+ bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, cfra_eval);
+ bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, cfra_eval);
+ UNUSED_VARS(frame_color);
+
+ /* generate stroke */
+ gps = BKE_gpencil_add_stroke(frame_lines, color_black, 175, 3);
+ BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
+
+ /* update depsgraph */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 0ddd8700c09..d8be0dd665a 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -48,6 +48,7 @@
#include "BLT_translation.h"
+#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -60,6 +61,9 @@
#include "BKE_library.h"
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "BKE_object_deform.h"
+#include "BKE_colortools.h"
+#include "BKE_material.h"
#include "UI_interface.h"
@@ -80,6 +84,9 @@
#include "GPU_immediate_util.h"
#include "GPU_state.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* ************************************************ */
@@ -89,7 +96,9 @@
typedef struct tGP_BrushEditData {
/* Current editor/region/etc. */
/* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
+ Depsgraph *depsgraph;
Scene *scene;
+ Object *object;
ScrArea *sa;
ARegion *ar;
@@ -114,6 +123,10 @@ typedef struct tGP_BrushEditData {
/* Start of new sculpt stroke */
bool first;
+ /* Is multiframe editing enabled, and are we using falloff for that? */
+ bool is_multiframe;
+ bool use_multiframe_falloff;
+
/* Current frame */
int cfra;
@@ -128,6 +141,13 @@ typedef struct tGP_BrushEditData {
/* - effect vector (e.g. 2D/3D translation for grab brush) */
float dvec[3];
+ /* - multiframe falloff factor */
+ float mf_falloff;
+
+ /* active vertex group */
+ int vrgroup;
+
+
/* brush geometry (bounding box) */
rcti brush_rect;
@@ -147,12 +167,34 @@ typedef struct tGP_BrushEditData {
/* Callback for performing some brush operation on a single point */
-typedef bool (*GP_BrushApplyCb)(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
+typedef bool (*GP_BrushApplyCb)(tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
const int radius, const int co[2]);
/* ************************************************ */
/* Utility Functions */
+/* apply lock axis reset */
+static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, bGPDspoint *pt, const float save_pt[3])
+{
+ if (gso->sa->spacetype != SPACE_VIEW3D) {
+ return;
+ }
+
+ ToolSettings *ts = gso->scene->toolsettings;
+ int axis = ts->gp_sculpt.lock_axis;
+
+ /* lock axis control */
+ if (axis == 1) {
+ pt->x = save_pt[0];
+ }
+ if (axis == 2) {
+ pt->y = save_pt[1];
+ }
+ if (axis == 3) {
+ pt->z = save_pt[2];
+ }
+}
+
/* Context ---------------------------------------- */
/* Get the sculpting settings */
@@ -162,10 +204,18 @@ static GP_BrushEdit_Settings *gpsculpt_get_settings(Scene *scene)
}
/* Get the active brush */
-static GP_EditBrush_Data *gpsculpt_get_brush(Scene *scene)
+static GP_EditBrush_Data *gpsculpt_get_brush(Scene *scene, bool is_weight_mode)
{
GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
- return &gset->brush[gset->brushtype];
+ GP_EditBrush_Data *brush = NULL;
+ if (is_weight_mode) {
+ brush = &gset->brush[gset->weighttype];
+ }
+ else {
+ brush = &gset->brush[gset->brushtype];
+ }
+
+ return brush;
}
/* Brush Operations ------------------------------- */
@@ -181,6 +231,14 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso)
invert ^= true;
}
+ /* set temporary status */
+ if (invert) {
+ gso->brush->flag |= GP_EDITBRUSH_FLAG_TMP_INVERT;
+ }
+ else {
+ gso->brush->flag &= ~GP_EDITBRUSH_FLAG_TMP_INVERT;
+ }
+
return invert;
}
@@ -208,6 +266,9 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
influence *= fac;
}
+ /* apply multiframe falloff */
+ influence *= gso->mf_falloff;
+
/* return influence */
return influence;
}
@@ -222,29 +283,34 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
/* Smooth Brush */
/* A simple (but slower + inaccurate) smooth-brush implementation to test the algorithm for stroke smoothing */
-static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_smooth_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- GP_EditBrush_Data *brush = gso->brush;
+ // GP_EditBrush_Data *brush = gso->brush;
float inf = gp_brush_influence_calc(gso, radius, co);
- bool affect_pressure = (brush->flag & GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE) != 0;
/* need one flag enabled by default */
- if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
- GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
- GP_BRUSHEDIT_FLAG_APPLY_THICKNESS)) == 0)
+ if ((gso->settings->flag &
+ (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
+ GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
+ GP_BRUSHEDIT_FLAG_APPLY_THICKNESS |
+ GP_BRUSHEDIT_FLAG_APPLY_UV)) == 0)
{
gso->settings->flag |= GP_BRUSHEDIT_FLAG_APPLY_POSITION;
}
/* perform smoothing */
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_POSITION) {
- gp_smooth_stroke(gps, i, inf, affect_pressure);
+ BKE_gpencil_smooth_stroke(gps, pt_index, inf);
}
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) {
- gp_smooth_stroke_strength(gps, i, inf);
+ BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
}
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
- gp_smooth_stroke_thickness(gps, i, inf);
+ BKE_gpencil_smooth_stroke_thickness(gps, pt_index, inf);
+ }
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_UV) {
+ BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
}
return true;
@@ -254,10 +320,11 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i
/* Line Thickness Brush */
/* Make lines thicker or thinner by the specified amounts */
-static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_thickness_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
float inf;
/* Compute strength of effect
@@ -294,28 +361,29 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
/* Make color more or less transparent by the specified amounts */
static bool gp_brush_strength_apply(
- tGP_BrushEditData *gso, bGPDstroke *gps, int i,
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
float inf;
/* Compute strength of effect
- * - We divide the strength by 10, so that users can set "sane" values.
+ * - We divide the strength, so that users can set "sane" values.
* Otherwise, good default values are in the range of 0.093
*/
- inf = gp_brush_influence_calc(gso, radius, co) / 10.0f;
+ inf = gp_brush_influence_calc(gso, radius, co) / 20.0f;
/* apply */
- // XXX: this is much too strong, and it should probably do some smoothing with the surrounding stuff
if (gp_brush_invert_check(gso)) {
- /* make line thinner - reduce stroke pressure */
+ /* make line more transparent - reduce alpha factor */
pt->strength -= inf;
}
else {
- /* make line thicker - increase stroke pressure */
+ /* make line more opaque - increase stroke strength */
pt->strength += inf;
}
+ /* smooth the strength */
+ BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
/* Strength should stay within [0.0, 1.0] */
CLAMP(pt->strength, 0.0f, 1.0f);
@@ -382,8 +450,9 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
}
/* store references to stroke points in the initial stage */
-static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_grab_store_points(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
float inf = gp_brush_influence_calc(gso, radius, co);
@@ -392,7 +461,7 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, bGPDstroke *gps,
BLI_assert(data->size < data->capacity);
/* insert this point into the set of affected points */
- data->points[data->size] = i;
+ data->points[data->size] = pt_index;
data->weights[data->size] = inf;
data->size++;
@@ -431,7 +500,7 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
/* Apply grab transform to all relevant points of the affected strokes */
static void gp_brush_grab_apply_cached(
- tGP_BrushEditData *gso, bGPDstroke *gps, bool parented, float diff_mat[4][4])
+ tGP_BrushEditData *gso, bGPDstroke *gps, float diff_mat[4][4])
{
tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
int i;
@@ -443,23 +512,21 @@ static void gp_brush_grab_apply_cached(
/* adjust the amount of displacement to apply */
mul_v3_v3fl(delta, gso->dvec, data->weights[i]);
- if (!parented) {
- /* apply */
- add_v3_v3(&pt->x, delta);
- }
- else {
- float fpt[3];
- /* apply transformation */
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- /* apply */
- add_v3_v3(fpt, delta);
- copy_v3_v3(&pt->x, fpt);
- /* undo transformation to the init parent position */
- float inverse_diff_mat[4][4];
- invert_m4_m4(inverse_diff_mat, diff_mat);
- mul_m4_v3(inverse_diff_mat, &pt->x);
- }
+ float fpt[3];
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+ /* apply transformation */
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* apply */
+ add_v3_v3v3(&pt->x, fpt, delta);
+ /* undo transformation to the init parent position */
+ float inverse_diff_mat[4][4];
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
}
@@ -480,10 +547,14 @@ static void gp_brush_grab_stroke_free(void *ptr)
/* Push Brush */
/* NOTE: Depends on gp_brush_grab_calc_dvec() */
-static bool gp_brush_push_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_push_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
+
float inf = gp_brush_influence_calc(gso, radius, co);
float delta[3] = {0.0f};
@@ -493,6 +564,9 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
/* apply */
add_v3_v3(&pt->x, delta);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
+
/* done */
return true;
}
@@ -512,7 +586,8 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso)
float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d)->location;
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
- float mval_f[2] = {UNPACK2(gso->mval)};
+ float mval_f[2];
+ copy_v2fl_v2i(mval_f, gso->mval);
float mval_prj[2];
float dvec[3];
@@ -536,12 +611,15 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso)
}
/* Shrink distance between midpoint and this point... */
-static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_pinch_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
float fac, inf;
float vec[3];
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
/* Scale down standard influence value to get it more manageable...
* - No damping = Unmanageable at > 0.5 strength
@@ -571,6 +649,9 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
/* 3) Translate back to original space, with the shrinkage applied */
add_v3_v3v3(&pt->x, gso->dvec, vec);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
+
/* done */
return true;
}
@@ -582,11 +663,14 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
* convert the rotated point and convert it into "data" space
*/
-static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_twist_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
float angle, inf;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
/* Angle to rotate by */
inf = gp_brush_influence_calc(gso, radius, co);
@@ -615,6 +699,9 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center (center is stored in dvec) */
mul_m3_v3(rmat, vec);
add_v3_v3v3(&pt->x, vec, gso->dvec); /* restore */
+
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
else {
const float axis[3] = {0.0f, 0.0f, 1.0f};
@@ -654,10 +741,13 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
/* Randomize Brush */
/* Apply some random jitter to the point */
-static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i,
- const int radius, const int co[2])
+static bool gp_brush_randomize_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
{
- bGPDspoint *pt = gps->points + i;
+ bGPDspoint *pt = gps->points + pt_index;
+ float save_pt[3];
+ copy_v3_v3(save_pt, &pt->x);
/* Amount of jitter to apply depends on the distance of the point to the cursor,
* as well as the strength of the brush
@@ -665,9 +755,11 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f;
const float fac = BLI_rng_get_float(gso->rng) * inf;
/* need one flag enabled by default */
- if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
- GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
- GP_BRUSHEDIT_FLAG_APPLY_THICKNESS)) == 0)
+ if ((gso->settings->flag &
+ (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
+ GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
+ GP_BRUSHEDIT_FLAG_APPLY_THICKNESS |
+ GP_BRUSHEDIT_FLAG_APPLY_UV)) == 0)
{
gso->settings->flag |= GP_BRUSHEDIT_FLAG_APPLY_POSITION;
}
@@ -710,6 +802,8 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
float dvec[3];
ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
add_v3_v3(&pt->x, dvec);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
}
else {
@@ -749,11 +843,76 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
/* only limit lower value */
CLAMP_MIN(pt->pressure, 0.0f);
}
+ /* apply random to UV (use pressure) */
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_UV) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
+ pt->uv_rot += fac;
+ }
+ else {
+ pt->uv_rot -= fac;
+ }
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
+ }
/* done */
return true;
}
+/* Weight Paint Brush */
+
+/* Change weight paint for vertex groups */
+static bool gp_brush_weight_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int pt_index,
+ const int radius, const int co[2])
+{
+ bGPDspoint *pt = gps->points + pt_index;
+ MDeformVert *dvert = gps->dvert + pt_index;
+ float inf;
+
+ /* Compute strength of effect
+ * - We divide the strength by 10, so that users can set "sane" values.
+ * Otherwise, good default values are in the range of 0.093
+ */
+ inf = gp_brush_influence_calc(gso, radius, co) / 10.0f;
+
+ /* need a vertex group */
+ if (gso->vrgroup == -1) {
+ if (gso->object) {
+ BKE_object_defgroup_add(gso->object);
+ gso->vrgroup = 0;
+ }
+ }
+ /* get current weight */
+ float curweight = 0.0f;
+ for (int i = 0; i < dvert->totweight; i++) {
+ MDeformWeight *gpw = &dvert->dw[i];
+ if (gpw->def_nr == gso->vrgroup) {
+ curweight = gpw->weight;
+ break;
+ }
+ }
+
+ if (gp_brush_invert_check(gso)) {
+ /* reduce weight */
+ curweight -= inf;
+ }
+ else {
+ /* increase weight */
+ curweight += inf;
+ }
+
+ CLAMP(curweight, 0.0f, 1.0f);
+ BKE_gpencil_vgroup_add_point_weight(dvert, gso->vrgroup, curweight);
+
+ /* weight should stay within [0.0, 1.0] */
+ if (pt->pressure < 0.0f)
+ pt->pressure = 0.0f;
+
+ return true;
+}
+
+
+
/* ************************************************ */
/* Non Callback-Based Brushes */
@@ -827,7 +986,7 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
/* Init colormap for mapping between the pasted stroke's source colour(names)
* and the final colours that will be used here instead...
*/
- data->new_colors = gp_copybuf_validate_colormap(gso->gpd);
+ data->new_colors = gp_copybuf_validate_colormap(C);
}
/* Free custom data used for "clone" brush */
@@ -857,9 +1016,12 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
{
tGPSB_CloneBrushData *data = gso->customdata;
- Scene *scene = gso->scene;
+ Object *ob = CTX_data_active_object(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, true);
bGPDstroke *gps;
float delta[3];
@@ -882,17 +1044,22 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
new_stroke = MEM_dupallocN(gps);
new_stroke->points = MEM_dupallocN(gps->points);
+ new_stroke->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
new_stroke->triangles = MEM_dupallocN(gps->triangles);
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
/* Fix color references */
- BLI_assert(new_stroke->colorname[0] != '\0');
- new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname);
-
- BLI_assert(new_stroke->palcolor != NULL);
- BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+ Material *ma = BLI_ghash_lookup(data->new_colors, &new_stroke->mat_nr);
+ if ((ma) && (BKE_gpencil_get_material_index(ob, ma) > 0)) {
+ gps->mat_nr = BKE_gpencil_get_material_index(ob, ma) - 1;
+ CLAMP_MIN(gps->mat_nr, 0);
+ }
+ else {
+ gps->mat_nr = 0; /* only if the color is not found */
+ }
/* Adjust all the stroke's points, so that the strokes
* get pasted relative to where the cursor is now
@@ -977,57 +1144,6 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
}
/* ************************************************ */
-/* Cursor drawing */
-
-/* Helper callback for drawing the cursor itself */
-static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
-{
- GP_EditBrush_Data *brush = gpsculpt_get_brush(CTX_data_scene(C));
-
- if (brush) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_line_smooth(true);
- GPU_blend(true);
-
- /* Inner Ring: Light color for action of the brush */
- /* TODO: toggle between add and remove? */
- immUniformColor4ub(255, 255, 255, 200);
- imm_draw_circle_wire_2d(pos, x, y, brush->size, 40);
-
- /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
- immUniformColor3ub(30, 30, 30);
- imm_draw_circle_wire_2d(pos, x, y, brush->size + 1, 40);
-
- immUnbindProgram();
-
- GPU_blend(false);
- GPU_line_smooth(false);
- }
-}
-
-/* Turn brush cursor in on/off */
-static void gpencil_toggle_brush_cursor(bContext *C, bool enable)
-{
- GP_BrushEdit_Settings *gset = gpsculpt_get_settings(CTX_data_scene(C));
-
- if (gset->paintcursor && !enable) {
- /* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
- gset->paintcursor = NULL;
- }
- else if (enable) {
- /* enable cursor */
- gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- NULL,
- gp_brush_drawcursor, NULL);
- }
-}
-
-
-/* ************************************************ */
/* Header Info for GPencil Sculpt */
static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
@@ -1054,17 +1170,40 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+
+ const bool is_weight_mode = ob->mode == OB_MODE_GPENCIL_WEIGHT;
+ /* set the brush using the tool */
+ GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
+ eGP_EditBrush_Types mode = RNA_enum_get(op->ptr, "mode");
+ const bool keep_brush = RNA_boolean_get(op->ptr, "keep_brush");
+
+ if (!keep_brush) {
+ if (is_weight_mode) {
+ gset->weighttype = mode;
+ }
+ else {
+ gset->brushtype = mode;
+ }
+ }
tGP_BrushEditData *gso;
/* setup operator data */
gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData");
op->customdata = gso;
+ gso->depsgraph = CTX_data_depsgraph(C);
/* store state */
gso->settings = gpsculpt_get_settings(scene);
- gso->brush = gpsculpt_get_brush(scene);
+ gso->brush = gpsculpt_get_brush(scene, is_weight_mode);
- gso->brush_type = gso->settings->brushtype;
+ if (is_weight_mode) {
+ gso->brush_type = gso->settings->weighttype;
+ }
+ else {
+ gso->brush_type = gso->settings->brushtype;
+ }
/* Random generator, only init once. */
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
@@ -1078,10 +1217,31 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso->cfra = INT_MAX; /* NOTE: So that first stroke will get handled in init_stroke() */
gso->scene = scene;
+ gso->object = ob;
+ if (ob) {
+ gso->vrgroup = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
+ gso->vrgroup = -1;
+ }
+ }
+ else {
+ gso->vrgroup = - 1;
+ }
gso->sa = CTX_wm_area(C);
gso->ar = CTX_wm_region(C);
+ /* multiframe settings */
+ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
+ gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_FRAME_FALLOFF) != 0;
+
+ /* init multiedit falloff curve data before doing anything,
+ * so we won't have to do it again later
+ */
+ if (gso->is_multiframe) {
+ curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
/* initialise custom data for brushes */
switch (gso->brush_type) {
case GP_EDITBRUSH_TYPE_CLONE:
@@ -1133,9 +1293,10 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gpsculpt_brush_header_set(C, gso);
/* setup cursor drawing */
- WM_cursor_modal_set(CTX_wm_window(C), BC_CROSSCURSOR);
- gpencil_toggle_brush_cursor(C, true);
-
+ //WM_cursor_modal_set(CTX_wm_window(C), BC_CROSSCURSOR);
+ if (gso->sa->spacetype != SPACE_VIEW3D) {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
return true;
}
@@ -1179,7 +1340,12 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
/* disable cursor and headerprints */
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
- gpencil_toggle_brush_cursor(C, false);
+ if (gso->sa->spacetype != SPACE_VIEW3D) {
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+
+ /* disable temp invert flag */
+ gso->brush->flag &= ~GP_EDITBRUSH_FLAG_TMP_INVERT;
/* free operator data */
MEM_freeN(gso);
@@ -1197,13 +1363,13 @@ static bool gpsculpt_brush_poll(bContext *C)
static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
{
- Scene *scene = gso->scene;
bGPdata *gpd = gso->gpd;
+
bGPDlayer *gpl;
- int cfra = CFRA;
+ int cfra_eval = (int)DEG_get_ctime(gso->depsgraph);
/* only try to add a new frame if this is the first stroke, or the frame has changed */
- if ((gpd == NULL) || (cfra == gso->cfra))
+ if ((gpd == NULL) || (cfra_eval == gso->cfra))
return;
/* go through each layer, and ensure that we've got a valid frame to use */
@@ -1217,21 +1383,21 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
* spent too much time editing the wrong frame...
*/
// XXX: should this be allowed when framelock is enabled?
- if (gpf->framenum != cfra) {
- BKE_gpencil_frame_addcopy(gpl, cfra);
+ if (gpf->framenum != cfra_eval) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
}
}
}
/* save off new current frame, so that next update works fine */
- gso->cfra = cfra;
+ gso->cfra = cfra_eval;
}
/* Apply ----------------------------------------------- */
/* Apply brush operation to points in this stroke */
static bool gpsculpt_brush_do_stroke(
- tGP_BrushEditData *gso, bGPDstroke *gps, bool parented,
+ tGP_BrushEditData *gso, bGPDstroke *gps,
float diff_mat[4][4], GP_BrushApplyCb apply)
{
GP_SpaceConversion *gsc = &gso->gsc;
@@ -1246,14 +1412,9 @@ static bool gpsculpt_brush_do_stroke(
bool changed = false;
if (gps->totpoints == 1) {
- if (!parented) {
- gp_point_to_xy(gsc, gps, gps->points, &pc1[0], &pc1[1]);
- }
- else {
- bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
- }
+ bGPDspoint pt_temp;
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
@@ -1280,19 +1441,12 @@ static bool gpsculpt_brush_do_stroke(
continue;
}
}
- if (!parented) {
- gp_point_to_xy(gsc, gps, pt1, &pc1[0], &pc1[1]);
- gp_point_to_xy(gsc, gps, pt2, &pc2[0], &pc2[1]);
- }
- else {
- bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
-
- gp_point_to_parent_space(pt2, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
- }
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
/* Check that point segment of the boundbox of the selection stroke */
if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
@@ -1342,9 +1496,114 @@ static bool gpsculpt_brush_do_stroke(
return changed;
}
+/* Apply sculpt brushes to strokes in the given frame */
+static bool gpsculpt_brush_do_frame(
+ bContext *C, tGP_BrushEditData *gso,
+ bGPDlayer *gpl, bGPDframe *gpf,
+ float diff_mat[4][4])
+{
+ bool changed = false;
+ Object *ob = CTX_data_active_object(C);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* 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(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ switch (gso->brush_type) {
+ case GP_EDITBRUSH_TYPE_SMOOTH: /* Smooth strokes */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_THICKNESS: /* Adjust stroke thickness */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_thickness_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_STRENGTH: /* Adjust stroke color strength */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_strength_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */
+ {
+ if (gso->first) {
+ /* First time this brush stroke is being applied:
+ * 1) Prepare data buffers (init/clear) for this stroke
+ * 2) Use the points now under the cursor
+ */
+ gp_brush_grab_stroke_init(gso, gps);
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_grab_store_points);
+ }
+ else {
+ /* Apply effect to the stored points */
+ gp_brush_grab_apply_cached(gso, gps, diff_mat);
+ changed |= true;
+ }
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_PUSH: /* Push points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_RANDOMIZE: /* Apply jitter */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_randomize_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_WEIGHT: /* Adjust vertex group weight */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_weight_apply);
+ break;
+ }
+
+
+ default:
+ printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
+ break;
+ }
+ /* Triangulation must be calculated if changed */
+ if (changed) {
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
+ }
+ }
+
+ return changed;
+}
+
/* Perform two-pass brushes which modify the existing strokes */
static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+ Object *obact = gso->object;
+ bGPdata *gpd = gso->gpd;
bool changed = false;
/* Calculate brush-specific data which applies equally to all points */
@@ -1378,104 +1637,53 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
/* Find visible strokes, and perform operations on those if hit */
- float diff_mat[4][4];
- bool parented = false;
-
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL)
+ /* If no active frame, don't do anything... */
+ if (gpl->actframe == NULL) {
continue;
-
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- parented = true;
- }
- else {
- parented = false;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* 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;
- }
+ /* calculate difference matrix */
+ float diff_mat[4][4];
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
- switch (gso->brush_type) {
- case GP_EDITBRUSH_TYPE_SMOOTH: /* Smooth strokes */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_smooth_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_THICKNESS: /* Adjust stroke thickness */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_thickness_apply);
- break;
- }
+ /* Active Frame or MultiFrame? */
+ if (gso->is_multiframe) {
+ /* init multiframe falloff options */
+ int f_init = 0;
+ int f_end = 0;
- case GP_EDITBRUSH_TYPE_STRENGTH: /* Adjust stroke color strength */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_strength_apply);
- break;
- }
+ if (gso->use_multiframe_falloff) {
+ BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ }
- case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */
- {
- if (gso->first) {
- /* First time this brush stroke is being applied:
- * 1) Prepare data buffers (init/clear) for this stroke
- * 2) Use the points now under the cursor
- */
- gp_brush_grab_stroke_init(gso, gps);
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_grab_store_points);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* Always do active frame; Otherwise, only include selected frames */
+ if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
+ /* compute multiframe falloff factor */
+ if (gso->use_multiframe_falloff) {
+ /* Faloff depends on distance to active frame (relative to the overall frame range) */
+ gso->mf_falloff = BKE_gpencil_multiframe_falloff_calc(
+ gpf, gpl->actframe->framenum,
+ f_init, f_end,
+ ts->gp_sculpt.cur_falloff);
}
else {
- /* Apply effect to the stored points */
- gp_brush_grab_apply_cached(gso, gps, parented, diff_mat);
- changed |= true;
+ /* No falloff */
+ gso->mf_falloff = 1.0f;
}
- break;
- }
-
- case GP_EDITBRUSH_TYPE_PUSH: /* Push points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_push_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_pinch_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_twist_apply);
- break;
- }
- case GP_EDITBRUSH_TYPE_RANDOMIZE: /* Apply jitter */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_randomize_apply);
- break;
+ /* affect strokes in this frame */
+ changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf, diff_mat);
}
-
- default:
- printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
- break;
- }
- /* Triangulation must be calculated if changed */
- if (changed) {
- gps->flag |= GP_STROKE_RECALC_CACHES;
- gps->tot_triangles = 0;
}
}
+ else {
+ /* Apply to active frame's strokes */
+ gso->mf_falloff = 1.0f;
+ changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
}
CTX_DATA_END;
@@ -1529,6 +1737,7 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
/* Updates */
if (changed) {
+ DEG_id_tag_update(&gso->gpd->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
@@ -1605,9 +1814,18 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
tGP_BrushEditData *gso = NULL;
const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ const bool is_playing = ED_screen_animation_playing(CTX_wm_manager(C)) != NULL;
bool needs_timer = false;
float brush_rate = 0.0f;
+ /* the operator cannot work while play animation */
+ if (is_playing) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Cannot sculpt while play animation");
+
+ return OPERATOR_CANCELLED;
+ }
+
/* init painting data */
if (!gpsculpt_brush_init(C, op))
return OPERATOR_CANCELLED;
@@ -1832,7 +2050,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
case DOWNARROWKEY:
return OPERATOR_PASS_THROUGH;
- /* Camera/View Manipulations - Allowed */
+ /* Camera/View Gizmo's - Allowed */
/* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
@@ -1852,6 +2070,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
/* Redraw toolsettings (brush settings)? */
if (redraw_toolsettings) {
+ DEG_id_tag_update(&gso->gpd->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
@@ -1860,6 +2079,19 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
/* Operator --------------------------------------------- */
+static const EnumPropertyItem prop_gpencil_sculpt_brush_items[] = {
+ {GP_EDITBRUSH_TYPE_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth stroke points" },
+ {GP_EDITBRUSH_TYPE_THICKNESS, "THICKNESS", 0, "Thickness", "Adjust thickness of strokes" },
+ {GP_EDITBRUSH_TYPE_STRENGTH, "STRENGTH", 0, "Strength", "Adjust color strength of strokes" },
+ {GP_EDITBRUSH_TYPE_GRAB, "GRAB", 0, "Grab", "Translate the set of points initially within the brush circle" },
+ {GP_EDITBRUSH_TYPE_PUSH, "PUSH", 0, "Push", "Move points out of the way, as if combing them" },
+ {GP_EDITBRUSH_TYPE_TWIST, "TWIST", 0, "Twist", "Rotate points around the midpoint of the brush" },
+ {GP_EDITBRUSH_TYPE_PINCH, "PINCH", 0, "Pinch", "Pull points towards the midpoint of the brush" },
+ {GP_EDITBRUSH_TYPE_RANDOMIZE, "RANDOMIZE", 0, "Randomize", "Introduce jitter/randomness into strokes" },
+ {GP_EDITBRUSH_TYPE_CLONE, "CLONE", 0, "Clone", "Paste copies of the strokes stored on the clipboard" },
+ {GP_EDITBRUSH_TYPE_WEIGHT, "WEIGHT", 0, "Weight", "Weight Paint" },
+ {0, NULL, 0, NULL, NULL }
+};
void GPENCIL_OT_brush_paint(wmOperatorType *ot)
{
@@ -1879,13 +2111,20 @@ void GPENCIL_OT_brush_paint(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_sculpt_brush_items, 0, "Mode", "Brush mode");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
PropertyRNA *prop;
prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input",
"Enter a mini 'sculpt-mode' if enabled, otherwise, exit after drawing a single stroke");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "keep_brush", false, "Keep Brush",
+ "Keep current brush activated");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index ccdbcba71f9..f662e9b42be 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -56,7 +56,6 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_workspace_types.h"
#include "BKE_collection.h"
#include "BKE_context.h"
@@ -74,6 +73,7 @@
#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
@@ -149,28 +149,24 @@ static const EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), Poi
* - assumes that the active space is the 3D-View
*/
static void gp_strokepoint_convertcoords(
- bContext *C, bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *source_pt,
+ bContext *C, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *source_pt,
float p3d[3], const rctf *subrect)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+ Object *obact = CTX_data_active_object(C);
bGPDspoint mypt, *pt;
float diff_mat[4][4];
pt = &mypt;
- /* calculate difference matrix if parent object */
- if (gpl->parent == NULL) {
- copy_v3_v3(&pt->x, &source_pt->x);
- }
- else {
- /* apply parent transform */
- float fpt[3];
- ED_gpencil_parent_location(gpl, diff_mat);
- mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
- copy_v3_v3(&pt->x, fpt);
- }
+ /* apply parent transform */
+ float fpt[3];
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
+ copy_v3_v3(&pt->x, fpt);
if (gps->flag & GP_STROKE_3DSPACE) {
@@ -591,7 +587,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl
}
}
-static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+static void gp_stroke_to_path(bContext *C, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
const bool add_end_point, tGpTimingData *gtd)
{
@@ -655,7 +651,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
bp = &nu->bp[old_nbp - 1];
/* First point */
- gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
if (prev_bp) {
interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
if (do_gtd) {
@@ -676,7 +672,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
/* Second point */
/* Note dt2 is always negative, which marks the gap. */
if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect);
interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
if (do_gtd) {
dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
@@ -697,9 +693,9 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
float p[3], next_p[3];
float dt = 0.0f;
- gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect);
interp_v3_v3v3(p, p, next_p, -GAP_DFAC);
if (do_gtd) {
dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
@@ -728,10 +724,10 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv
i++, pt++, bp++)
{
float p[3];
- float width = pt->pressure * (gps->thickness + gpl->thickness) * WIDTH_CORR_FAC;
+ float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC;
/* get coordinates to add at */
- gp_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, p, subrect);
gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time,
width, rad_fac, minmax_weights);
@@ -801,7 +797,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt,
}
}
-static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+static void gp_stroke_to_bezier(bContext *C, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point,
const bool add_end_point, tGpTimingData *gtd)
{
@@ -843,12 +839,12 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
/* get initial coordinates */
pt = gps->points;
if (tot) {
- gp_strokepoint_convertcoords(C, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
if (tot > 1) {
- gp_strokepoint_convertcoords(C, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
}
if (stitch && tot > 2) {
- gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
}
}
@@ -967,7 +963,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
/* add points */
for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) {
- float width = pt->pressure * (gps->thickness + gpl->thickness) * WIDTH_CORR_FAC;
+ float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC;
if (i || old_nbezt) {
interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
@@ -991,7 +987,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu
copy_v3_v3(p3d_cur, p3d_next);
if (i + 2 < tot) {
- gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
}
prev_bezt = bezt;
@@ -1130,10 +1126,12 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
{
struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Collection *collection = CTX_data_collection(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
Curve *cu;
@@ -1192,12 +1190,12 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
switch (mode) {
case GP_STROKECONVERT_PATH:
- gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
+ gp_stroke_to_path(C, gpd, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
add_start_point, add_end_point, gtd);
break;
case GP_STROKECONVERT_CURVE:
case GP_STROKECONVERT_POLY: /* convert after */
- gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
+ gp_stroke_to_bezier(C, gpd, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
add_start_point, add_end_point, gtd);
break;
default:
@@ -1238,7 +1236,9 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
*/
static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
bGPDframe *gpf = NULL;
bGPDstroke *gps = NULL;
bGPDspoint *pt;
@@ -1246,7 +1246,7 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
int i;
bool valid = true;
- if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first))
+ if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0)) || !(gps = gpf->strokes.first))
return false;
do {
@@ -1294,10 +1294,12 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN
static bool gp_convert_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
bGPDlayer *gpl = NULL;
bGPDframe *gpf = NULL;
ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
@@ -1305,7 +1307,7 @@ static bool gp_convert_poll(bContext *C)
*/
return ((sa && sa->spacetype == SPACE_VIEW3D) &&
(gpl = BKE_gpencil_layer_getactive(gpd)) &&
- (gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) &&
+ (gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0)) &&
(gpf->strokes.first) &&
(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL));
}
@@ -1382,8 +1384,9 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool gp_convert_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
{
+ PointerRNA *ptr = op->ptr;
const char *prop_id = RNA_property_identifier(prop);
const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
int timing_mode = RNA_enum_get(ptr, "timing_mode");
@@ -1446,18 +1449,6 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
-static void gp_convert_ui(bContext *C, wmOperator *op)
-{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
-}
-
void GPENCIL_OT_convert(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1471,7 +1462,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
ot->invoke = WM_menu_invoke;
ot->exec = gp_convert_layer_exec;
ot->poll = gp_convert_poll;
- ot->ui = gp_convert_ui;
+ ot->poll_property = gp_convert_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index c28fea0fc41..faeee4db169 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -46,18 +46,31 @@
#include "BLT_translation.h"
+#include "DNA_anim_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_gpencil_types.h"
-#include "BKE_colortools.h"
+#include "BKE_main.h"
+#include "BKE_brush.h"
+#include "BKE_animsys.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_library.h"
-#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -72,8 +85,13 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "ED_object.h"
#include "ED_gpencil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* ************************************************ */
@@ -84,9 +102,9 @@
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ PointerRNA gpd_owner = {{NULL}};
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
+ bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
if (gpd_ptr == NULL) {
BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
@@ -94,19 +112,36 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
}
else {
/* decrement user count and add new datablock */
- bGPdata *gpd = (*gpd_ptr);
+ /* TODO: if a datablock exists, we should make a copy of it instead of starting fresh (as in other areas) */
+ Main *bmain = CTX_data_main(C);
- id_us_min(&gpd->id);
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+ /* decrement user count of old GP datablock */
+ if (*gpd_ptr) {
+ bGPdata *gpd = (*gpd_ptr);
+ id_us_min(&gpd->id);
+ }
- /* if not exist brushes, create a new set */
- if (ts) {
- if (BLI_listbase_is_empty(&ts->gp_brushes)) {
- /* create new brushes */
- BKE_gpencil_brush_init_presets(ts);
- }
+ /* add new datablock, with a single layer ready to use (so users don't have to perform an extra step) */
+ if (is_annotation) {
+ bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
+ *gpd_ptr = gpd;
+
+ /* tag for annotations */
+ gpd->flag |= GP_DATA_ANNOTATIONS;
+
+ /* add new layer (i.e. a "note") */
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
}
+ else {
+ /* GP Object Case - This shouldn't happen! */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+
+ /* add default sets of colors and brushes */
+ ED_gpencil_add_defaults(C);
+ /* add new layer */
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
+ }
}
/* notifiers */
@@ -185,28 +220,42 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
/* add new layer - wrapper around API */
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ PointerRNA gpd_owner = {{NULL}};
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
+ bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
/* if there's no existing Grease-Pencil data there, add some */
if (gpd_ptr == NULL) {
BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
return OPERATOR_CANCELLED;
}
- if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
- /* if not exist brushes, create a new set */
- if (ts) {
- if (BLI_listbase_is_empty(&ts->gp_brushes)) {
- /* create new brushes */
- BKE_gpencil_brush_init_presets(ts);
+ if (*gpd_ptr == NULL) {
+ Main *bmain = CTX_data_main(C);
+ if (is_annotation) {
+ /* Annotations */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
+
+ /* mark as annotation */
+ (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
+ }
+ else {
+ /* GP Object */
+ /* NOTE: This shouldn't actually happen in practice */
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
+
+ /* add default sets of colors and brushes */
+ ED_gpencil_add_defaults(C);
}
}
/* add new layer now */
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
+ if (is_annotation) {
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
+ }
+ else {
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
+ }
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -219,7 +268,7 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Add New Layer";
ot->idname = "GPENCIL_OT_layer_add";
- ot->description = "Add new Grease Pencil layer for the active Grease Pencil data-block";
+ ot->description = "Add new layer or note for the active data-block";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -257,6 +306,7 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
BKE_gpencil_layer_delete(gpd, gpl);
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -296,6 +346,7 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
@@ -346,6 +397,7 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
BKE_gpencil_layer_setactive(gpd, new_layer);
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -366,6 +418,153 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ********************* Duplicate Frame ************************** */
+enum {
+ GP_FRAME_DUP_ACTIVE = 0,
+ GP_FRAME_DUP_ALL = 1
+};
+
+static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl))
+ return OPERATOR_CANCELLED;
+
+ if (mode == 0) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
+ }
+ else {
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
+ BKE_gpencil_frame_addcopy(gpl, cfra_eval);
+ }
+ }
+
+ }
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_frame_duplicate(wmOperatorType *ot)
+{
+ static const EnumPropertyItem duplicate_mode[] = {
+ { GP_FRAME_DUP_ACTIVE, "ACTIVE", 0, "Active", "Duplicate frame in active layer only" },
+ { GP_FRAME_DUP_ALL, "ALL", 0, "All", "Duplicate active frames in all layers" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* identifiers */
+ ot->name = "Duplicate Frame";
+ ot->idname = "GPENCIL_OT_frame_duplicate";
+ ot->description = "Make a copy of the active Grease Pencil Frame";
+
+ /* callbacks */
+ ot->exec = gp_frame_duplicate_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
+}
+
+/* ********************* Clean Fill Boundaries on Frame ************************** */
+enum {
+ GP_FRAME_CLEAN_FILL_ACTIVE = 0,
+ GP_FRAME_CLEAN_FILL_ALL = 1
+};
+
+static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op)
+{
+ bool changed = false;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *init_gpf = gpl->actframe;
+ if (mode == GP_FRAME_CLEAN_FILL_ALL) {
+ init_gpf = gpl->frames.first;
+ }
+
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || (mode == GP_FRAME_CLEAN_FILL_ALL)) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL)
+ continue;
+
+ /* simply delete strokes which are no fill */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke */
+ if (gps->flag & GP_STROKE_NOFILL) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ MEM_SAFE_FREE(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot)
+{
+ static const EnumPropertyItem duplicate_mode[] = {
+ { GP_FRAME_CLEAN_FILL_ACTIVE, "ACTIVE", 0, "Active Frame Only", "Clean active frame only" },
+ { GP_FRAME_CLEAN_FILL_ALL, "ALL", 0, "All Frames", "Clean all frames in all layers" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* identifiers */
+ ot->name = "Clean Fill Boundaries";
+ ot->idname = "GPENCIL_OT_frame_clean_fill";
+ ot->description = "Remove 'no fill' boundary strokes";
+
+ /* callbacks */
+ ot->exec = gp_frame_clean_fill_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
+}
+
/* *********************** Hide Layers ******************************** */
static int gp_hide_exec(bContext *C, wmOperator *op)
@@ -394,6 +593,7 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -481,6 +681,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -521,6 +722,7 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -558,6 +760,7 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -630,6 +833,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -673,22 +877,28 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
BLI_ghash_insert(gh_frames_cur, SET_INT_IN_POINTER(gpf->framenum), gpf);
}
- /* read all frames from next layer */
+ /* read all frames from next layer and add any missing in current layer */
for (bGPDframe *gpf = gpl_next->frames.first; gpf; gpf = gpf->next) {
- /* try to find frame in active layer */
+ /* try to find frame in current layer */
bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, SET_INT_IN_POINTER(gpf->framenum));
if (!frame) {
- /* nothing found, create new */
+ bGPDframe *actframe = BKE_gpencil_layer_getframe(gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
+ /* duplicate strokes of current active frame */
+ if (actframe) {
+ BKE_gpencil_frame_copy_strokes(actframe, frame);
+ }
}
/* add to tail all strokes */
BLI_movelisttolist(&frame->strokes, &gpf->strokes);
}
+
/* Now delete next layer */
BKE_gpencil_layer_delete(gpd, gpl_next);
BLI_ghash_free(gh_frames_cur, NULL, NULL);
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -750,6 +960,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op)
BKE_gpencil_layer_setactive(gpd, gpl);
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -788,6 +999,7 @@ enum {
static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
{
+ Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
bGPDstroke *gps;
@@ -797,79 +1009,95 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- bGPDframe *gpf = gpl->actframe;
- /* temp listbase to store selected strokes */
- ListBase selected = {NULL};
const int direction = RNA_enum_get(op->ptr, "direction");
- /* verify if any selected stroke is in the extreme of the stack and select to move */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
- }
- /* some stroke is already at front*/
- if ((direction == GP_STROKE_MOVE_TOP) || (direction == GP_STROKE_MOVE_UP)) {
- if (gps == gpf->strokes.last) {
- return OPERATOR_CANCELLED;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* temp listbase to store selected strokes by layer */
+ ListBase selected = { NULL };
+ bGPDframe *gpf = gpl->actframe;
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ continue;
+ }
+
+ if (gpf == NULL) {
+ continue;
+ }
+ bool gpf_lock = false;
+ /* verify if any selected stroke is in the extreme of the stack and select to move */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
}
- }
- /* some stroke is already at botom */
- if ((direction == GP_STROKE_MOVE_BOTTOM) || (direction == GP_STROKE_MOVE_DOWN)) {
- if (gps == gpf->strokes.first) {
- return OPERATOR_CANCELLED;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ /* some stroke is already at front*/
+ if ((direction == GP_STROKE_MOVE_TOP) || (direction == GP_STROKE_MOVE_UP)) {
+ if (gps == gpf->strokes.last) {
+ gpf_lock = true;
+ continue;
+ }
+ }
+ /* some stroke is already at botom */
+ if ((direction == GP_STROKE_MOVE_BOTTOM) || (direction == GP_STROKE_MOVE_DOWN)) {
+ if (gps == gpf->strokes.first) {
+ gpf_lock = true;
+ continue;
+ }
+ }
+ /* add to list (if not locked) */
+ if (!gpf_lock) {
+ BLI_addtail(&selected, BLI_genericNodeN(gps));
}
}
- /* add to list */
- BLI_addtail(&selected, BLI_genericNodeN(gps));
}
- }
-
- /* Now do the movement of the stroke */
- switch (direction) {
- /* Bring to Front */
- case GP_STROKE_MOVE_TOP:
- for (LinkData *link = selected.first; link; link = link->next) {
- gps = link->data;
- BLI_remlink(&gpf->strokes, gps);
- BLI_addtail(&gpf->strokes, gps);
- }
- break;
- /* Bring Forward */
- case GP_STROKE_MOVE_UP:
- for (LinkData *link = selected.last; link; link = link->prev) {
- gps = link->data;
- BLI_listbase_link_move(&gpf->strokes, gps, 1);
- }
- break;
- /* Send Backward */
- case GP_STROKE_MOVE_DOWN:
- for (LinkData *link = selected.first; link; link = link->next) {
- gps = link->data;
- BLI_listbase_link_move(&gpf->strokes, gps, -1);
- }
- break;
- /* Send to Back */
- case GP_STROKE_MOVE_BOTTOM:
- for (LinkData *link = selected.last; link; link = link->prev) {
- gps = link->data;
- BLI_remlink(&gpf->strokes, gps);
- BLI_addhead(&gpf->strokes, gps);
+ /* Now do the movement of the stroke */
+ if (!gpf_lock) {
+ switch (direction) {
+ /* Bring to Front */
+ case GP_STROKE_MOVE_TOP:
+ for (LinkData *link = selected.first; link; link = link->next) {
+ gps = link->data;
+ BLI_remlink(&gpf->strokes, gps);
+ BLI_addtail(&gpf->strokes, gps);
+ }
+ break;
+ /* Bring Forward */
+ case GP_STROKE_MOVE_UP:
+ for (LinkData *link = selected.last; link; link = link->prev) {
+ gps = link->data;
+ BLI_listbase_link_move(&gpf->strokes, gps, 1);
+ }
+ break;
+ /* Send Backward */
+ case GP_STROKE_MOVE_DOWN:
+ for (LinkData *link = selected.first; link; link = link->next) {
+ gps = link->data;
+ BLI_listbase_link_move(&gpf->strokes, gps, -1);
+ }
+ break;
+ /* Send to Back */
+ case GP_STROKE_MOVE_BOTTOM:
+ for (LinkData *link = selected.last; link; link = link->prev) {
+ gps = link->data;
+ BLI_remlink(&gpf->strokes, gps);
+ BLI_addhead(&gpf->strokes, gps);
+ }
+ break;
+ default:
+ BLI_assert(0);
+ break;
}
- break;
- default:
- BLI_assert(0);
- break;
+ }
+ BLI_freelistN(&selected);
}
- BLI_freelistN(&selected);
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -890,58 +1118,87 @@ void GPENCIL_OT_stroke_arrange(wmOperatorType *ot)
ot->idname = "GPENCIL_OT_stroke_arrange";
ot->description = "Arrange selected strokes up/down in the drawing order of the active layer";
- /* api callbacks */
+ /* callbacks */
ot->exec = gp_stroke_arrange_exec;
ot->poll = gp_active_layer_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* properties */
ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_STROKE_MOVE_UP, "Direction", "");
}
+
/* ******************* Move Stroke to new color ************************** */
-static int gp_stroke_change_color_exec(bContext *C, wmOperator *UNUSED(op))
+static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
+ Material *ma = NULL;
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "material", name);
+
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette;
- bGPDpalettecolor *color;
+ Object *ob = CTX_data_active_object(C);
+ if (name[0] == '\0') {
+ ma = give_current_material(ob, ob->actcol);
+ }
+ else {
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
+ if (ma == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ /* try to find slot */
+ int idx = BKE_gpencil_get_material_index(ob, ma) - 1;
+ if (idx <= 0) {
+ return OPERATOR_CANCELLED;
+ }
/* sanity checks */
if (ELEM(NULL, gpd)) {
return OPERATOR_CANCELLED;
}
- palette = BKE_gpencil_palette_getactive(gpd);
- color = BKE_gpencil_palettecolor_getactive(palette);
- if (ELEM(NULL, palette, color)) {
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ if (ELEM(NULL, ma)) {
return OPERATOR_CANCELLED;
}
/* loop all strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* 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;
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL)
+ continue;
- /* asign new color (only if different) */
- if ((STREQ(gps->colorname, color->info) == false) || (gps->palcolor != color)) {
- BLI_strncpy(gps->colorname, color->info, sizeof(gps->colorname));
- gps->palcolor = color;
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* 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(ob, gpl, gps) == false)
+ continue;
+
+ /* asign new color */
+ gps->mat_nr = idx;
}
}
}
}
}
+ CTX_DATA_END;
+
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -952,11 +1209,17 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
/* identifiers */
ot->name = "Change Stroke Color";
ot->idname = "GPENCIL_OT_stroke_change_color";
- ot->description = "Move selected strokes to active color";
+ ot->description = "Move selected strokes to active material";
- /* api callbacks */
+ /* callbacks */
ot->exec = gp_stroke_change_color_exec;
ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_string(ot->srna, "material", NULL, MAX_ID_NAME - 2, "Material", "Name of the material");
+
}
/* ******************* Lock color of non selected Strokes colors ************************** */
@@ -964,19 +1227,19 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette;
+
+ Object *ob = CTX_data_active_object(C);
+
+ short *totcol = give_totcolp(ob);
/* sanity checks */
if (ELEM(NULL, gpd))
return OPERATOR_CANCELLED;
- palette = BKE_gpencil_palette_getactive(gpd);
- if (ELEM(NULL, palette))
- return OPERATOR_CANCELLED;
-
/* first lock all colors */
- for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag |= PC_COLOR_LOCKED;
+ for (short i = 0; i < *totcol; i++) {
+ Material *tmp_ma = give_current_material(ob, i + 1);
+ tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
}
/* loop all selected strokes and unlock any color */
@@ -991,14 +1254,15 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
/* unlock color */
- if (gps->palcolor != NULL) {
- gps->palcolor->flag &= ~PC_COLOR_LOCKED;
- }
+ Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
+
+ tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
}
}
}
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1014,25 +1278,18 @@ void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
/* api callbacks */
ot->exec = gp_stroke_lock_color_exec;
ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************ */
/* Drawing Brushes Operators */
-/* ******************* Add New Brush ************************ */
-
-/* add new brush - wrapper around API */
-static int gp_brush_add_exec(bContext *C, wmOperator *op)
+/* ******************* Brush create presets ************************** */
+static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- /* if there's no existing container */
- if (ts == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for brush data to go");
- return OPERATOR_CANCELLED;
- }
- /* add new brush now */
- BKE_gpencil_brush_addnew(ts, DATA_("GP_Brush"), true);
+ BKE_brush_gpencil_presets(C);
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -1040,513 +1297,757 @@ static int gp_brush_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_add(wmOperatorType *ot)
+void GPENCIL_OT_brush_presets_create(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Brush";
- ot->idname = "GPENCIL_OT_brush_add";
- ot->description = "Add new Grease Pencil drawing brush for the active Grease Pencil data-block";
+ ot->name = "Create Preset Brushes";
+ ot->idname = "GPENCIL_OT_brush_presets_create";
+ ot->description = "Create a set of predefined Grease Pencil drawing brushes";
+ /* api callbacks */
+ ot->exec = gp_brush_presets_create_exec;
+
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_brush_add_exec;
- ot->poll = gp_add_poll;
}
-/* ******************* Remove Active Brush ************************* */
+/* ***************** Select Brush ************************ */
-static int gp_brush_remove_exec(bContext *C, wmOperator *op)
+static int gp_brush_select_exec(bContext *C, wmOperator *op)
{
ToolSettings *ts = CTX_data_tool_settings(C);
- bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
-
- /* sanity checks */
- if (ELEM(NULL, ts, brush))
- return OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
- if (BLI_listbase_count_at_most(&ts->gp_brushes, 2) < 2) {
- BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush, unable to delete the last one");
+ /* if there's no existing container */
+ if (ts == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere to go");
return OPERATOR_CANCELLED;
}
+ const int index = RNA_int_get(op->ptr, "index");
- /* make the brush before this the new active brush
- * - use the one after if this is the first
- * - if this is the only brush, this naturally becomes NULL
- */
- if (brush->prev)
- BKE_gpencil_brush_setactive(ts, brush->prev);
- else
- BKE_gpencil_brush_setactive(ts, brush->next);
-
- /* delete the brush now... */
- BKE_gpencil_brush_delete(ts, brush);
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ int i = 0;
+ for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if (brush->ob_mode == OB_MODE_GPENCIL_PAINT) {
+ if (i == index) {
+ BKE_paint_brush_set(paint, brush);
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ i++;
+ }
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_CANCELLED;
}
-void GPENCIL_OT_brush_remove(wmOperatorType *ot)
+void GPENCIL_OT_brush_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Brush";
- ot->idname = "GPENCIL_OT_brush_remove";
- ot->description = "Remove active Grease Pencil drawing brush";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->name = "Select Brush";
+ ot->idname = "GPENCIL_OT_brush_select";
+ ot->description = "Select a Grease Pencil drawing brush";
/* callbacks */
- ot->exec = gp_brush_remove_exec;
+ ot->exec = gp_brush_select_exec;
ot->poll = gp_active_brush_poll;
-}
-
-/* ********************** Change Brush ***************************** */
-static int gp_brush_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
-{
- uiPopupMenu *pup;
- uiLayout *layout;
-
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "GPENCIL_OT_brush_change", "brush");
- UI_popup_menu_end(C, pup);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- return OPERATOR_INTERFACE;
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of Drawing Brush", 0, INT_MAX);
}
-static int gp_brush_change_exec(bContext *C, wmOperator *op)
+/* ***************** Select Sculpt Brush ************************ */
+
+static int gp_sculpt_select_exec(bContext *C, wmOperator *op)
{
ToolSettings *ts = CTX_data_tool_settings(C);
- bGPDbrush *brush = NULL;
- int brush_num = RNA_enum_get(op->ptr, "brush");
- /* Get brush or create new one */
- if (brush_num == -1) {
- /* Create brush */
- brush = BKE_gpencil_brush_addnew(ts, DATA_("GP_Brush"), true);
+ /* if there's no existing container */
+ if (ts == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Nowhere to go");
+ return OPERATOR_CANCELLED;
}
- else {
- /* Try to get brush */
- brush = BLI_findlink(&ts->gp_brushes, brush_num);
- if (brush == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Cannot change to non-existent brush (index = %d)", brush_num);
- return OPERATOR_CANCELLED;
- }
+ const int index = RNA_int_get(op->ptr, "index");
+ GP_BrushEdit_Settings *gp_sculpt = &ts->gp_sculpt;
+ /* sanity checks */
+ if (ELEM(NULL, gp_sculpt)) {
+ return OPERATOR_CANCELLED;
}
- /* Set active brush */
- BKE_gpencil_brush_setactive(ts, brush);
-
- /* updates */
+ if (index < TOT_GP_EDITBRUSH_TYPES - 1) {
+ gp_sculpt->brushtype = index;
+ }
+ /* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_change(wmOperatorType *ot)
+void GPENCIL_OT_sculpt_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Change Brush";
- ot->idname = "GPENCIL_OT_brush_change";
- ot->description = "Change active Grease Pencil drawing brush";
+ ot->name = "Select Sculpt Brush";
+ ot->idname = "GPENCIL_OT_sculpt_select";
+ ot->description = "Select a Grease Pencil sculpt brush";
/* callbacks */
- ot->invoke = gp_brush_change_invoke;
- ot->exec = gp_brush_change_exec;
- ot->poll = gp_active_brush_poll;
+ ot->exec = gp_sculpt_select_exec;
+ ot->poll = gp_add_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* gp brush to use (dynamic enum) */
- ot->prop = RNA_def_enum(ot->srna, "brush", DummyRNA_DEFAULT_items, 0, "Grease Pencil Brush", "");
- RNA_def_enum_funcs(ot->prop, ED_gpencil_brushes_enum_itemf);
+ /* properties */
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of Sculpt Brush", 0, INT_MAX);
}
-/* ******************* Move Brush Up/Down ************************** */
+/*********************** Vertex Groups ***********************************/
-enum {
- GP_BRUSH_MOVE_UP = -1,
- GP_BRUSH_MOVE_DOWN = 1
-};
+static bool gpencil_vertex_group_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ if (ELEM(ob->mode,
+ OB_MODE_GPENCIL_EDIT,
+ OB_MODE_GPENCIL_SCULPT))
+ {
+ return true;
+ }
+ }
+ }
-static int gp_brush_move_exec(bContext *C, wmOperator *op)
+ return false;
+}
+
+static bool gpencil_vertex_group_weight_poll(bContext *C)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
+ Object *ob = CTX_data_active_object(C);
- int direction = RNA_enum_get(op->ptr, "type");
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ if (ob->mode == OB_MODE_GPENCIL_WEIGHT) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int gpencil_vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
/* sanity checks */
- if (ELEM(NULL, ts, brush)) {
+ if (ELEM(NULL, ts, ob, ob->data))
return OPERATOR_CANCELLED;
- }
- /* up or down? */
- if (direction == GP_BRUSH_MOVE_UP) {
- /* up */
- BLI_remlink(&ts->gp_brushes, brush);
- BLI_insertlinkbefore(&ts->gp_brushes, brush->prev, brush);
- }
- else if (direction == GP_BRUSH_MOVE_DOWN) {
- /* down */
- BLI_remlink(&ts->gp_brushes, brush);
- BLI_insertlinkafter(&ts->gp_brushes, brush->next, brush);
- }
- else {
- BLI_assert(0);
- }
+ ED_gpencil_vgroup_assign(C, ob, ts->vgroup_weight);
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_move(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_assign(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {GP_BRUSH_MOVE_UP, "UP", 0, "Up", ""},
- {GP_BRUSH_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL }
- };
-
/* identifiers */
- ot->name = "Move Brush";
- ot->idname = "GPENCIL_OT_brush_move";
- ot->description = "Move the active Grease Pencil drawing brush up/down in the list";
+ ot->name = "Assign to Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_assign";
+ ot->description = "Assign the selected vertices to the active vertex group";
/* api callbacks */
- ot->exec = gp_brush_move_exec;
- ot->poll = gp_active_brush_poll;
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_assign_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", slot_move, GP_BRUSH_MOVE_UP, "Type", "");
}
-/* ******************* Brush create presets ************************** */
-
-static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
+/* remove point from vertex group */
+static int gpencil_vertex_group_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- BKE_gpencil_brush_init_presets(ts);
+ Object *ob = CTX_data_active_object(C);
+
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->data))
+ return OPERATOR_CANCELLED;
+
+ ED_gpencil_vgroup_remove(C, ob);
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_presets_create(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_remove_from(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create Preset Brushes";
- ot->idname = "GPENCIL_OT_brush_presets_create";
- ot->description = "Create a set of predefined Grease Pencil drawing brushes";
+ ot->name = "Remove from Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_remove_from";
+ ot->description = "Remove the selected vertices from active or all vertex group(s)";
/* api callbacks */
- ot->exec = gp_brush_presets_create_exec;
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_remove_from_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ***************** Copy Brush ************************ */
-
-static int gp_brush_copy_exec(bContext *C, wmOperator *op)
+static int gpencil_vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- /* if there's no existing container */
- if (ts == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for brush data to go");
- return OPERATOR_CANCELLED;
- }
-
- bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
- bGPDbrush *newbrush;
+ Object *ob = CTX_data_active_object(C);
/* sanity checks */
- if (ELEM(NULL, brush))
+ if (ELEM(NULL, ob, ob->data))
return OPERATOR_CANCELLED;
- /* create a brush and duplicate data */
- newbrush = BKE_gpencil_brush_addnew(ts, brush->info, true);
- newbrush->thickness = brush->thickness;
- newbrush->draw_smoothfac = brush->draw_smoothfac;
- newbrush->draw_smoothlvl = brush->draw_smoothlvl;
- newbrush->sublevel = brush->sublevel;
- newbrush->flag = brush->flag;
- newbrush->draw_sensitivity = brush->draw_sensitivity;
- newbrush->draw_strength = brush->draw_strength;
- newbrush->draw_jitter = brush->draw_jitter;
- newbrush->draw_angle = brush->draw_angle;
- newbrush->draw_angle_factor = brush->draw_angle_factor;
- newbrush->draw_random_press = brush->draw_random_press;
- newbrush->draw_random_sub = brush->draw_random_sub;
-
- /* free automatic curves created by default (replaced by copy) */
- curvemapping_free(newbrush->cur_sensitivity);
- curvemapping_free(newbrush->cur_strength);
- curvemapping_free(newbrush->cur_jitter);
-
- /* make a copy of curves */
- newbrush->cur_sensitivity = curvemapping_copy(brush->cur_sensitivity);
- newbrush->cur_strength = curvemapping_copy(brush->cur_strength);
- newbrush->cur_jitter = curvemapping_copy(brush->cur_jitter);
-
- BKE_gpencil_brush_setactive(ts, newbrush);
+ ED_gpencil_vgroup_select(C, ob);
+
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_copy(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Copy Brush";
- ot->idname = "GPENCIL_OT_brush_copy";
- ot->description = "Copy current Grease Pencil drawing brush";
+ ot->name = "Select Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_select";
+ ot->description = "Select all the vertices assigned to the active vertex group";
- /* callbacks */
- ot->exec = gp_brush_copy_exec;
- ot->poll = gp_active_brush_poll;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_select_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ***************** Select Brush ************************ */
-
-static int gp_brush_select_exec(bContext *C, wmOperator *op)
+static int gpencil_vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
- /* if there's no existing container */
- if (ts == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere to go");
- return OPERATOR_CANCELLED;
- }
-
- const int index = RNA_int_get(op->ptr, "index");
- bGPDbrush *brush = BLI_findlink(&ts->gp_brushes, index);
/* sanity checks */
- if (ELEM(NULL, brush)) {
+ if (ELEM(NULL, ob, ob->data))
return OPERATOR_CANCELLED;
- }
- BKE_gpencil_brush_setactive(ts, brush);
+ ED_gpencil_vgroup_deselect(C, ob);
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_select(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_deselect(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Brush";
- ot->idname = "GPENCIL_OT_brush_select";
- ot->description = "Select a Grease Pencil drawing brush";
+ ot->name = "Deselect Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_deselect";
+ ot->description = "Deselect all selected vertices assigned to the active vertex group";
- /* callbacks */
- ot->exec = gp_brush_select_exec;
- ot->poll = gp_active_brush_poll;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_poll;
+ ot->exec = gpencil_vertex_group_deselect_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of Drawing Brush", 0, INT_MAX);
}
-/* ************************************************ */
-/* Palette Operators */
-
-/* ******************* Add New Palette ************************ */
-
-/* add new palette - wrapper around API */
-static int gp_palette_add_exec(bContext *C, wmOperator *op)
+/* invert */
+static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
- /* if there's no existing Grease-Pencil data there, add some */
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
+ /* sanity checks */
+ if (ELEM(NULL, ts, ob, ob->data))
+ return OPERATOR_CANCELLED;
+
+ MDeformVert *dvert;
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
return OPERATOR_CANCELLED;
- }
- if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
- /* add new palette now */
- BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true);
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ for (int i = 0; i < gps->totpoints; i++) {
+ dvert = &gps->dvert[i];
+ if (dvert->dw == NULL) {
+ BKE_gpencil_vgroup_add_point_weight(dvert, def_nr, 1.0f);
+ }
+ else if (dvert->dw->weight == 1.0f) {
+ BKE_gpencil_vgroup_remove_point_weight(dvert, def_nr);
+ }
+ else {
+ dvert->dw->weight = 1.0f - dvert->dw->weight;
+ }
+ }
+ }
+ CTX_DATA_END;
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palette_add(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_invert(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Palette";
- ot->idname = "GPENCIL_OT_palette_add";
- ot->description = "Add new Grease Pencil palette for the active Grease Pencil data-block";
+ ot->name = "Invert Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_invert";
+ ot->description = "Invert weights to the active vertex group";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_invert_exec;
- /* callbacks */
- ot->exec = gp_palette_add_exec;
- ot->poll = gp_add_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* Remove Active Palette ************************* */
-
-static int gp_palette_remove_exec(bContext *C, wmOperator *op)
+/* smooth */
+static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
/* sanity checks */
- if (ELEM(NULL, gpd, palette))
+ if (ELEM(NULL, ts, ob, ob->data))
return OPERATOR_CANCELLED;
- if (BLI_listbase_count_at_most(&gpd->palettes, 2) < 2) {
- BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette, unable to delete the last one");
- return OPERATOR_CANCELLED;
- }
+ bGPDspoint *pta, *ptb, *ptc;
+ MDeformVert *dverta, *dvertb;
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return OPERATOR_CANCELLED;
- /* make the palette before this the new active palette
- * - use the one after if this is the first
- * - if this is the only palette, this naturally becomes NULL
- */
- if (palette->prev)
- BKE_gpencil_palette_setactive(gpd, palette->prev);
- else
- BKE_gpencil_palette_setactive(gpd, palette->next);
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ for (int s = 0; s < repeat; s++) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ /* previous point */
+ if (i > 0) {
+ pta = &gps->points[i - 1];
+ dverta = &gps->dvert[i - 1];
+ }
+ else {
+ pta = &gps->points[i];
+ dverta = &gps->dvert[i];
+ }
+ /* current */
+ ptb = &gps->points[i];
+ dvertb = &gps->dvert[i];
+ /* next point */
+ if (i + 1 < gps->totpoints) {
+ ptc = &gps->points[i + 1];
+ }
+ else {
+ ptc = &gps->points[i];
+ }
- /* delete the palette now... */
- BKE_gpencil_palette_delete(gpd, palette);
+ float wa = BKE_gpencil_vgroup_use_index(dverta, def_nr);
+ float wb = BKE_gpencil_vgroup_use_index(dvertb, def_nr);
+ CLAMP_MIN(wa, 0.0f);
+ CLAMP_MIN(wb, 0.0f);
+
+ /* the optimal value is the corresponding to the interpolation of the weight
+ * at the distance of point b
+ */
+ const float opfac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
+ const float optimal = interpf(wa, wb, opfac);
+ /* Based on influence factor, blend between original and optimal */
+ wb = interpf(wb, optimal, fac);
+ BKE_gpencil_vgroup_add_point_weight(dvertb, def_nr, wb);
+ }
+ }
+ }
+ CTX_DATA_END;
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palette_remove(wmOperatorType *ot)
+void GPENCIL_OT_vertex_group_smooth(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove palette";
- ot->idname = "GPENCIL_OT_palette_remove";
- ot->description = "Remove active Grease Pencil palette";
+ ot->name = "Smooth Vertex Group";
+ ot->idname = "GPENCIL_OT_vertex_group_smooth";
+ ot->description = "Smooth weights to the active vertex group";
+ /* api callbacks */
+ ot->poll = gpencil_vertex_group_weight_poll;
+ ot->exec = gpencil_vertex_group_smooth_exec;
+
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* callbacks */
- ot->exec = gp_palette_remove_exec;
- ot->poll = gp_active_palette_poll;
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
}
-/* ********************** Change Palette ***************************** */
+/****************************** Join ***********************************/
+
+/* userdata for joined_gpencil_fix_animdata_cb() */
+typedef struct tJoinGPencil_AdtFixData {
+ bGPdata *src_gpd;
+ bGPdata *tar_gpd;
-static int gp_palette_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
+ GHash *names_map;
+} tJoinGPencil_AdtFixData;
+
+/* Callback to pass to BKE_fcurves_main_cb() for RNA Paths attached to each F-Curve used in the AnimData */
+static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data;
+ ID *src_id = &afd->src_gpd->id;
+ ID *dst_id = &afd->tar_gpd->id;
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "GPENCIL_OT_palette_change", "palette");
- UI_popup_menu_end(C, pup);
+ GHashIterator gh_iter;
- return OPERATOR_INTERFACE;
+ /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
+ if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "layers",
+ old_name, new_name, 0, 0, false);
+
+ /* we don't want to apply a second remapping on this F-Curve now,
+ * so stop trying to fix names names
+ */
+ break;
+ }
+ }
+ }
+
+ /* Fix driver targets */
+ if (fcu->driver) {
+ /* Fix driver references to invalid ID's */
+ for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
+ /* only change the used targets, since the others will need fixing manually anyway */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ /* change the ID's used... */
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+
+ /* also check on the subtarget...
+ * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
+ * little twists so that we know that it isn't going to clobber the wrong data
+ */
+ if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed */
+ if (!STREQ(old_name, new_name)) {
+ if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
+ /* Fix up path */
+ dtar->rna_path = BKE_animsys_fix_rna_path_rename(id, dtar->rna_path, "layers",
+ old_name, new_name, 0, 0, false);
+ break; /* no need to try any more names for layer path */
+ }
+ }
+ }
+ }
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
+ }
}
-static int gp_palette_change_exec(bContext *C, wmOperator *op)
+/* join objects called from OBJECT_OT_join */
+int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDpalette *palette = NULL;
- int palette_num = RNA_enum_get(op->ptr, "palette");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
+ bGPdata *gpd_dst = NULL;
+ bool ok = false;
+
+ /* Ensure we're in right mode and that the active object is correct */
+ if (!obact || obact->type != OB_GPENCIL)
+ return OPERATOR_CANCELLED;
- /* Get palette or create new one */
- if (palette_num == -1) {
- /* Create palette */
- palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true);
+ bGPdata *gpd = (bGPdata *)obact->data;
+ if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
}
- else {
- /* Try to get palette */
- palette = BLI_findlink(&gpd->palettes, palette_num);
- if (palette == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Cannot change to non-existent palette (index = %d)", palette_num);
- return OPERATOR_CANCELLED;
+ /* Ensure all rotations are applied before */
+ // XXX: Why don't we apply them here instead of warning?
+ CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ {
+ if (base->object->type == OB_GPENCIL) {
+ if ((base->object->rot[0] != 0) ||
+ (base->object->rot[1] != 0) ||
+ (base->object->rot[2] != 0))
+ {
+ BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
+ return OPERATOR_CANCELLED;
+ }
}
}
+ CTX_DATA_END;
- /* Set active palette */
- BKE_gpencil_palette_setactive(gpd, palette);
+ CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ {
+ if (base->object == obact) {
+ ok = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
- /* updates */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ /* that way the active object is always selected */
+ if (ok == false) {
+ BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
+ return OPERATOR_CANCELLED;
+ }
- return OPERATOR_FINISHED;
-}
+ gpd_dst = obact->data;
+ Object *ob_dst = obact;
+
+ /* loop and join all data */
+ CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ {
+ if ((base->object->type == OB_GPENCIL) && (base->object != obact)) {
+ /* we assume that each datablock is not already used in active object */
+ if (obact->data != base->object->data) {
+ Object *ob_src = base->object;
+ bGPdata *gpd_src = base->object->data;
+
+ /* Apply all GP modifiers before */
+ for (GpencilModifierData *md = base->object->greasepencil_modifiers.first; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ if (mti->bakeModifier) {
+ mti->bakeModifier(bmain, depsgraph, md, base->object);
+ }
+ }
-void GPENCIL_OT_palette_change(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Change Palette";
- ot->idname = "GPENCIL_OT_palette_change";
- ot->description = "Change active Grease Pencil palette";
+ /* copy vertex groups to the base one's */
+ int old_idx = 0;
+ for (bDeformGroup *dg = base->object->defbase.first; dg; dg = dg->next) {
+ bDeformGroup *vgroup = MEM_dupallocN(dg);
+ int idx = BLI_listbase_count(&obact->defbase);
+ defgroup_unique_name(vgroup, obact);
+ BLI_addtail(&obact->defbase, vgroup);
+ /* update vertex groups in strokes in original data */
+ for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ MDeformVert *dvert;
+ int i;
+ for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
+ if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
+ dvert->dw->def_nr = idx;
+ }
+ }
+ }
+ }
+ }
+ old_idx++;
+ }
+ if (obact->defbase.first && obact->actdef == 0)
+ obact->actdef = 1;
- /* callbacks */
- ot->invoke = gp_palette_change_invoke;
- ot->exec = gp_palette_change_exec;
- ot->poll = gp_active_palette_poll;
+ /* add missing materials reading source materials and checking in destination object */
+ short *totcol = give_totcolp(ob_src);
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ for (short i = 0; i < *totcol; i++) {
+ Material *tmp_ma = give_current_material(ob_src, i + 1);
+ if (BKE_gpencil_get_material_index(ob_dst, tmp_ma) == 0) {
+ BKE_object_material_slot_add(bmain, ob_dst);
+ assign_material(bmain, ob_dst, tmp_ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF);
+ }
+ }
+
+ /* duplicate bGPDlayers */
+ tJoinGPencil_AdtFixData afd = {0};
+ afd.src_gpd = gpd_src;
+ afd.tar_gpd = gpd_dst;
+ afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
+
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+
+ sub_v3_v3v3(offset_global, obact->loc, base->object->obmat[3]);
+ copy_m3_m4(bmat, obact->obmat);
+ invert_m3_m3(imat, bmat);
+ mul_m3_v3(imat, offset_global);
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+
+ for (bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src);
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ /* recalculate all stroke points */
+ ED_gpencil_parent_location(depsgraph, base->object, gpd_src, gpl_src, diff_mat);
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ Material *ma_src = NULL;
+ int idx;
+ for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+
+ /* reasign material. Look old material and try to find in dst */
+ ma_src = give_current_material(ob_src, gps->mat_nr + 1);
+ if (ma_src != NULL) {
+ idx = BKE_gpencil_get_material_index(ob_dst, ma_src);
+ if (idx > 0) {
+ gps->mat_nr = idx - 1;
+ }
+ else {
+ gps->mat_nr = 0;
+ }
+ }
+ else {
+ gps->mat_nr = 0;
+ }
+
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
+ }
+ }
+ }
- /* gp palette to use (dynamic enum) */
- ot->prop = RNA_def_enum(ot->srna, "palette", DummyRNA_DEFAULT_items, 0, "Grease Pencil Palette", "");
- RNA_def_enum_funcs(ot->prop, ED_gpencil_palettes_enum_itemf);
+ /* be sure name is unique in new object */
+ BLI_uniquename(&gpd_dst->layers, gpl_new, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_new->info));
+ BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
+
+ /* add to destination datablock */
+ BLI_addtail(&gpd_dst->layers, gpl_new);
+ }
+
+ /* Fix all the animation data */
+ BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd);
+ BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
+
+ /* Only copy over animdata now, after all the remapping has been done,
+ * so that we don't have to worry about ambiguities re which datablock
+ * a layer came from!
+ */
+ if (base->object->adt) {
+ if (obact->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ obact->adt = BKE_animdata_copy(bmain, base->object->adt, false, true);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(bmain, &obact->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ if (gpd_src->adt) {
+ if (gpd_dst->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, false, true);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+ }
+
+ /* Free the old object */
+ ED_object_base_free_and_unlink(bmain, scene, base->object);
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain); /* because we removed object(s) */
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
}
-/* ******************* Lock and hide any color non used in current layer ************************** */
+/* Color Handle operator */
+static bool gpencil_active_color_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ if (ob && ob->data && (ob->type == OB_GPENCIL)) {
+ short *totcolp = give_totcolp(ob);
+ return *totcolp > 0;
+ }
+ return false;
+}
-static int gp_palette_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
+
+/* ******************* Lock and hide any color non used in current layer ************************** */
+static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette;
+ Object *ob = CTX_data_active_object(C);
+ MaterialGPencilStyle *gp_style = NULL;
/* sanity checks */
if (ELEM(NULL, gpd))
return OPERATOR_CANCELLED;
- palette = BKE_gpencil_palette_getactive(gpd);
- if (ELEM(NULL, palette))
+ /* first lock and hide all colors */
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ if (totcol == 0)
return OPERATOR_CANCELLED;
- /* first lock and hide all colors */
- for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag |= PC_COLOR_LOCKED;
- palcolor->flag |= PC_COLOR_HIDE;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_STYLE_COLOR_HIDE;
}
/* loop all selected strokes and unlock any color used in active layer */
@@ -1558,140 +2059,49 @@ static int gp_palette_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
+ gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
/* unlock/unhide color if not unlocked before */
- if (gps->palcolor != NULL) {
- gps->palcolor->flag &= ~PC_COLOR_LOCKED;
- gps->palcolor->flag &= ~PC_COLOR_HIDE;
+ if (gp_style != NULL) {
+ gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
}
}
}
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palette_lock_layer(wmOperatorType *ot)
+void GPENCIL_OT_lock_layer(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Disable Unused Layer Colors";
- ot->idname = "GPENCIL_OT_palette_lock_layer";
+ ot->idname = "GPENCIL_OT_lock_layer";
ot->description = "Lock and hide any color not used in any layer";
/* api callbacks */
- ot->exec = gp_palette_lock_layer_exec;
+ ot->exec = gpencil_lock_layer_exec;
ot->poll = gp_active_layer_poll;
}
-/* ************************************************ */
-/* Palette Colors Operators */
-
-/* ******************* Add New Palette ************************ */
-
-/* add new palette - wrapper around API */
-static int gp_palettecolor_add_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
-
- /* if there's no existing Grease-Pencil data there, add some */
- if (gpd_ptr == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
- return OPERATOR_CANCELLED;
- }
- if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
-
- /* verify palette */
- bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr);
- if (palette == NULL)
- palette = BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true);
-
- /* add new palette color now */
- BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true);
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void GPENCIL_OT_palettecolor_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Palette Color";
- ot->idname = "GPENCIL_OT_palettecolor_add";
- ot->description = "Add new Grease Pencil palette color for the active Grease Pencil data-block";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* callbacks */
- ot->exec = gp_palettecolor_add_exec;
- ot->poll = gp_add_poll;
-}
-
-/* ******************* Remove Active Palette color ************************* */
-
-static int gp_palettecolor_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *color = BKE_gpencil_palettecolor_getactive(palette);
-
- /* sanity checks */
- if (ELEM(NULL, gpd, palette, color))
- return OPERATOR_CANCELLED;
-
- /* make the palette color before this the new active color
- * - use the one after if this is the first
- * - if this is the only color, this naturally becomes NULL
- */
- if (color->prev)
- BKE_gpencil_palettecolor_setactive(palette, color->prev);
- else
- BKE_gpencil_palettecolor_setactive(palette, color->next);
+/* ********************** Isolate gpencil_ color **************************** */
- /* delete the strokes */
- BKE_gpencil_palettecolor_delete_strokes(gpd, color->info);
-
- /* delete the palette color now... */
- BKE_gpencil_palettecolor_delete(palette, color);
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void GPENCIL_OT_palettecolor_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove palette color";
- ot->idname = "GPENCIL_OT_palettecolor_remove";
- ot->description = "Remove active Grease Pencil palette color";
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* callbacks */
- ot->exec = gp_palettecolor_remove_exec;
- ot->poll = gp_active_palettecolor_poll;
-}
-
-/* ********************** Isolate palette color **************************** */
-
-static int gp_isolate_palettecolor_exec(bContext *C, wmOperator *op)
+static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *active_color = BKE_gpencil_palettecolor_getactive(palette);
- bGPDpalettecolor *palcolor;
+ Object *ob = CTX_data_active_object(C);
+ Material *active_ma = give_current_material(ob, ob->actcol);
+ MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ MaterialGPencilStyle *gp_style;
- int flags = PC_COLOR_LOCKED;
+ int flags = GP_STYLE_COLOR_LOCKED;
bool isolate = false;
if (RNA_boolean_get(op->ptr, "affect_visibility"))
- flags |= PC_COLOR_HIDE;
+ flags |= GP_STYLE_COLOR_HIDE;
if (ELEM(NULL, gpd, active_color)) {
BKE_report(op->reports, RPT_ERROR, "No active color to isolate");
@@ -1699,15 +2109,19 @@ static int gp_isolate_palettecolor_exec(bContext *C, wmOperator *op)
}
/* Test whether to isolate or clear all flags */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
/* Skip if this is the active one */
- if (palcolor == active_color)
+ if (ma == active_ma)
continue;
/* If the flags aren't set, that means that the color is
- * not alone, so we have some colors to isolate still
- */
- if ((palcolor->flag & flags) == 0) {
+ * not alone, so we have some colors to isolate still
+ */
+ gp_style = ma->gp_style;
+ if ((gp_style->flag & flags) == 0) {
isolate = true;
break;
}
@@ -1716,72 +2130,78 @@ static int gp_isolate_palettecolor_exec(bContext *C, wmOperator *op)
/* Set/Clear flags as appropriate */
if (isolate) {
/* Set flags on all "other" colors */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- if (palcolor == active_color)
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ if (gp_style == active_color)
continue;
else
- palcolor->flag |= flags;
+ gp_style->flag |= flags;
}
}
else {
/* Clear flags - Restore everything else */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag &= ~flags;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~flags;
}
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_isolate(wmOperatorType *ot)
+void GPENCIL_OT_color_isolate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Isolate Palette Color";
- ot->idname = "GPENCIL_OT_palettecolor_isolate";
+ ot->name = "Isolate Color";
+ ot->idname = "GPENCIL_OT_color_isolate";
ot->description = "Toggle whether the active color is the only one that is editable and/or visible";
/* callbacks */
- ot->exec = gp_isolate_palettecolor_exec;
- ot->poll = gp_active_palettecolor_poll;
+ ot->exec = gpencil_color_isolate_exec;
+ ot->poll = gpencil_active_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility", "In addition to toggling "
- "the editability, also affect the visibility");
+ "the editability, also affect the visibility");
}
-/* *********************** Hide Palette colors ******************************** */
+/* *********************** Hide colors ******************************** */
-static int gp_palettecolor_hide_exec(bContext *C, wmOperator *op)
+static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
+ Object *ob = CTX_data_active_object(C);
+ MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
bool unselected = RNA_boolean_get(op->ptr, "unselected");
- /* sanity checks */
- if (ELEM(NULL, gpd, palette, palcolor))
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+ if (totcol == 0)
return OPERATOR_CANCELLED;
if (unselected) {
- bGPDpalettecolor *color;
-
/* hide unselected */
- for (color = palette->colors.first; color; color = color->next) {
- if (color != palcolor) {
- color->flag |= PC_COLOR_HIDE;
+ MaterialGPencilStyle *color = NULL;
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ color = ma->gp_style;
+ if (active_color != color) {
+ color->flag |= GP_STYLE_COLOR_HIDE;
}
}
}
else {
/* hide selected/active */
- palcolor->flag |= PC_COLOR_HIDE;
+ active_color->flag |= GP_STYLE_COLOR_HIDE;
}
/* notifiers */
@@ -1790,18 +2210,18 @@ static int gp_palettecolor_hide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_hide(wmOperatorType *ot)
+void GPENCIL_OT_color_hide(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hide Color(s)";
- ot->idname = "GPENCIL_OT_palettecolor_hide";
+ ot->idname = "GPENCIL_OT_color_hide";
ot->description = "Hide selected/unselected Grease Pencil colors";
/* callbacks */
- ot->exec = gp_palettecolor_hide_exec;
- ot->poll = gp_active_palettecolor_poll; /* NOTE: we need an active color to play with */
+ ot->exec = gpencil_color_hide_exec;
+ ot->poll = gpencil_active_color_poll; /* NOTE: we need an active color to play with */
- /* flags */
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
@@ -1810,25 +2230,22 @@ void GPENCIL_OT_palettecolor_hide(wmOperatorType *ot)
/* ********************** Show All Colors ***************************** */
-/* poll callback for showing colors */
-static bool gp_palettecolor_reveal_poll(bContext *C)
-{
- return ED_gpencil_data_get_active(C) != NULL;
-}
-
-static int gp_palettecolor_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor;
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
- /* sanity checks */
- if (ELEM(NULL, gpd, palette))
+ if (totcol == 0)
return OPERATOR_CANCELLED;
/* make all colors visible */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag &= ~PC_COLOR_HIDE;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
}
/* notifiers */
@@ -1837,36 +2254,40 @@ static int gp_palettecolor_reveal_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_reveal(wmOperatorType *ot)
+void GPENCIL_OT_color_reveal(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Show All Colors";
- ot->idname = "GPENCIL_OT_palettecolor_reveal";
- ot->description = "Unhide all hidden Grease Pencil palette colors";
+ ot->idname = "GPENCIL_OT_color_reveal";
+ ot->description = "Unhide all hidden Grease Pencil gpencil_ colors";
/* callbacks */
- ot->exec = gp_palettecolor_reveal_exec;
- ot->poll = gp_palettecolor_reveal_poll;
+ ot->exec = gpencil_color_reveal_exec;
+ ot->poll = gpencil_active_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ***************** Lock/Unlock All Palette colors ************************ */
+/* ***************** Lock/Unlock All colors ************************ */
-static int gp_palettecolor_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor;
- /* sanity checks */
- if (ELEM(NULL, gpd, palette))
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
+
+ if (totcol == 0)
return OPERATOR_CANCELLED;
/* make all layers non-editable */
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag |= PC_COLOR_LOCKED;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
}
/* notifiers */
@@ -1875,16 +2296,16 @@ static int gp_palettecolor_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_lock_all(wmOperatorType *ot)
+void GPENCIL_OT_color_lock_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Lock All Colors";
- ot->idname = "GPENCIL_OT_palettecolor_lock_all";
+ ot->idname = "GPENCIL_OT_color_lock_all";
ot->description = "Lock all Grease Pencil colors to prevent them from being accidentally modified";
/* callbacks */
- ot->exec = gp_palettecolor_lock_all_exec;
- ot->poll = gp_palettecolor_reveal_poll; /* XXX: could use dedicated poll later */
+ ot->exec = gpencil_color_lock_all_exec;
+ ot->poll = gpencil_active_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1892,19 +2313,22 @@ void GPENCIL_OT_palettecolor_lock_all(wmOperatorType *ot)
/* -------------------------- */
-static int gp_palettecolor_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor;
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+ short *totcol = give_totcolp(ob);
- /* sanity checks */
- if (ELEM(NULL, gpd, palette))
+ if (totcol == 0)
return OPERATOR_CANCELLED;
/* make all layers editable again*/
- for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
- palcolor->flag &= ~PC_COLOR_LOCKED;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
}
/* notifiers */
@@ -1913,94 +2337,32 @@ static int gp_palettecolor_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_unlock_all(wmOperatorType *ot)
+void GPENCIL_OT_color_unlock_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Unlock All Colors";
- ot->idname = "GPENCIL_OT_palettecolor_unlock_all";
+ ot->idname = "GPENCIL_OT_color_unlock_all";
ot->description = "Unlock all Grease Pencil colors so that they can be edited";
/* callbacks */
- ot->exec = gp_palettecolor_unlock_all_exec;
- ot->poll = gp_palettecolor_reveal_poll; /* XXX: could use dedicated poll later */
+ ot->exec = gpencil_color_unlock_all_exec;
+ ot->poll = gpencil_active_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* Move Color Up/Down ************************** */
-enum {
- GP_COLOR_MOVE_UP = -1,
- GP_COLOR_MOVE_DOWN = 1
-};
+/* ***************** Select all strokes using color ************************ */
-static int gp_palettecolor_move_exec(bContext *C, wmOperator *op)
+static int gpencil_color_select_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
-
- int direction = RNA_enum_get(op->ptr, "direction");
+ Object *ob = CTX_data_active_object(C);
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
/* sanity checks */
- if (ELEM(NULL, gpd, palette, palcolor))
- return OPERATOR_CANCELLED;
-
- /* up or down? */
- if (direction == GP_COLOR_MOVE_UP) {
- /* up */
- BLI_remlink(&palette->colors, palcolor);
- BLI_insertlinkbefore(&palette->colors, palcolor->prev, palcolor);
- }
- else if (direction == GP_COLOR_MOVE_DOWN) {
- /* down */
- BLI_remlink(&palette->colors, palcolor);
- BLI_insertlinkafter(&palette->colors, palcolor->next, palcolor);
- }
- else {
- BLI_assert(0);
- }
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void GPENCIL_OT_palettecolor_move(wmOperatorType *ot)
-{
- static const EnumPropertyItem slot_move[] = {
- {GP_COLOR_MOVE_UP, "UP", 0, "Up", ""},
- {GP_COLOR_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Move Palette color";
- ot->idname = "GPENCIL_OT_palettecolor_move";
- ot->description = "Move the active Grease Pencil palette color up/down in the list";
-
- /* api callbacks */
- ot->exec = gp_palettecolor_move_exec;
- ot->poll = gp_palettecolor_reveal_poll; /* XXX: could use dedicated poll later */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_COLOR_MOVE_UP, "Direction", "");
-}
-
-/* ***************** Select all strokes using Palette color ************************ */
-
-static int gp_palettecolor_select_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
-
- /* sanity checks */
- if (ELEM(NULL, gpd, palette, palcolor))
+ if (ELEM(NULL, gpd, gp_style))
return OPERATOR_CANCELLED;
/* read all strokes and select*/
@@ -2013,11 +2375,11 @@ static int gp_palettecolor_select_exec(bContext *C, wmOperator *UNUSED(op))
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)
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)
continue;
/* select */
- if (strcmp(palcolor->info, gps->colorname) == 0) {
+ if (ob->actcol == gps->mat_nr) {
bGPDspoint *pt;
int i;
@@ -2035,56 +2397,16 @@ static int gp_palettecolor_select_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_palettecolor_select(wmOperatorType *ot)
+void GPENCIL_OT_color_select(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Color";
- ot->idname = "GPENCIL_OT_palettecolor_select";
+ ot->idname = "GPENCIL_OT_color_select";
ot->description = "Select all Grease Pencil strokes using current color";
/* callbacks */
- ot->exec = gp_palettecolor_select_exec;
- ot->poll = gp_palettecolor_reveal_poll; /* XXX: could use dedicated poll later */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** Copy Palette color ************************ */
-
-static int gp_palettecolor_copy_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
- bGPDpalettecolor *newcolor;
-
- /* sanity checks */
- if (ELEM(NULL, gpd, palette, palcolor))
- return OPERATOR_CANCELLED;
-
- /* create a new color and duplicate data */
- newcolor = BKE_gpencil_palettecolor_addnew(palette, palcolor->info, true);
- copy_v4_v4(newcolor->color, palcolor->color);
- copy_v4_v4(newcolor->fill, palcolor->fill);
- newcolor->flag = palcolor->flag;
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void GPENCIL_OT_palettecolor_copy(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Copy Color";
- ot->idname = "GPENCIL_OT_palettecolor_copy";
- ot->description = "Copy current Grease Pencil palette color";
-
- /* callbacks */
- ot->exec = gp_palettecolor_copy_exec;
- ot->poll = gp_active_palettecolor_poll;
+ ot->exec = gpencil_color_select_exec;
+ ot->poll = gpencil_active_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index ec67b2da161..f7c08239647 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -54,12 +55,18 @@
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "BKE_main.h"
#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_brush.h"
#include "BKE_gpencil.h"
+#include "BKE_paint.h"
#include "BKE_library.h"
-#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -80,31 +87,70 @@
#include "ED_space_api.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "gpencil_intern.h"
/* ************************************************ */
/* Stroke Edit Mode Management */
-
static bool gpencil_editmode_toggle_poll(bContext *C)
{
+ /* if using gpencil object, use this gpd */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return ob->data != NULL;
+ }
return ED_gpencil_data_get_active(C) != NULL;
}
-static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op)
{
+ const int back = RNA_boolean_get(op->ptr, "back");
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_object = false;
+ short mode;
+ /* if using a gpencil object, use this datablock */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpd = ob->data;
+ is_object = true;
+ }
- if (gpd == NULL)
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active GP data");
return OPERATOR_CANCELLED;
+ }
/* Just toggle editmode flag... */
gpd->flag ^= GP_DATA_STROKE_EDITMODE;
/* recalculate parent matrix */
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- ED_gpencil_reset_layers_parent(gpd);
+ ED_gpencil_reset_layers_parent(depsgraph, ob, gpd);
+ }
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ mode = OB_MODE_GPENCIL_EDIT;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_EDITMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
}
+ /* setup other modes */
+ ED_gpencil_setup_modes(C, gpd, mode);
+ /* set cache as dirty */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
@@ -114,6 +160,8 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Strokes Edit Mode Toggle";
ot->idname = "GPENCIL_OT_editmode_toggle";
@@ -125,6 +173,259 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/* Stroke Paint Mode Management */
+
+static bool gpencil_paintmode_toggle_poll(bContext *C)
+{
+ /* if using gpencil object, use this gpd */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return ob->data != NULL;
+ }
+ return ED_gpencil_data_get_active(C) != NULL;
+}
+
+static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
+{
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ bool is_object = false;
+ short mode;
+ /* if using a gpencil object, use this datablock */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpd = ob->data;
+ is_object = true;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle paintmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_PAINTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ mode = OB_MODE_GPENCIL_PAINT;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* be sure we have brushes */
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ BKE_brush_gpencil_presets(C);
+ }
+
+ /* setup other modes */
+ ED_gpencil_setup_modes(C, gpd, mode);
+ /* set cache as dirty */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_paintmode_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Strokes Paint Mode Toggle";
+ ot->idname = "GPENCIL_OT_paintmode_toggle";
+ ot->description = "Enter/Exit paint mode for Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_paintmode_toggle_exec;
+ ot->poll = gpencil_paintmode_toggle_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/* Stroke Sculpt Mode Management */
+
+static bool gpencil_sculptmode_toggle_poll(bContext *C)
+{
+ /* if using gpencil object, use this gpd */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return ob->data != NULL;
+ }
+ return ED_gpencil_data_get_active(C) != NULL;
+}
+
+static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
+{
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_object = false;
+ short mode;
+ /* if using a gpencil object, use this datablock */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpd = ob->data;
+ is_object = true;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle sculptmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
+ mode = OB_MODE_GPENCIL_SCULPT;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* setup other modes */
+ ED_gpencil_setup_modes(C, gpd, mode);
+ /* set cache as dirty */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_sculptmode_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Strokes Sculpt Mode Toggle";
+ ot->idname = "GPENCIL_OT_sculptmode_toggle";
+ ot->description = "Enter/Exit sculpt mode for Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_sculptmode_toggle_exec;
+ ot->poll = gpencil_sculptmode_toggle_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/* Stroke Weight Paint Mode Management */
+
+static bool gpencil_weightmode_toggle_poll(bContext *C)
+{
+ /* if using gpencil object, use this gpd */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return ob->data != NULL;
+ }
+ return ED_gpencil_data_get_active(C) != NULL;
+}
+
+static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
+{
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_object = false;
+ short mode;
+ /* if using a gpencil object, use this datablock */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpd = ob->data;
+ is_object = true;
+ }
+
+ if (gpd == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Just toggle weightmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
+ mode = OB_MODE_GPENCIL_WEIGHT;
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ /* setup other modes */
+ ED_gpencil_setup_modes(C, gpd, mode);
+ /* set cache as dirty */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Strokes Weight Mode Toggle";
+ ot->idname = "GPENCIL_OT_weightmode_toggle";
+ ot->description = "Enter/Exit weight paint mode for Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_weightmode_toggle_exec;
+ ot->poll = gpencil_weightmode_toggle_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/* ************************************************ */
@@ -137,21 +438,30 @@ static bool gp_stroke_edit_poll(bContext *C)
return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}
+/* poll callback to verify edit mode in 3D view only */
+static bool gp_strokes_edit3d_poll(bContext *C)
+{
+ /* 2 Requirements:
+ * - 1) Editable GP data
+ * - 2) 3D View only
+ */
+ return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C));
+}
+
/* ************ Stroke Hide selection Toggle ************** */
static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- if (ts == NULL)
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d == NULL)
return OPERATOR_CANCELLED;
/* Just toggle alpha... */
- if (ts->gp_sculpt.alpha > 0.0f) {
- ts->gp_sculpt.alpha = 0.0f;
+ if (v3d->vertex_opacity > 0.0f) {
+ v3d->vertex_opacity = 0.0f;
}
else {
- ts->gp_sculpt.alpha = 1.0f;
+ v3d->vertex_opacity = 1.0f;
}
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
@@ -220,7 +530,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
/* make a stupid copy first of the entire stroke (to get the flags too) */
gpsd = MEM_dupallocN(gps);
- BLI_strncpy(gpsd->tmp_layerinfo, layername, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */
+ BLI_strncpy(gpsd->runtime.tmp_layerinfo, layername, sizeof(gpsd->runtime.tmp_layerinfo)); /* saves original layer name */
/* initialize triangle memory - will be calculated on next redraw */
gpsd->triangles = NULL;
@@ -232,6 +542,20 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co
memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
gpsd->totpoints = len;
+ if (gps->dvert != NULL) {
+ gpsd->dvert = MEM_callocN(sizeof(MDeformVert) * len, "gps stroke weights copy");
+ memcpy(gpsd->dvert, gps->dvert + start_idx, sizeof(MDeformVert) * len);
+
+ /* Copy weights */
+ int e = start_idx;
+ for (int j = 0; j < gpsd->totpoints; j++) {
+ MDeformVert *dvert_dst = &gps->dvert[e];
+ MDeformVert *dvert_src = &gps->dvert[j];
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ e++;
+ }
+ }
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
BLI_addtail(new_strokes, gpsd);
@@ -252,6 +576,11 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
/* for each visible (and editable) layer's selected strokes,
* copy the strokes into a temporary buffer, then append
* once all done
@@ -279,8 +608,12 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
/* make direct copies of the stroke and its points */
gpsd = MEM_dupallocN(gps);
- BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo));
+ BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
gpsd->points = MEM_dupallocN(gps->points);
+ if (gps->dvert != NULL) {
+ gpsd->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
+ }
/* triangle information - will be calculated on next redraw */
gpsd->flag |= GP_STROKE_RECALC_CACHES;
@@ -309,6 +642,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -342,7 +676,7 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
ListBase gp_strokes_copypastebuf = {NULL, NULL};
-/* Hash for hanging on to all the palette colors used by strokes in the buffer
+/* Hash for hanging on to all the colors used by strokes in the buffer
*
* This is needed to prevent dangling and unsafe pointers when pasting across datablocks,
* or after a color used by a stroke in the buffer gets deleted (via user action or undo).
@@ -354,11 +688,11 @@ void ED_gpencil_strokes_copybuf_free(void)
{
bGPDstroke *gps, *gpsn;
- /* Free the palettes buffer
- * NOTE: This is done before the strokes so that the name ptrs (keys) are still safe
+ /* Free the colors buffer
+ * NOTE: This is done before the strokes so that the ptrs are still safe
*/
if (gp_strokes_copypastebuf_colors) {
- BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
+ BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, NULL);
gp_strokes_copypastebuf_colors = NULL;
}
@@ -366,8 +700,15 @@ void ED_gpencil_strokes_copybuf_free(void)
for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
gpsn = gps->next;
- if (gps->points) MEM_freeN(gps->points);
- if (gps->triangles) MEM_freeN(gps->triangles);
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ MEM_SAFE_FREE(gps->triangles);
BLI_freelinkN(&gp_strokes_copypastebuf, gps);
}
@@ -378,38 +719,26 @@ void ED_gpencil_strokes_copybuf_free(void)
/* Ensure that destination datablock has all the colours the pasted strokes need
* Helper function for copy-pasting strokes
*/
-GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
+GHash *gp_copybuf_validate_colormap(bContext *C)
{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors");
GHashIterator gh_iter;
- /* If there's no active palette yet (i.e. new datablock), add one */
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- if (palette == NULL) {
- palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true);
- }
-
- /* For each color, figure out what to map to... */
+ /* For each color, check if exist and add if not */
GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
- bGPDpalettecolor *palcolor;
- char *name = BLI_ghashIterator_getKey(&gh_iter);
-
- /* Look for existing color to map to */
- /* XXX: What to do if same name but different color? Behaviour here should depend on a property? */
- palcolor = BKE_gpencil_palettecolor_getbyname(palette, name);
- if (palcolor == NULL) {
- /* Doesn't Exist - Create new matching color for this palette */
- /* XXX: This still doesn't fix the pasting across file boundaries problem... */
- bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter);
- palcolor = MEM_dupallocN(src_color);
- BLI_addtail(&palette->colors, palcolor);
+ int *key = BLI_ghashIterator_getKey(&gh_iter);
+ Material *ma = BLI_ghashIterator_getValue(&gh_iter);
- BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info));
+ if (BKE_gpencil_get_material_index(ob, ma) == 0) {
+ BKE_object_material_slot_add(bmain, ob);
+ assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
}
/* Store this mapping (for use later when pasting) */
- BLI_ghash_insert(new_colors, name, palcolor);
+ BLI_ghash_insert(new_colors, key, ma);
}
return new_colors;
@@ -420,6 +749,7 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
{
+ Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
if (gpd == NULL) {
@@ -427,6 +757,11 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
/* clear the buffer first */
ED_gpencil_strokes_copybuf_free();
@@ -455,8 +790,12 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
/* make direct copies of the stroke and its points */
gpsd = MEM_dupallocN(gps);
- BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */
+ BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo)); /* saves original layer name */
gpsd->points = MEM_dupallocN(gps->points);
+ if (gps->dvert != NULL) {
+ gpsd->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
+ }
/* triangles cache - will be recalculated on next redraw */
gpsd->flag |= GP_STROKE_RECALC_CACHES;
@@ -476,17 +815,15 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- /* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */
+ /* Build up hash of material colors used in these strokes */
if (gp_strokes_copypastebuf.first) {
gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors");
-
+ Material *ma = NULL;
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use(C, gps)) {
- if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) {
- bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor);
-
- BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color);
- gps->palcolor = color;
+ ma = give_current_material(ob, gps->mat_nr + 1);
+ if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, &gps->mat_nr) == false) {
+ BLI_ghash_insert(gp_strokes_copypastebuf_colors, &gps->mat_nr, ma);
}
}
}
@@ -534,9 +871,11 @@ typedef enum eGP_PasteMode {
static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
bGPDframe *gpf;
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
@@ -547,6 +886,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
return OPERATOR_CANCELLED;
}
+ else if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
else if (BLI_listbase_is_empty(&gp_strokes_copypastebuf)) {
BKE_report(op->reports, RPT_ERROR, "No strokes to paste, select and copy some points before trying again");
return OPERATOR_CANCELLED;
@@ -599,14 +942,14 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* Ensure that all the necessary colors exist */
- new_colors = gp_copybuf_validate_colormap(gpd);
+ new_colors = gp_copybuf_validate_colormap(C);
/* Copy over the strokes from the buffer (and adjust the colors) */
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use(C, gps)) {
/* Need to verify if layer exists */
if (type != GP_COPY_MERGE) {
- gpl = BLI_findstring(&gpd->layers, gps->tmp_layerinfo, offsetof(bGPDlayer, info));
+ gpl = BLI_findstring(&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info));
if (gpl == NULL) {
/* no layer - use active (only if layer deleted before paste) */
gpl = CTX_data_active_gpencil_layer(C);
@@ -618,28 +961,33 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
* we are obliged to add a new frame if one
* doesn't exist already
*/
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
+ gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, true);
if (gpf) {
/* Create new stroke */
bGPDstroke *new_stroke = MEM_dupallocN(gps);
- new_stroke->tmp_layerinfo[0] = '\0';
+ new_stroke->runtime.tmp_layerinfo[0] = '\0';
new_stroke->points = MEM_dupallocN(gps->points);
-
+ if (gps->dvert != NULL) {
+ new_stroke->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
+ }
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
new_stroke->triangles = NULL;
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
- /* Fix color references */
- BLI_assert(new_stroke->colorname[0] != '\0');
- new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname);
-
- BLI_assert(new_stroke->palcolor != NULL);
- BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+ /* Remap material */
+ Material *ma = BLI_ghash_lookup(new_colors, &new_stroke->mat_nr);
+ if ((ma) && (BKE_gpencil_get_material_index(ob, ma) > 0)) {
+ gps->mat_nr = BKE_gpencil_get_material_index(ob, ma) - 1;
+ CLAMP_MIN(gps->mat_nr, 0);
+ }
+ else {
+ gps->mat_nr = 0; /* only if the color is not found */
+ }
- /*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */
}
}
}
@@ -648,6 +996,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
BLI_ghash_free(new_colors, NULL, NULL);
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -697,10 +1046,17 @@ static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *U
static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
bGPDlayer *target_layer = NULL;
ListBase strokes = {NULL, NULL};
int layer_num = RNA_enum_get(op->ptr, "layer");
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
+ return OPERATOR_CANCELLED;
+ }
+
/* Get layer or create new one */
if (layer_num == -1) {
/* Create layer */
@@ -748,14 +1104,14 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
/* Paste them all in one go */
if (strokes.first) {
- Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, true);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, cfra_eval, true);
BLI_movelisttolist(&gpf->strokes, &strokes);
BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
}
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -804,8 +1160,10 @@ static bool UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C)
static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
@@ -826,7 +1184,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 1) Check for an existing frame on the current frame */
- bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, CFRA);
+ bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra_eval);
if (gpf) {
/* Shunt all frames after (and including) the existing one later by 1-frame */
for (; gpf; gpf = gpf->next) {
@@ -835,11 +1193,12 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 2) Now add a new frame, with nothing in it */
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
}
CTX_DATA_END;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -876,10 +1235,13 @@ static bool gp_actframe_delete_poll(bContext *C)
/* delete active frame - wrapper around API calls */
static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
@@ -895,6 +1257,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
BKE_gpencil_layer_delframe(gpl, gpf);
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -928,13 +1291,16 @@ static bool gp_actframe_delete_all_poll(bContext *C)
static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
bool success = false;
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
/* try to get the "active" frame - but only if it actually occurs on this frame */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
if (gpf == NULL)
continue;
@@ -949,6 +1315,7 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
/* updates */
if (success) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -983,43 +1350,69 @@ typedef enum eGP_DeleteMode {
GP_DELETEOP_FRAME = 2,
} eGP_DeleteMode;
+typedef enum eGP_DissolveMode {
+ /* dissolve all selected points */
+ GP_DISSOLVE_POINTS = 0,
+ /* dissolve between selected points */
+ GP_DISSOLVE_BETWEEN = 1,
+ /* dissolve unselected points */
+ GP_DISSOLVE_UNSELECT = 2,
+} eGP_DissolveMode;
+
/* ----------------------------------- */
/* Delete selected strokes */
static int gp_delete_selected_strokes(bContext *C)
{
bool changed = false;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps, *gpsn;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
- if (gpf == NULL)
- continue;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ bGPDstroke *gps, *gpsn;
- /* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ if (gpf == NULL)
+ continue;
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
- /* free stroke if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- /* free stroke memory arrays, then stroke itself */
- if (gps->points) MEM_freeN(gps->points);
- if (gps->triangles) MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
- changed = true;
+ /* free stroke if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ MEM_SAFE_FREE(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ changed = true;
+ }
+ }
}
}
}
CTX_DATA_END;
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1031,88 +1424,238 @@ static int gp_delete_selected_strokes(bContext *C)
/* ----------------------------------- */
/* Delete selected points but keep the stroke */
-static int gp_dissolve_selected_points(bContext *C)
+static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bool changed = false;
+ int first = 0;
+ int last = 0;
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps, *gpsn;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
- if (gpf == NULL)
- continue;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- /* simply delete points from selected strokes
- * NOTE: we may still have to remove the stroke if it ends up having no points!
- */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ bGPDstroke *gps, *gpsn;
- /* 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 (gpf == NULL)
+ continue;
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
+ /* simply delete points from selected strokes
+ * NOTE: we may still have to remove the stroke if it ends up having no points!
+ */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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(ob, gpl, gps) == false)
+ continue;
+
+ /* the stroke must have at least one point selected for any operator */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ MDeformVert *dvert = NULL;
+ int i;
+
+ int tot = gps->totpoints; /* number of points in new buffer */
+
+ /* first pass: count points to remove */
+ switch (mode) {
+ case GP_DISSOLVE_POINTS:
+ /* Count how many points are selected (i.e. how many to remove) */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ /* selected point - one of the points to remove */
+ tot--;
+ }
+ }
+ break;
+ case GP_DISSOLVE_BETWEEN:
+ /* need to find first and last point selected */
+ first = -1;
+ last = 0;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ if (first < 0) {
+ first = i;
+ }
+ last = i;
+ }
+ }
+ /* count unselected points in the range */
+ for (i = first, pt = gps->points + first; i < last; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ tot--;
+ }
+ }
+ break;
+ case GP_DISSOLVE_UNSELECT:
+ /* count number of unselected points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ tot--;
+ }
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
- int tot = gps->totpoints; /* number of points in new buffer */
+ /* if no points are left, we simply delete the entire stroke */
+ if (tot <= 0) {
+ /* remove the entire stroke */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+ if (gps->triangles) {
+ MEM_freeN(gps->triangles);
+ }
+ BLI_freelinkN(&gpf->strokes, gps);
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+ else {
+ /* just copy all points to keep into a smaller buffer */
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
+ bGPDspoint *npt = new_points;
- /* First Pass: Count how many points are selected (i.e. how many to remove) */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- /* selected point - one of the points to remove */
- tot--;
- }
- }
+ MDeformVert *new_dvert = NULL;
+ MDeformVert *ndvert = NULL;
- /* if no points are left, we simply delete the entire stroke */
- if (tot <= 0) {
- /* remove the entire stroke */
- MEM_freeN(gps->points);
- if (gps->triangles) {
- MEM_freeN(gps->triangles);
- }
- BLI_freelinkN(&gpf->strokes, gps);
- }
- else {
- /* just copy all unselected into a smaller buffer */
- bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
- bGPDspoint *npt = new_points;
+ if (gps->dvert != NULL) {
+ new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
+ ndvert = new_dvert;
+ }
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) == 0) {
- *npt = *pt;
- npt++;
- }
- }
+ switch (mode) {
+ case GP_DISSOLVE_POINTS:
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) == 0) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ break;
+ case GP_DISSOLVE_BETWEEN:
+ /* copy first segment */
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < first; i++, pt++) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ /* copy segment (selected points) */
+ (gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
+ for (i = first, pt = gps->points + first; i < last; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ /* copy last segment */
+ (gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
+ for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+
+ break;
+ case GP_DISSOLVE_UNSELECT:
+ /* copy any selected point */
+ (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ *npt = *pt;
+ npt++;
+
+ if (gps->dvert != NULL) {
+ *ndvert = *dvert;
+ ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert++;
+ dvert++;
+ }
+ }
+ }
+ break;
+ }
- /* free the old buffer */
- MEM_freeN(gps->points);
+ /* free the old buffer */
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
- /* save the new buffer */
- gps->points = new_points;
- gps->totpoints = tot;
+ /* save the new buffer */
+ gps->points = new_points;
+ gps->dvert = new_dvert;
+ gps->totpoints = tot;
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_CACHES;
- gps->tot_triangles = 0;
+ /* triangles cache needs to be recalculated */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
- /* deselect the stroke, since none of its selected points will still be selected */
- gps->flag &= ~GP_STROKE_SELECT;
- }
+ /* deselect the stroke, since none of its selected points will still be selected */
+ gps->flag &= ~GP_STROKE_SELECT;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
- changed = true;
+ changed = true;
+ }
+ }
}
}
}
CTX_DATA_END;
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1146,17 +1689,17 @@ typedef struct tGPDeleteIsland {
* becomes much less
* 2) Each island gets converted to a new stroke
*/
-void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags)
+void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke,
+ int tag_flags, bool select)
{
tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
bool in_island = false;
int num_islands = 0;
- bGPDspoint *pt;
- int i;
/* First Pass: Identify start/end of islands */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bGPDspoint *pt = gps->points;
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
if (pt->flag & tag_flags) {
/* selected - stop accumulating to island */
in_island = false;
@@ -1198,11 +1741,26 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
/* Compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
new_stroke->totpoints = island->end_idx - island->start_idx + 1;
- new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
- /* Copy over the relevant points */
+ /* Copy over the relevant point data */
+ new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment");
memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints);
+ /* Copy over vertex weight data (if available) */
+ if (new_stroke->dvert != NULL) {
+ /* Copy over the relevant vertex-weight points */
+ new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints, "gp delete stroke fragment weight");
+ memcpy(new_stroke->dvert, gps->dvert + island->start_idx, sizeof(MDeformVert) * new_stroke->totpoints);
+
+ /* Copy weights */
+ int e = island->start_idx;
+ for (int i = 0; i < new_stroke->totpoints; i++) {
+ MDeformVert *dvert_dst = &gps->dvert[e];
+ MDeformVert *dvert_src = &new_stroke->dvert[i];
+ dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ e++;
+ }
+ }
/* Each island corresponds to a new stroke. We must adjust the
* timings of these new strokes:
@@ -1222,6 +1780,11 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
pts = new_stroke->points;
for (j = 0; j < new_stroke->totpoints; j++, pts++) {
pts->time -= delta;
+ /* set flag for select again later */
+ if (select == true) {
+ pts->flag &= ~GP_SPOINT_SELECT;
+ pts->flag |= GP_SPOINT_TAG;
+ }
}
}
@@ -1239,53 +1802,70 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke
MEM_freeN(islands);
/* Delete the old stroke */
- MEM_freeN(gps->points);
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
if (gps->triangles) {
MEM_freeN(gps->triangles);
}
BLI_freelinkN(&gpf->strokes, gps);
}
-
/* Split selected strokes into segments, splitting on selected points */
static int gp_delete_selected_points(bContext *C)
{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bool changed = false;
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps, *gpsn;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
- if (gpf == NULL)
- continue;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ bGPDstroke *gps, *gpsn;
- /* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ if (gpf == NULL)
+ continue;
- /* 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;
+ /* simply delete strokes which are selected */
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+ /* 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(ob, gpl, gps) == false)
+ continue;
- if (gps->flag & GP_STROKE_SELECT) {
- /* deselect old stroke, since it will be used as template for the new strokes */
- gps->flag &= ~GP_STROKE_SELECT;
- /* delete unwanted points by splitting stroke into several smaller ones */
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT);
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* deselect old stroke, since it will be used as template for the new strokes */
+ gps->flag &= ~GP_STROKE_SELECT;
- changed = true;
+ /* delete unwanted points by splitting stroke into several smaller ones */
+ gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false);
+
+ changed = true;
+ }
+ }
}
}
}
CTX_DATA_END;
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1294,6 +1874,12 @@ static int gp_delete_selected_points(bContext *C)
}
}
+/* simple wrapper to external call */
+int gp_delete_selected_point_wrap(bContext *C)
+{
+ return gp_delete_selected_points(C);
+}
+
/* ----------------------------------- */
static int gp_delete_exec(bContext *C, wmOperator *op)
@@ -1344,24 +1930,37 @@ void GPENCIL_OT_delete(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data");
}
-static int gp_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
+static int gp_dissolve_exec(bContext *C, wmOperator *op)
{
- return gp_dissolve_selected_points(C);
+ eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type");
+
+ return gp_dissolve_selected_points(C, mode);
}
void GPENCIL_OT_dissolve(wmOperatorType *ot)
{
+ static EnumPropertyItem prop_gpencil_dissolve_types[] = {
+ { GP_DISSOLVE_POINTS, "POINTS", 0, "Dissolve", "Dissolve selected points" },
+ { GP_DISSOLVE_BETWEEN, "BETWEEN", 0, "Dissolve Between", "Dissolve points between selected points" },
+ { GP_DISSOLVE_UNSELECT, "UNSELECT", 0, "Dissolve Unselect", "Dissolve all unselected points" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
/* identifiers */
ot->name = "Dissolve";
ot->idname = "GPENCIL_OT_dissolve";
ot->description = "Delete selected points without splitting strokes";
/* callbacks */
+ ot->invoke = WM_menu_invoke;
ot->exec = gp_dissolve_exec;
ot->poll = gp_stroke_edit_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_dissolve_types, 0, "Type", "Method used for disolving Stroke points");
}
/* ****************** Snapping - Strokes <-> Cursor ************************ */
@@ -1384,6 +1983,8 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
RegionView3D *rv3d = CTX_wm_region_data(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+ Object *obact = CTX_data_active_object(C);
const float gridf = rv3d->gridview;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -1392,10 +1993,8 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- }
+ /* calculate difference matrix object */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
bGPDspoint *pt;
@@ -1405,37 +2004,32 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
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)
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false)
continue;
// TODO: if entire stroke is selected, offset entire stroke by same amount?
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
/* only if point is selected */
if (pt->flag & GP_SPOINT_SELECT) {
- if (gpl->parent == NULL) {
- pt->x = gridf * floorf(0.5f + pt->x / gridf);
- pt->y = gridf * floorf(0.5f + pt->y / gridf);
- pt->z = gridf * floorf(0.5f + pt->z / gridf);
- }
- else {
- /* apply parent transformations */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* apply parent transformations */
+ float fpt[3];
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
- fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf);
- fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf);
- fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf);
+ fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf);
+ fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf);
+ fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf);
- /* return data */
- copy_v3_v3(&pt->x, fpt);
- gp_apply_parent_point(gpl, pt);
- }
+ /* return data */
+ copy_v3_v3(&pt->x, fpt);
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
}
}
}
}
}
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&obact->id, DEG_TAG_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1463,6 +2057,8 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+ Object *obact = CTX_data_active_object(C); \
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d)->location;
@@ -1473,10 +2069,8 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- }
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
bGPDspoint *pt;
@@ -1486,7 +2080,7 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
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)
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false)
continue;
/* only continue if this stroke is selected (editable doesn't guarantee this)... */
if ((gps->flag & GP_STROKE_SELECT) == 0)
@@ -1509,9 +2103,7 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
copy_v3_v3(&pt->x, cursor_global);
- if (gpl->parent != NULL) {
- gp_apply_parent_point(gpl, pt);
- }
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
}
}
}
@@ -1520,6 +2112,8 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&obact->id, DEG_TAG_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -1551,6 +2145,8 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
+ Object *obact = CTX_data_active_object(C); \
float *cursor = ED_view3d_cursor3d_get(scene, v3d)->location;
float centroid[3] = {0.0f};
@@ -1566,10 +2162,8 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- }
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
bGPDspoint *pt;
@@ -1579,7 +2173,7 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
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)
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false)
continue;
/* only continue if this stroke is selected (editable doesn't guarantee this)... */
if ((gps->flag & GP_STROKE_SELECT) == 0)
@@ -1587,18 +2181,13 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
- if (gpl->parent == NULL) {
- add_v3_v3(centroid, &pt->x);
- minmax_v3v3_v3(min, max, &pt->x);
- }
- else {
- /* apply parent transformations */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* apply parent transformations */
+ float fpt[3];
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
add_v3_v3(centroid, fpt);
- minmax_v3v3_v3(min, max, fpt);
- }
+ minmax_v3v3_v3(min, max, fpt);
+
count++;
}
}
@@ -1616,7 +2205,9 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
}
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+
return OPERATOR_FINISHED;
}
@@ -1650,13 +2241,20 @@ static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* Apply thickness */
- gps->thickness = gps->thickness + gpl->thickness;
+ if ((gps->thickness == 0) && (gpl->line_change == 0)) {
+ gps->thickness = gpl->thickness;
+ }
+ else {
+ gps->thickness = gps->thickness + gpl->line_change;
+ }
}
}
/* clear value */
gpl->thickness = 0.0f;
+ gpl->line_change = 0;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1685,6 +2283,8 @@ enum {
static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
const int type = RNA_enum_get(op->ptr, "type");
/* sanity checks */
@@ -1698,13 +2298,13 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
continue;
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- bGPDpalettecolor *palcolor = gps->palcolor;
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
/* skip strokes that are not selected or invalid for current view */
if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false)
continue;
/* skip hidden or locked colors */
- if (!palcolor || (palcolor->flag & PC_COLOR_HIDE) || (palcolor->flag & PC_COLOR_LOCKED))
+ if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) || (gp_style->flag & GP_STYLE_COLOR_LOCKED))
continue;
switch (type) {
@@ -1729,6 +2329,7 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1809,15 +2410,18 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
}
/* Helper: copy point between strokes */
-static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float delta[3],
+static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, int idx, float delta[3],
float pressure, float strength, float deltatime)
{
bGPDspoint *newpoint;
gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
+ }
gps->totpoints++;
-
newpoint = &gps->points[gps->totpoints - 1];
+
newpoint->x = point->x * delta[0];
newpoint->y = point->y * delta[1];
newpoint->z = point->z * delta[2];
@@ -1825,6 +2429,14 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float
newpoint->pressure = pressure;
newpoint->strength = strength;
newpoint->time = point->time + deltatime;
+
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert = &gps->dvert[idx];
+ MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1];
+
+ newdvert->totweight = dvert->totweight;
+ newdvert->dw = MEM_dupallocN(dvert->dw);
+ }
}
/* Helper: join two strokes using the shortest distance (reorder stroke if necessary ) */
@@ -1870,18 +2482,18 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, co
/* 1st: add one tail point to start invisible area */
point = gps_a->points[gps_a->totpoints - 1];
deltatime = point.time;
- gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, 0.0f);
+ gpencil_stroke_copy_point(gps_a, &point, gps_a->totpoints - 1, delta, 0.0f, 0.0f, 0.0f);
/* 2nd: add one head point to finish invisible area */
point = gps_b->points[0];
- gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, deltatime);
+ gpencil_stroke_copy_point(gps_a, &point, 0, delta, 0.0f, 0.0f, deltatime);
}
/* 3rd: add all points */
for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
/* check if still room in buffer */
if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) {
- gpencil_stroke_copy_point(gps_a, pt, delta, pt->pressure, pt->strength, deltatime);
+ gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime);
}
}
}
@@ -1891,8 +2503,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *activegpl = BKE_gpencil_layer_getactive(gpd);
bGPDstroke *gps, *gpsn;
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
+ Object *ob = CTX_data_active_object(C);
bGPDframe *gpf_a = NULL;
bGPDstroke *stroke_a = NULL;
@@ -1928,7 +2539,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
continue;
}
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
@@ -1948,15 +2559,17 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
if (new_stroke == NULL) {
new_stroke = MEM_dupallocN(stroke_a);
new_stroke->points = MEM_dupallocN(stroke_a->points);
+ if (stroke_a->dvert != NULL) {
+ new_stroke->dvert = MEM_dupallocN(stroke_a->dvert);
+ BKE_gpencil_stroke_weights_duplicate(stroke_a, new_stroke);
+ }
new_stroke->triangles = NULL;
new_stroke->tot_triangles = 0;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
/* if new, set current color */
if (type == GP_STROKE_JOINCOPY) {
- new_stroke->palcolor = palcolor;
- BLI_strncpy(new_stroke->colorname, palcolor->info, sizeof(new_stroke->colorname));
- new_stroke->flag |= GP_STROKE_RECALC_COLOR;
+ new_stroke->mat_nr = stroke_a->mat_nr;
}
}
@@ -1995,6 +2608,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -2030,6 +2644,7 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot)
static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
/* sanity checks */
if (ELEM(NULL, gpd))
@@ -2049,7 +2664,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
@@ -2061,6 +2676,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -2084,33 +2700,42 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
/* ***************** Reproject Strokes ********************** */
typedef enum eGP_ReprojectModes {
+ /* Axis (equal to lock axis) */
+ GP_REPROJECT_AXIS = 0,
/* On same plane, parallel to viewplane */
- GP_REPROJECT_PLANAR = 0,
+ GP_REPROJECT_PLANAR,
/* Reprojected on to the scene geometry */
GP_REPROJECT_SURFACE,
} eGP_ReprojectModes;
-static bool gp_strokes_reproject_poll(bContext *C)
-{
- /* 2 Requirements:
- * - 1) Editable GP data
- * - 2) 3D View only (2D editors don't have projection issues)
- */
- return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C));
-}
-
static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = sa->spacedata.first;
+
GP_SpaceConversion gsc = {NULL};
- eGP_ReprojectModes mode = RNA_boolean_get(op->ptr, "type");
+ eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
+
+ int lock_axis = ts->gp_sculpt.lock_axis;
+ float origin[3];
+
+ if ((mode == GP_REPROJECT_AXIS) && (lock_axis == GP_LOCKAXIS_NONE)) {
+ BKE_report(op->reports, RPT_ERROR, "To reproject by axis, a lock axis must be set before");
+ return OPERATOR_CANCELLED;
+ }
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
/* init autodist for geometry projection */
if (mode == GP_REPROJECT_SURFACE) {
- struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0);
}
@@ -2127,9 +2752,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
/* Compute inverse matrix for unapplying parenting once instead of doing per-point */
/* TODO: add this bit to the iteration macro? */
- if (gpl->parent) {
- invert_m4_m4(inverse_diff_mat, diff_mat);
- }
+ invert_m4_m4(inverse_diff_mat, diff_mat);
/* Adjust each point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
@@ -2140,19 +2763,28 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
* coordinates, resulting in lost precision, which in turn causes stairstepping
* artifacts in the final points.
*/
- if (gpl->parent == NULL) {
- gp_point_to_xy_fl(&gsc, gps, pt, &xy[0], &xy[1]);
- }
- else {
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
+
+ /* Project stroke in the axis locked */
+ if (mode == GP_REPROJECT_AXIS) {
+ if (lock_axis > GP_LOCKAXIS_NONE) {
+ ED_gp_get_drawing_reference(v3d, scene, ob, gpl,
+ ts->gpencil_v3d_align, origin);
+ ED_gp_project_point_to_plane(ob, rv3d, origin,
+ lock_axis - 1, &pt2);
+
+ copy_v3_v3(&pt->x, &pt2.x);
+
+ /* apply parent again */
+ gp_apply_parent_point(depsgraph, ob, gpd, gpl, pt);
+ }
}
-
/* Project screenspace back to 3D space (from current perspective)
* so that all points have been treated the same way
*/
- if (mode == GP_REPROJECT_PLANAR) {
+ else if (mode == GP_REPROJECT_PLANAR) {
/* Planar - All on same plane parallel to the viewplane */
gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
}
@@ -2175,7 +2807,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
}
/* Unapply parent corrections */
- if (gpl->parent) {
+ if (mode != GP_REPROJECT_AXIS) {
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
@@ -2183,6 +2815,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
}
GP_EDITABLE_STROKES_END;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -2190,6 +2823,9 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_reproject(wmOperatorType *ot)
{
static const EnumPropertyItem reproject_type[] = {
+ { GP_REPROJECT_AXIS, "AXIS", 0, "Axis",
+ "Reproject the strokes using the current lock axis configuration. This is the same projection using while"
+ "drawing new strokes" },
{GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar",
"Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
"using 'Cursor' Stroke Placement"},
@@ -2208,10 +2844,10 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = gp_strokes_reproject_exec;
- ot->poll = gp_strokes_reproject_poll;
+ ot->poll = gp_strokes_edit3d_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", reproject_type, GP_REPROJECT_PLANAR, "Projection Type", "");
@@ -2229,7 +2865,7 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps)
if (pt->flag & GP_SPOINT_SELECT) {
if (i + 1 < gps->totpoints) {
if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
- ++totnewpoints;
+ totnewpoints++;
}
}
}
@@ -2237,6 +2873,7 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps)
return totnewpoints;
}
+
static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -2267,6 +2904,9 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
/* resize the points arrys */
gps->totpoints += totnewpoints;
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
gps->flag |= GP_STROKE_RECALC_CACHES;
/* loop and interpolate */
@@ -2275,19 +2915,27 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
bGPDspoint *pt = &temp_points[i];
bGPDspoint *pt_final = &gps->points[i2];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
/* copy current point */
copy_v3_v3(&pt_final->x, &pt->x);
pt_final->pressure = pt->pressure;
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
- ++i2;
+
+ dvert_final->totweight = 0;
+ dvert_final->dw = NULL;
+ i2++;
/* if next point is selected add a half way point */
if (pt->flag & GP_SPOINT_SELECT) {
if (i + 1 < oldtotpoints) {
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
pt_final = &gps->points[i2];
+ if (gps->dvert != NULL) {
+ dvert_final = &gps->dvert[i2];
+ }
/* Interpolate all values */
bGPDspoint *next = &temp_points[i + 1];
interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
@@ -2296,7 +2944,11 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
- ++i2;
+
+ dvert_final->totweight = 0;
+ dvert_final->dw = NULL;
+
+ i2++;
}
}
}
@@ -2309,6 +2961,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_END;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -2328,7 +2981,7 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
ot->poll = gp_active_layer_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, 5);
@@ -2336,3 +2989,414 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+
+/* ** simplify stroke *** */
+static int gp_stroke_simplify_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ float factor = RNA_float_get(op->ptr, "factor");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* simplify stroke using Ramer-Douglas-Peucker algorithm */
+ BKE_gpencil_simplify_stroke(gps, factor);
+ }
+ }
+ GP_EDITABLE_STROKES_END;
+
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_simplify(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Simplify Stroke";
+ ot->idname = "GPENCIL_OT_stroke_simplify";
+ ot->description = "Simplify selected stroked reducing number of points";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_simplify_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, 100.0f, "Factor", "", 0.0f, 100.0f);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ** simplify stroke using fixed algorith *** */
+static int gp_stroke_simplify_fixed_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ int steps = RNA_int_get(op->ptr, "step");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd))
+ return OPERATOR_CANCELLED;
+
+ /* Go through each editable + selected stroke */
+ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (int i = 0; i < steps; i++) {
+ BKE_gpencil_simplify_fixed(gps);
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END;
+
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Simplify Fixed Stroke";
+ ot->idname = "GPENCIL_OT_stroke_simplify_fixed";
+ ot->description = "Simplify selected stroked reducing number of points using fixed algorithm";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_simplify_fixed_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Steps", "Number of simplify steps", 1, 10);
+
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+}
+
+/* ***************** Separate Strokes ********************** */
+typedef enum eGP_SeparateModes {
+ /* Points */
+ GP_SEPARATE_POINT = 0,
+ /* Selected Strokes */
+ GP_SEPARATE_STROKE,
+ /* Current Layer */
+ GP_SEPARATE_LAYER,
+} eGP_SeparateModes;
+
+static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
+{
+ Base *base_new;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base_old = CTX_data_active_base(C);
+ bGPdata *gpd_src = ED_gpencil_data_get_active(C);
+ Object *ob = CTX_data_active_object(C);
+
+ Object *ob_dst = NULL;
+ bGPdata *gpd_dst = NULL;
+ bGPDlayer *gpl_dst = NULL;
+ bGPDframe *gpf_dst = NULL;
+ bGPDspoint *pt;
+ Material *ma = NULL;
+ int i, idx;
+
+ eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd_src)) {
+ return OPERATOR_CANCELLED;
+ }
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
+
+ /* create a new object */
+ base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, 0);
+ ob_dst = base_new->object;
+
+ /* create new grease pencil datablock */
+ // XXX: check usercounts
+ gpd_dst = BKE_gpencil_data_addnew(bmain, "GPencil");
+ ob_dst->data = (bGPdata *)gpd_dst;
+
+ int totslots = ob_dst->totcol;
+ int totadd = 0;
+
+ /* loop old datablock and separate parts */
+ if ((mode == GP_SEPARATE_POINT) || (mode == GP_SEPARATE_STROKE)) {
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ gpl_dst = NULL;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL) {
+ continue;
+ }
+
+ gpf_dst = NULL;
+
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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(ob, gpl, gps) == false) {
+ continue;
+ }
+ /* separate selected strokes */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* add layer if not created before */
+ if (gpl_dst == NULL) {
+ gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
+ }
+
+ /* add frame if not created before */
+ if (gpf_dst == NULL) {
+ gpf_dst = BKE_gpencil_layer_getframe(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
+ }
+
+ /* add duplicate materials */
+ ma = give_current_material(ob, gps->mat_nr + 1);
+ idx = BKE_gpencil_get_material_index(ob_dst, ma);
+ if (idx == 0) {
+
+ totadd++;
+ ob_dst->actcol = totadd;
+ ob_dst->totcol = totadd;
+
+ if (totadd > totslots) {
+ BKE_object_material_slot_add(bmain, ob_dst);
+ }
+
+ assign_material(bmain, ob_dst, ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF);
+ idx = totadd;
+ }
+
+ /* selected points mode */
+ if (mode == GP_SEPARATE_POINT) {
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+
+ /* reasign material */
+ gps_dst->mat_nr = idx - 1;
+
+ /* link to destination frame */
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+
+ /* Invert selection status of all points in destination stroke */
+ for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
+ pt->flag ^= GP_SPOINT_SELECT;
+ }
+
+ /* delete selected points from destination stroke */
+ gp_stroke_delete_tagged_points(gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false);
+
+ /* delete selected points from origin stroke */
+ gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false);
+ }
+ /* selected strokes mode */
+ else if (mode == GP_SEPARATE_STROKE) {
+ /* deselect old stroke */
+ gps->flag &= ~GP_STROKE_SELECT;
+ /* unlink from source frame */
+ BLI_remlink(&gpf->strokes, gps);
+ gps->prev = gps->next = NULL;
+ /* relink to destination frame */
+ BLI_addtail(&gpf_dst->strokes, gps);
+ /* reasign material */
+ gps->mat_nr = idx - 1;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+ else if (mode == GP_SEPARATE_LAYER) {
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ if (gpl) {
+ /* try to set a new active layer in source datablock */
+ if (gpl->prev) {
+ BKE_gpencil_layer_setactive(gpd_src, gpl->prev);
+ }
+ else if (gpl->next) {
+ BKE_gpencil_layer_setactive(gpd_src, gpl->next);
+ }
+ /* unlink from source datablock */
+ BLI_remlink(&gpd_src->layers, gpl);
+ gpl->prev = gpl->next = NULL;
+ /* relink to destination datablock */
+ BLI_addtail(&gpd_dst->layers, gpl);
+ }
+ }
+ DEG_id_tag_update(&gpd_src->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&gpd_dst->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_separate(wmOperatorType *ot)
+{
+ static const EnumPropertyItem separate_type[] = {
+ {GP_SEPARATE_POINT, "POINT", 0, "Selected Points", "Separate the selected points" },
+ {GP_SEPARATE_STROKE, "STROKE", 0, "Selected Strokes", "Separate the selected strokes"},
+ {GP_SEPARATE_LAYER, "LAYER", 0, "Active Layer", "Separate the strokes of the current layer" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* identifiers */
+ ot->name = "Separate Strokes";
+ ot->idname = "GPENCIL_OT_stroke_separate";
+ ot->description = "Separate the selected strokes or layer in a new grease pencil object";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gp_stroke_separate_exec;
+ ot->poll = gp_strokes_edit3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", "");
+}
+
+/* ***************** Split Strokes ********************** */
+static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDspoint *pt;
+ int i;
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ /* loop strokes and split parts */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ bGPDstroke *gps, *gpsn;
+
+ if (gpf == NULL) {
+ continue;
+ }
+
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ /* 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(ob, gpl, gps) == false) {
+ continue;
+ }
+ /* split selected strokes */
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+
+ /* link to same frame */
+ BLI_addtail(&gpf->strokes, gps_dst);
+
+ /* invert selection status of all points in destination stroke */
+ for (i = 0, pt = gps_dst->points; i < gps_dst->totpoints; i++, pt++) {
+ pt->flag ^= GP_SPOINT_SELECT;
+ }
+
+ /* delete selected points from destination stroke */
+ gp_stroke_delete_tagged_points(gpf, gps_dst, NULL, GP_SPOINT_SELECT, true);
+
+ /* delete selected points from origin stroke */
+ gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false);
+ }
+ }
+ /* select again tagged points */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *ptn = gps->points;
+ for (int i2 = 0; i2 < gps->totpoints; i2++, ptn++) {
+ if (ptn->flag & GP_SPOINT_TAG) {
+ ptn->flag |= GP_SPOINT_SELECT;
+ ptn->flag &= ~GP_SPOINT_TAG;
+ }
+ }
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split Strokes";
+ ot->idname = "GPENCIL_OT_stroke_split";
+ ot->description = "Split selected points as new stroke on same frame";
+
+ /* callbacks */
+ ot->exec = gp_stroke_split_exec;
+ ot->poll = gp_strokes_edit3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
new file mode 100644
index 00000000000..c6df07ae83e
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -0,0 +1,1258 @@
+/*
+ * ***** 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, Joshua Leung
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/gpencil/gpencil_fill.c
+ * \ingroup edgpencil
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_stack.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_image_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_main.h"
+#include "BKE_brush.h"
+#include "BKE_image.h"
+#include "BKE_gpencil.h"
+#include "BKE_material.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_paint.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_view3d.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+#include "GPU_matrix.h"
+#include "GPU_framebuffer.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+#define LEAK_HORZ 0
+#define LEAK_VERT 1
+
+
+/* Temporary fill operation data (op->customdata) */
+typedef struct tGPDfill {
+ struct Main *bmain;
+ struct Depsgraph *depsgraph;
+ struct wmWindow *win; /* window where painting originated */
+ struct Scene *scene; /* current scene from context */
+ struct Object *ob; /* current active gp object */
+ struct ScrArea *sa; /* area where painting originated */
+ struct RegionView3D *rv3d; /* region where painting originated */
+ struct View3D *v3d; /* view3 where painting originated */
+ struct ARegion *ar; /* region where painting originated */
+ struct bGPdata *gpd; /* current GP datablock */
+ struct Material *mat; /* current material */
+ struct bGPDlayer *gpl; /* layer */
+ struct bGPDframe *gpf; /* frame */
+
+ short flag; /* flags */
+ short oldkey; /* avoid too fast events */
+ bool on_back; /* send to back stroke */
+
+ int center[2]; /* mouse fill center position */
+ int sizex; /* windows width */
+ int sizey; /* window height */
+ int lock_axis; /* lock to viewport axis */
+
+ short fill_leak; /* number of pixel to consider the leak is too small (x 2) */
+ float fill_threshold; /* factor for transparency */
+ int fill_simplylvl; /* number of simplify steps */
+ int fill_draw_mode; /* boundary limits drawing mode */
+
+ short sbuffer_size; /* number of elements currently in cache */
+ void *sbuffer; /* temporary points */
+ float *depth_arr; /* depth array for reproject */
+
+ Image *ima; /* temp image */
+ BLI_Stack *stack; /* temp points data */
+ void *draw_handle_3d; /* handle for drawing strokes while operator is running 3d stuff */
+} tGPDfill;
+
+
+ /* draw a given stroke using same thickness and color for all points */
+static void gp_draw_basic_stroke(
+ tGPDfill *tgpf, bGPDstroke *gps, const float diff_mat[4][4],
+ bool cyclic, float ink[4], int flag, float thershold)
+{
+ bGPDspoint *points = gps->points;
+
+ Material *ma = tgpf->mat;
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ int totpoints = gps->totpoints;
+ float fpt[3];
+ float col[4];
+
+ copy_v4_v4(col, ink);
+
+ /* if cyclic needs more vertex */
+ int cyclic_add = (cyclic) ? 1 : 0;
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* draw stroke curve */
+ glLineWidth(1.0f);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+
+ for (int i = 0; i < totpoints; i++, pt++) {
+
+ if (flag & GP_BRUSH_FILL_HIDE) {
+ float alpha = gp_style->stroke_rgba[3] * pt->strength;
+ CLAMP(alpha, 0.0f, 1.0f);
+ col[3] = alpha <= thershold ? 0.0f : 1.0f;
+ }
+ else {
+ col[3] = 1.0f;
+ }
+ /* set point */
+ immAttrib4fv(color, col);
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ immVertex3fv(pos, fpt);
+ }
+
+ if (cyclic && totpoints > 2) {
+ /* draw line to first point to complete the cycle */
+ immAttrib4fv(color, col);
+ mul_v3_m4v3(fpt, diff_mat, &points->x);
+ immVertex3fv(pos, fpt);
+ }
+
+ immEnd();
+ immUnbindProgram();
+}
+
+/* loop all layers */
+static void gp_draw_datablock(tGPDfill *tgpf, float ink[4])
+{
+ /* duplicated: etempFlags */
+ enum {
+ GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */
+ GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */
+ };
+
+ Object *ob = tgpf->ob;
+ bGPdata *gpd = tgpf->gpd;
+ int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
+
+ tGPDdraw tgpw;
+ tgpw.rv3d = tgpf->rv3d;
+ tgpw.depsgraph = tgpf->depsgraph;
+ tgpw.ob = ob;
+ tgpw.gpd = gpd;
+ tgpw.offsx = 0;
+ tgpw.offsy = 0;
+ tgpw.winx = tgpf->ar->winx;
+ tgpw.winy = tgpf->ar->winy;
+ tgpw.dflag = 0;
+ tgpw.disable_fill = 1;
+ tgpw.dflag |= (GP_DRAWFILLS_ONLY3D | GP_DRAWFILLS_NOSTATUS);
+
+ glEnable(GL_BLEND);
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* calculate parent position */
+ ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, tgpw.diff_mat);
+
+ /* do not draw layer if hidden */
+ if (gpl->flag & GP_LAYER_HIDE)
+ continue;
+
+ /* get frame to draw */
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
+ if (gpf == NULL)
+ continue;
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if stroke can be drawn */
+ if ((gps->points == NULL) || (gps->totpoints < 2)) {
+ continue;
+ }
+ /* check if the color is visible */
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE)) {
+ continue;
+ }
+
+ tgpw.gps = gps;
+ tgpw.gpl = gpl;
+ tgpw.gpf = gpf;
+ tgpw.t_gpf = gpf;
+
+ /* reduce thickness to avoid gaps */
+ tgpw.lthick = gpl->line_change - 4;
+ tgpw.opacity = 1.0;
+ copy_v4_v4(tgpw.tintcolor, ink);
+ tgpw.onion = true;
+ tgpw.custonion = true;
+
+ /* normal strokes */
+ if ((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
+ (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH))
+ {
+ ED_gp_draw_fill(&tgpw);
+
+ }
+
+ /* 3D Lines with basic shapes and invisible lines */
+ if ((tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ||
+ (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH))
+ {
+ gp_draw_basic_stroke(tgpf, gps, tgpw.diff_mat, gps->flag & GP_STROKE_CYCLIC, ink,
+ tgpf->flag, tgpf->fill_threshold);
+ }
+ }
+ }
+
+ glDisable(GL_BLEND);
+}
+
+ /* draw strokes in offscreen buffer */
+static void gp_render_offscreen(tGPDfill *tgpf)
+{
+ bool is_ortho = false;
+ float winmat[4][4];
+
+ if (!tgpf->gpd) {
+ return;
+ }
+
+ char err_out[256] = "unknown";
+ GPUOffScreen *offscreen = GPU_offscreen_create(tgpf->sizex, tgpf->sizey, 0, true, false, err_out);
+ GPU_offscreen_bind(offscreen, true);
+ uint flag = IB_rect | IB_rectfloat;
+ ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag);
+
+ rctf viewplane;
+ float clipsta, clipend;
+
+ is_ortho = ED_view3d_viewplane_get(tgpf->depsgraph, tgpf->v3d, tgpf->rv3d, tgpf->sizex, tgpf->sizey, &viewplane, &clipsta, &clipend, NULL);
+ if (is_ortho) {
+ orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
+ }
+ else {
+ perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ }
+
+ /* set temporary new size */
+ int bwinx = tgpf->ar->winx;
+ int bwiny = tgpf->ar->winy;
+ rcti brect = tgpf->ar->winrct;
+
+ tgpf->ar->winx = (short) tgpf->sizex;
+ tgpf->ar->winy = (short) tgpf->sizey;
+ tgpf->ar->winrct.xmin = 0;
+ tgpf->ar->winrct.ymin = 0;
+ tgpf->ar->winrct.xmax = tgpf->sizex;
+ tgpf->ar->winrct.ymax = tgpf->sizey;
+
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_set();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ED_view3d_update_viewmat(
+ tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar,
+ NULL, winmat, NULL);
+ /* set for opengl */
+ GPU_matrix_projection_set(tgpf->rv3d->winmat);
+ GPU_matrix_set(tgpf->rv3d->viewmat);
+
+ /* draw strokes */
+ float ink[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
+ gp_draw_datablock(tgpf, ink);
+
+ /* restore size */
+ tgpf->ar->winx = (short)bwinx;
+ tgpf->ar->winy = (short)bwiny;
+ tgpf->ar->winrct = brect;
+
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+
+ /* create a image to see result of template */
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(offscreen, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+ if (ibuf->rect_float && ibuf->rect) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ tgpf->ima = BKE_image_add_from_imbuf(tgpf->bmain, ibuf, "GP_fill");
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+
+ BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
+
+ /* switch back to window-system-provided framebuffer */
+ GPU_offscreen_unbind(offscreen, true);
+ GPU_offscreen_free(offscreen);
+}
+
+/* return pixel data (rgba) at index */
+static void get_pixel(ImBuf *ibuf, int idx, float r_col[4])
+{
+ if (ibuf->rect_float) {
+ float *frgba = &ibuf->rect_float[idx * 4];
+ copy_v4_v4(r_col, frgba);
+ }
+ else {
+ /* XXX: This case probably doesn't happen, as we only write to the float buffer,
+ * but we get compiler warnings about uninitialised vars otherwise
+ */
+ BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!");
+ zero_v4(r_col);
+ }
+}
+
+/* set pixel data (rgba) at index */
+static void set_pixel(ImBuf *ibuf, int idx, const float col[4])
+{
+ //BLI_assert(idx <= ibuf->x * ibuf->y);
+ if (ibuf->rect) {
+ uint *rrect = &ibuf->rect[idx];
+ uchar ccol[4];
+
+ rgba_float_to_uchar(ccol, col);
+ *rrect = *((uint *)ccol);
+ }
+
+ if (ibuf->rect_float) {
+ float *rrectf = &ibuf->rect_float[idx * 4];
+ copy_v4_v4(rrectf, col);
+ }
+}
+
+/* check if the size of the leak is narrow to determine if the stroke is closed
+ * this is used for strokes with small gaps between them to get a full fill
+ * and do not get a full screen fill.
+ *
+ * \param ibuf Image pixel data
+ * \param maxpixel Maximum index
+ * \param limit Limit of pixels to analize
+ * \param index Index of current pixel
+ * \param type 0-Horizontal 1-Vertical
+ */
+static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type)
+{
+ float rgba[4];
+ int i;
+ int pt;
+ bool t_a = false;
+ bool t_b = false;
+
+ /* Horizontal leak (check vertical pixels)
+ * X
+ * X
+ * xB7
+ * X
+ * X
+ */
+ if (type == LEAK_HORZ) {
+ /* pixels on top */
+ for (i = 1; i <= limit; i++) {
+ pt = index + (ibuf->x * i);
+ if (pt <= maxpixel) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_a = true;
+ break;
+ }
+ }
+ else {
+ t_a = true; /* edge of image*/
+ break;
+ }
+ }
+ /* pixels on bottom */
+ for (i = 1; i <= limit; i++) {
+ pt = index - (ibuf->x * i);
+ if (pt >= 0) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_b = true;
+ break;
+ }
+ }
+ else {
+ t_b = true; /* edge of image*/
+ break;
+ }
+ }
+ }
+
+ /* Vertical leak (check horizontal pixels)
+ *
+ * XXXxB7XX
+ *
+ */
+ if (type == LEAK_VERT) {
+ /* get pixel range of the row */
+ int row = index / ibuf->x;
+ int lowpix = row * ibuf->x;
+ int higpix = lowpix + ibuf->x - 1;
+
+ /* pixels to right */
+ for (i = 0; i < limit; i++) {
+ pt = index - (limit - i);
+ if (pt >= lowpix) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_a = true;
+ break;
+ }
+ }
+ else {
+ t_a = true; /* edge of image*/
+ break;
+ }
+ }
+ /* pixels to left */
+ for (i = 0; i < limit; i++) {
+ pt = index + (limit - i);
+ if (pt <= higpix) {
+ get_pixel(ibuf, pt, rgba);
+ if (rgba[0] == 1.0f) {
+ t_b = true;
+ break;
+ }
+ }
+ else {
+ t_b = true; /* edge of image */
+ break;
+ }
+ }
+ }
+ return (bool)(t_a && t_b);
+}
+
+/* Boundary fill inside strokes
+ * Fills the space created by a set of strokes using the stroke color as the boundary
+ * of the shape to fill.
+ *
+ * \param tgpf Temporary fill data
+ */
+static void gpencil_boundaryfill_area(tGPDfill *tgpf)
+{
+ ImBuf *ibuf;
+ float rgba[4];
+ void *lock;
+ const float fill_col[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ const int maxpixel = (ibuf->x * ibuf->y) - 1;
+
+ BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
+
+ /* calculate index of the seed point using the position of the mouse */
+ int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0];
+ if ((index >= 0) && (index < maxpixel)) {
+ BLI_stack_push(stack, &index);
+ }
+
+ /* the fill use a stack to save the pixel list instead of the common recursive
+ * 4-contact point method.
+ * The problem with recursive calls is that for big fill areas, we can get max limit
+ * of recursive calls and STACK_OVERFLOW error.
+ *
+ * The 4-contact point analyze the pixels to the left, right, bottom and top
+ * -----------
+ * | X |
+ * | XoX |
+ * | X |
+ * -----------
+ */
+ while (!BLI_stack_is_empty(stack)) {
+ int v;
+ BLI_stack_pop(stack, &v);
+
+ get_pixel(ibuf, v, rgba);
+
+ if (true) { /* Was: 'rgba' */
+ /* check if no border(red) or already filled color(green) */
+ if ((rgba[0] != 1.0f) && (rgba[1] != 1.0f)) {
+ /* fill current pixel */
+ set_pixel(ibuf, v, fill_col);
+
+ /* add contact pixels */
+ /* pixel left */
+ if (v - 1 >= 0) {
+ index = v - 1;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel right */
+ if (v + 1 < maxpixel) {
+ index = v + 1;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel top */
+ if (v + tgpf->sizex < maxpixel) {
+ index = v + tgpf->sizex;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ /* pixel bottom */
+ if (v - tgpf->sizex >= 0) {
+ index = v - tgpf->sizex;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
+ BLI_stack_push(stack, &index);
+ }
+ }
+ }
+ }
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+ /* free temp stack data */
+ BLI_stack_free(stack);
+}
+
+/* clean external border of image to avoid infinite loops */
+static void gpencil_clean_borders(tGPDfill *tgpf)
+{
+ ImBuf *ibuf;
+ void *lock;
+ const float fill_col[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ int idx;
+ int pixel = 0;
+
+ /* horizontal lines */
+ for (idx = 0; idx < ibuf->x - 1; idx++) {
+ /* bottom line */
+ set_pixel(ibuf, idx, fill_col);
+ /* top line */
+ pixel = idx + (ibuf->x * (ibuf->y - 1));
+ set_pixel(ibuf, pixel, fill_col);
+ }
+ /* vertical lines */
+ for (idx = 0; idx < ibuf->y; idx++) {
+ /* left line */
+ set_pixel(ibuf, ibuf->x * idx, fill_col);
+ /* right line */
+ pixel = ibuf->x * idx + (ibuf->x - 1);
+ set_pixel(ibuf, pixel, fill_col);
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+}
+
+/* Get the outline points of a shape using Moore Neighborhood algorithm
+ *
+ * This is a Blender customized version of the general algorithm described
+ * in https://en.wikipedia.org/wiki/Moore_neighborhood
+ */
+static void gpencil_get_outline_points(tGPDfill *tgpf)
+{
+ ImBuf *ibuf;
+ float rgba[4];
+ void *lock;
+ int v[2];
+ int boundary_co[2];
+ int start_co[2];
+ int backtracked_co[2];
+ int current_check_co[2];
+ int prev_check_co[2];
+ int backtracked_offset[1][2] = {{0, 0}};
+ // bool boundary_found = false;
+ bool start_found = false;
+ const int NEIGHBOR_COUNT = 8;
+
+ int offset[8][2] = {
+ { -1, -1 },
+ { 0, -1 },
+ { 1, -1 },
+ { 1, 0 },
+ { 1, 1 },
+ { 0, 1 },
+ { -1, 1 },
+ { -1, 0 }
+ };
+
+ tgpf->stack = BLI_stack_new(sizeof(int[2]), __func__);
+
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ int imagesize = ibuf->x * ibuf->y;
+
+ /* find the initial point to start outline analysis */
+ for (int idx = imagesize; idx >= 0; idx--) {
+ get_pixel(ibuf, idx, rgba);
+ if (rgba[1] == 1.0f) {
+ boundary_co[0] = idx % ibuf->x;
+ boundary_co[1] = idx / ibuf->x;
+ copy_v2_v2_int(start_co, boundary_co);
+ backtracked_co[0] = (idx - 1) % ibuf->x;
+ backtracked_co[1] = (idx - 1) / ibuf->x;
+ backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
+ backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
+ copy_v2_v2_int(prev_check_co, start_co);
+
+ BLI_stack_push(tgpf->stack, &boundary_co);
+ start_found = true;
+ break;
+ }
+ }
+
+ while (start_found) {
+ int cur_back_offset = -1;
+ for (int i = 0; i < NEIGHBOR_COUNT; i++) {
+ if (backtracked_offset[0][0] == offset[i][0] &&
+ backtracked_offset[0][1] == offset[i][1])
+ {
+ /* Finding the bracktracked pixel offset index */
+ cur_back_offset = i;
+ break;
+ }
+ }
+
+ int loop = 0;
+ while (loop < (NEIGHBOR_COUNT - 1) && cur_back_offset != -1) {
+ int offset_idx = (cur_back_offset + 1) % NEIGHBOR_COUNT;
+ current_check_co[0] = boundary_co[0] + offset[offset_idx][0];
+ current_check_co[1] = boundary_co[1] + offset[offset_idx][1];
+
+ int image_idx = ibuf->x * current_check_co[1] + current_check_co[0];
+ get_pixel(ibuf, image_idx, rgba);
+
+ /* find next boundary pixel */
+ if (rgba[1] == 1.0f) {
+ copy_v2_v2_int(boundary_co, current_check_co);
+ copy_v2_v2_int(backtracked_co, prev_check_co);
+ backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
+ backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
+
+ BLI_stack_push(tgpf->stack, &boundary_co);
+
+ break;
+ }
+ copy_v2_v2_int(prev_check_co, current_check_co);
+ cur_back_offset++;
+ loop++;
+ }
+ /* current pixel is equal to starting pixel */
+ if (boundary_co[0] == start_co[0] &&
+ boundary_co[1] == start_co[1])
+ {
+ BLI_stack_pop(tgpf->stack, &v);
+ // boundary_found = true;
+ break;
+ }
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+}
+
+/* get z-depth array to reproject on surface */
+static void gpencil_get_depth_array(tGPDfill *tgpf)
+{
+ tGPspoint *ptc;
+ ToolSettings *ts = tgpf->scene->toolsettings;
+ int totpoints = tgpf->sbuffer_size;
+ int i = 0;
+
+ if (totpoints == 0) {
+ return;
+ }
+
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) {
+ /* need to restore the original projection settings before packing up */
+ view3d_region_operator_needs_opengl(tgpf->win, tgpf->ar);
+ ED_view3d_autodist_init(tgpf->depsgraph, tgpf->ar, tgpf->v3d, 0);
+
+ /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+ int depth_margin = 0;
+
+ /* get an array of depths, far depths are blended */
+ int mval[2], mval_prev[2] = { 0 };
+ int interp_depth = 0;
+ int found_depth = 0;
+
+ tgpf->depth_arr = MEM_mallocN(sizeof(float) * totpoints, "depth_points");
+
+ for (i = 0, ptc = tgpf->sbuffer; i < totpoints; i++, ptc++) {
+ copy_v2_v2_int(mval, &ptc->x);
+
+ if ((ED_view3d_autodist_depth(
+ tgpf->ar, mval, depth_margin, tgpf->depth_arr + i) == 0) &&
+ (i && (ED_view3d_autodist_depth_seg(
+ tgpf->ar, mval, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0)))
+ {
+ interp_depth = true;
+ }
+ else {
+ found_depth = true;
+ }
+
+ copy_v2_v2_int(mval_prev, mval);
+ }
+
+ if (found_depth == false) {
+ /* eeh... not much we can do.. :/, ignore depth in this case */
+ for (i = totpoints - 1; i >= 0; i--)
+ tgpf->depth_arr[i] = 0.9999f;
+ }
+ else {
+ if (interp_depth) {
+ interp_sparse_array(tgpf->depth_arr, totpoints, FLT_MAX);
+ }
+ }
+ }
+}
+
+/* create array of points using stack as source */
+static void gpencil_points_from_stack(tGPDfill *tgpf)
+{
+ tGPspoint *point2D;
+ int totpoints = BLI_stack_count(tgpf->stack);
+ if (totpoints == 0) {
+ return;
+ }
+
+ tgpf->sbuffer_size = (short)totpoints;
+ tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__);
+
+ point2D = tgpf->sbuffer;
+ while (!BLI_stack_is_empty(tgpf->stack)) {
+ int v[2];
+ BLI_stack_pop(tgpf->stack, &v);
+ point2D->x = v[0];
+ point2D->y = v[1];
+
+ point2D->pressure = 1.0f;
+ point2D->strength = 1.0f;;
+ point2D->time = 0.0f;
+ point2D++;
+ }
+}
+
+/* create a grease pencil stroke using points in buffer */
+static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
+{
+ ToolSettings *ts = tgpf->scene->toolsettings;
+ int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
+
+ Brush *brush;
+ brush = BKE_brush_getactive_gpencil(ts);
+ if (brush == NULL) {
+ return;
+ }
+
+ bGPDspoint *pt;
+ MDeformVert *dvert;
+ tGPspoint *point2D;
+
+ if (tgpf->sbuffer_size == 0) {
+ return;
+ }
+
+ /* get frame or create a new one */
+ tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+
+ /* create new stroke */
+ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
+ gps->thickness = brush->size;
+ gps->inittime = 0.0f;
+
+ /* the polygon must be closed, so enabled cyclic */
+ gps->flag |= GP_STROKE_CYCLIC;
+ gps->flag |= GP_STROKE_3DSPACE;
+
+ gps->mat_nr = BKE_gpencil_get_material_index(tgpf->ob, tgpf->mat) - 1;
+
+ /* allocate memory for storage points */
+ gps->totpoints = tgpf->sbuffer_size;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_size, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * tgpf->sbuffer_size, "gp_stroke_weights");
+
+ /* initialize triangle memory to dummy data */
+ gps->tot_triangles = 0;
+ gps->triangles = NULL;
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* add stroke to frame */
+ if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) || (tgpf->on_back == true)) {
+ BLI_addhead(&tgpf->gpf->strokes, gps);
+ }
+ else {
+ BLI_addtail(&tgpf->gpf->strokes, gps);
+ }
+
+ /* add points */
+ pt = gps->points;
+ dvert = gps->dvert;
+ point2D = (tGPspoint *)tgpf->sbuffer;
+ for (int i = 0; i < tgpf->sbuffer_size && point2D; i++, point2D++, pt++, dvert++) {
+ /* convert screen-coordinates to 3D coordinates */
+ gp_stroke_convertcoords_tpoint(
+ tgpf->scene, tgpf->ar, tgpf->v3d, tgpf->ob,
+ tgpf->gpl, point2D,
+ tgpf->depth_arr ? tgpf->depth_arr + i : NULL,
+ &pt->x);
+
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;;
+ pt->time = 0.0f;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ }
+
+ /* smooth stroke */
+ float reduce = 0.0f;
+ float smoothfac = 1.0f;
+ for (int r = 0; r < 1; r++) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ BKE_gpencil_smooth_stroke(gps, i, smoothfac - reduce);
+ }
+ reduce += 0.25f; // reduce the factor
+ }
+
+ /* if axis locked, reproject to plane locked */
+ if ((tgpf->lock_axis > GP_LOCKAXIS_NONE) && ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) {
+ float origin[3];
+ ED_gp_get_drawing_reference(tgpf->v3d, tgpf->scene, tgpf->ob, tgpf->gpl,
+ ts->gpencil_v3d_align, origin);
+ ED_gp_project_stroke_to_plane(tgpf->ob, tgpf->rv3d, gps, origin,
+ tgpf->lock_axis - 1);
+ }
+
+ /* if parented change position relative to parent object */
+ for (int a = 0; a < tgpf->sbuffer_size; a++) {
+ pt = &gps->points[a];
+ gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
+ }
+
+ /* simplify stroke */
+ for (int b = 0; b < tgpf->fill_simplylvl; b++) {
+ BKE_gpencil_simplify_fixed(gps);
+ }
+}
+
+/* ----------------------- */
+/* Drawing */
+/* Helper: Draw status message while the user is running the operator */
+static void gpencil_fill_status_indicators(bContext *C, tGPDfill *UNUSED(tgpf))
+{
+ const char *status_str = IFACE_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back");
+ ED_workspace_status_text(C, status_str);
+}
+
+/* draw boundary lines to see fill limits */
+static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgpf)
+{
+ if (!tgpf->gpd) {
+ return;
+ }
+ float ink[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
+ gp_draw_datablock(tgpf, ink);
+}
+
+/* Drawing callback for modal operator in 3d mode */
+static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
+{
+ tGPDfill *tgpf = (tGPDfill *)arg;
+ /* draw only in the region that originated operator. This is required for multiwindow */
+ ARegion *ar = CTX_wm_region(C);
+ if (ar != tgpf->ar) {
+ return;
+ }
+
+ gpencil_draw_boundary_lines(C, tgpf);
+}
+
+/* check if context is suitable for filling */
+static bool gpencil_fill_poll(bContext *C)
+{
+ if (ED_operator_regionactive(C)) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_VIEW3D) {
+ return 1;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not valid for filling operator");
+ return 0;
+ }
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ return 0;
+ }
+}
+
+/* Allocate memory and initialize values */
+static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
+{
+ tGPDfill *tgpf = MEM_callocN(sizeof(tGPDfill), "GPencil Fill Data");
+
+ /* define initial values */
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Main *bmain = CTX_data_main(C);
+
+ /* set current scene and window info */
+ tgpf->bmain = CTX_data_main(C);
+ tgpf->scene = CTX_data_scene(C);
+ tgpf->ob = CTX_data_active_object(C);
+ tgpf->sa = CTX_wm_area(C);
+ tgpf->ar = CTX_wm_region(C);
+ tgpf->rv3d = tgpf->ar->regiondata;
+ tgpf->v3d = tgpf->sa->spacedata.first;
+ tgpf->depsgraph = CTX_data_depsgraph(C);
+ tgpf->win = CTX_wm_window(C);
+
+ /* set GP datablock */
+ tgpf->gpd = gpd;
+ tgpf->gpl = BKE_gpencil_layer_getactive(gpd);
+ if (tgpf->gpl == NULL) {
+ tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true);
+ }
+ tgpf->lock_axis = ts->gp_sculpt.lock_axis;
+
+ tgpf->oldkey = -1;
+ tgpf->sbuffer_size = 0;
+ tgpf->sbuffer = NULL;
+ tgpf->depth_arr = NULL;
+
+ /* save filling parameters */
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ tgpf->flag = brush->gpencil_settings->flag;
+ tgpf->fill_leak = brush->gpencil_settings->fill_leak;
+ tgpf->fill_threshold = brush->gpencil_settings->fill_threshold;
+ tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl;
+ tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode;
+
+ /* get color info */
+ Material *ma = BKE_gpencil_get_material_from_brush(brush);
+ /* if no brush defaults, get material and color info */
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ ma = BKE_gpencil_material_ensure(bmain, tgpf->ob);
+ /* assign always the first material to the brush */
+ brush->gpencil_settings->material = give_current_material(tgpf->ob, 1);
+ }
+
+ tgpf->mat = ma;
+
+ /* init undo */
+ gpencil_undo_init(tgpf->gpd);
+
+ /* return context data for running operator */
+ return tgpf;
+}
+
+/* end operator */
+static void gpencil_fill_exit(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* clear undo stack */
+ gpencil_undo_finish();
+
+ /* restore cursor to indicate end of fill */
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ tGPDfill *tgpf = op->customdata;
+
+ /* don't assume that operator data exists at all */
+ if (tgpf) {
+ /* clear status message area */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(tgpf->sbuffer);
+ MEM_SAFE_FREE(tgpf->depth_arr);
+
+ /* remove drawing handler */
+ if (tgpf->draw_handle_3d) {
+ ED_region_draw_cb_exit(tgpf->ar->type, tgpf->draw_handle_3d);
+ }
+
+ /* delete temp image */
+ if (tgpf->ima) {
+ for (Image *ima = bmain->image.first; ima; ima = ima->id.next) {
+ if (ima == tgpf->ima) {
+ BLI_remlink(&bmain->image, ima);
+ BKE_image_free(tgpf->ima);
+ MEM_SAFE_FREE(tgpf->ima);
+ break;
+ }
+ }
+ }
+
+ /* finally, free memory used by temp data */
+ MEM_freeN(tgpf);
+ }
+
+ /* clear pointer */
+ op->customdata = NULL;
+
+ /* drawing batch cache is dirty now */
+ if ((ob) && (ob->type == OB_GPENCIL) && (ob->data)) {
+ bGPdata *gpd2 = ob->data;
+ DEG_id_tag_update(&gpd2->id, OB_RECALC_OB | OB_RECALC_DATA);
+ gpd2->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+}
+
+static void gpencil_fill_cancel(bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ gpencil_fill_exit(C, op);
+}
+
+/* Init: Allocate memory and set init values */
+static int gpencil_fill_init(bContext *C, wmOperator *op)
+{
+ tGPDfill *tgpf;
+ /* cannot paint in locked layer */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
+ return 0;
+ }
+
+ /* check context */
+ tgpf = op->customdata = gp_session_init_fill(C, op);
+ if (tgpf == NULL) {
+ /* something wasn't set correctly in context */
+ gpencil_fill_exit(C, op);
+ return 0;
+ }
+
+ /* everything is now setup ok */
+ return 1;
+}
+
+/* start of interactive part of operator */
+static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ tGPDfill *tgpf = NULL;
+
+ /* try to initialize context data needed */
+ if (!gpencil_fill_init(C, op)) {
+ gpencil_fill_exit(C, op);
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ tgpf = op->customdata;
+ }
+
+ /* Enable custom drawing handlers to show help lines */
+ if (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) {
+ tgpf->draw_handle_3d = ED_region_draw_cb_activate(tgpf->ar->type, gpencil_fill_draw_3d, tgpf, REGION_DRAW_POST_VIEW);
+ }
+
+ WM_cursor_modal_set(CTX_wm_window(C), BC_PAINTBRUSHCURSOR);
+
+ gpencil_fill_status_indicators(C, tgpf);
+
+ DEG_id_tag_update(&tgpf->gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* add a modal handler for this operator*/
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* events handling during interactive part of operator */
+static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGPDfill *tgpf = op->customdata;
+
+ int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ estate = OPERATOR_CANCELLED;
+ break;
+ case LEFTMOUSE:
+ tgpf->on_back = RNA_boolean_get(op->ptr, "on_back");
+ /* first time the event is not enabled to show help lines */
+ if ((tgpf->oldkey != -1) || ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) == 0)) {
+ ARegion *ar = BKE_area_find_region_xy(CTX_wm_area(C), RGN_TYPE_ANY, event->x, event->y);
+ if (ar) {
+ bool in_bounds = false;
+
+ /* Perform bounds check */
+ in_bounds = BLI_rcti_isect_pt(&ar->winrct, event->x, event->y);
+
+ if ((in_bounds) && (ar->regiontype == RGN_TYPE_WINDOW)) {
+ /* TODO GPXX: Verify the mouse click is right for any window size */
+ tgpf->center[0] = event->mval[0];
+ tgpf->center[1] = event->mval[1];
+
+ /* save size */
+ tgpf->sizex = ar->winx;
+ tgpf->sizey = ar->winy;
+
+ /* render screen to temp image */
+ gp_render_offscreen(tgpf);
+
+ /* apply boundary fill */
+ gpencil_boundaryfill_area(tgpf);
+
+ /* clean borders to avoid infinite loops */
+ gpencil_clean_borders(tgpf);
+
+ /* analyze outline */
+ gpencil_get_outline_points(tgpf);
+
+ /* create array of points from stack */
+ gpencil_points_from_stack(tgpf);
+
+ /* create z-depth array for reproject */
+ gpencil_get_depth_array(tgpf);
+
+ /* create stroke and reproject */
+ gpencil_stroke_from_buffer(tgpf);
+
+ /* free temp stack data */
+ if (tgpf->stack) {
+ BLI_stack_free(tgpf->stack);
+ }
+
+ /* push undo data */
+ gpencil_undo_push(tgpf->gpd);
+
+ estate = OPERATOR_FINISHED;
+ }
+ else {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ tgpf->oldkey = event->type;
+ break;
+ }
+ /* process last operations before exiting */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ gpencil_fill_exit(C, op);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ break;
+
+ case OPERATOR_CANCELLED:
+ gpencil_fill_exit(C, op);
+ break;
+
+ case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
+ break;
+ }
+
+ /* return status code */
+ return estate;
+}
+
+void GPENCIL_OT_fill(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Grease Pencil Fill";
+ ot->idname = "GPENCIL_OT_fill";
+ ot->description = "Fill with color the shape formed by strokes";
+
+ /* api callbacks */
+ ot->invoke = gpencil_fill_invoke;
+ ot->modal = gpencil_fill_modal;
+ ot->poll = gpencil_fill_poll;
+ ot->cancel = gpencil_fill_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ prop = RNA_def_boolean(ot->srna, "on_back", false, "Draw On Back", "Send new stroke to Back");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 90ff1e0bb25..52e7d1e1f30 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -34,25 +34,145 @@
#include "DNA_vec_types.h"
+#include "ED_numinput.h"
+
/* internal exports only */
struct bGPdata;
struct bGPDstroke;
struct bGPDspoint;
+struct tGPspoint;
+struct Material;
struct GHash;
struct RNG;
+struct Brush;
+struct Scene;
struct ARegion;
+struct View3D;
struct View2D;
struct wmOperatorType;
+struct Depsgraph;
+
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
/* ***************************************************** */
+/* Modal Operator Geometry Preview
+ *
+ * Several modal operators (Fill, Interpolate, Primitive)
+ * need to run some drawing code to display previews, or
+ * to perform screen-space/image-based analysis routines.
+ * The following structs + function prototypes are used
+ * by these operators so that the operator code
+ * (in gpencil_<opname>.c) can communicate with the drawing
+ * code (in drawgpencil.c).
+ *
+ * NOTE: All this is within the gpencil module, so nothing needs
+ * to be exported to other modules.
+ */
+
+/* Internal Operator-State Data ------------------------ */
+
+/* Temporary draw data (no draw manager mode) */
+typedef struct tGPDdraw {
+ struct RegionView3D *rv3d; /* region to draw */
+ struct Depsgraph *depsgraph; /* depsgraph */
+ struct Object *ob; /* GP object */
+ struct bGPdata *gpd; /* current GP datablock */
+ struct bGPDlayer *gpl; /* layer */
+ struct bGPDframe *gpf; /* frame */
+ struct bGPDframe *t_gpf; /* temporal frame */
+ struct bGPDstroke *gps; /* stroke */
+ int disable_fill; /* disable fill */
+ int offsx; /* windows offset x */
+ int offsy; /* windows offset y */
+ int winx; /* windows width */
+ int winy; /* windows height */
+ int dflag; /* flags datablock */
+ short lthick; /* layer thickness */
+ float opacity; /* opacity */
+ float tintcolor[4]; /* tint color */
+ bool onion; /* onion flag */
+ bool custonion; /* use custom onion colors */
+ float diff_mat[4][4]; /* matrix */
+} tGPDdraw;
+
+
+/* Temporary interpolate operation data */
+typedef struct tGPDinterpolate_layer {
+ struct tGPDinterpolate_layer *next, *prev;
+
+ struct bGPDlayer *gpl; /* layer */
+ struct bGPDframe *prevFrame; /* frame before current frame (interpolate-from) */
+ struct bGPDframe *nextFrame; /* frame after current frame (interpolate-to) */
+ struct bGPDframe *interFrame; /* interpolated frame */
+ float factor; /* interpolate factor */
+
+} tGPDinterpolate_layer;
+
+typedef struct tGPDinterpolate {
+ struct Scene *scene; /* current scene from context */
+ struct ScrArea *sa; /* area where painting originated */
+ struct ARegion *ar; /* region where painting originated */
+ struct bGPdata *gpd; /* current GP datablock */
+ struct Material *mat; /* current material */
+
+ int cframe; /* current frame number */
+ ListBase ilayers; /* (tGPDinterpolate_layer) layers to be interpolated */
+ float shift; /* value for determining the displacement influence */
+ float init_factor; /* initial interpolation factor for active layer */
+ float low_limit; /* shift low limit (-100%) */
+ float high_limit; /* shift upper limit (200%) */
+ int flag; /* flag from toolsettings */
+
+ NumInput num; /* numeric input */
+ void *draw_handle_3d; /* handle for drawing strokes while operator is running 3d stuff */
+ void *draw_handle_screen; /* handle for drawing strokes while operator is running screen stuff */
+} tGPDinterpolate;
+
+
+/* Temporary primitive operation data */
+typedef struct tGPDprimitive {
+ struct Depsgraph *depsgraph;
+ struct wmWindow *win; /* window where painting originated */
+ struct Scene *scene; /* current scene from context */
+ struct Object *ob; /* current active gp object */
+ struct ScrArea *sa; /* area where painting originated */
+ struct RegionView3D *rv3d; /* region where painting originated */
+ struct View3D *v3d; /* view3d where painting originated */
+ struct ARegion *ar; /* region where painting originated */
+ struct bGPdata *gpd; /* current GP datablock */
+ struct Material *mat; /* current material */
+ struct Brush *brush; /* current brush */
+
+ int cframe; /* current frame number */
+ struct bGPDlayer *gpl; /* layer */
+ struct bGPDframe *gpf; /* frame */
+ int type; /* type of primitive */
+ int tot_edges; /* number of polygon edges */
+ int top[2]; /* first box corner */
+ int bottom[2]; /* last box corner */
+ int flag; /* flag to determine operations in progress */
+
+ int lock_axis; /* lock to viewport axis */
+
+ NumInput num; /* numeric input */
+ void *draw_handle_3d; /* handle for drawing strokes while operator is running 3d stuff */
+} tGPDprimitive;
+
+
+/* Modal Operator Drawing Callbacks ------------------------ */
+
+void ED_gp_draw_interpolation(const struct bContext *C, struct tGPDinterpolate *tgpi, const int type);
+void ED_gp_draw_primitives(const struct bContext *C, struct tGPDprimitive *tgpi, const int type);
+void ED_gp_draw_fill(struct tGPDdraw *tgpw);
+
+/* ***************************************************** */
/* Internal API */
/* Stroke Coordinates API ------------------------------ */
@@ -84,21 +204,30 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
float *r_x, float *r_y);
void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt);
-
-void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps);
-
-void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt);
+/**
+ * Change points position relative to parent object
+ */
+void gp_apply_parent(struct Depsgraph *depsgraph, struct Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps);
+/**
+ * Change point position relative to parent object
+ */
+void gp_apply_parent_point(struct Depsgraph *depsgraph, struct Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt);
bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, struct Scene *scene, const float screen_co[2], float r_out[3]);
+/* helper to convert 2d to 3d */
+void gp_stroke_convertcoords_tpoint(
+ struct Scene *scene, struct ARegion *ar,
+ struct View3D *v3d, struct Object *ob,
+ bGPDlayer *gpl, const struct tGPspoint *point2D,
+ float *depth, float out[3]);
+
/* Poll Callbacks ------------------------------------ */
/* gpencil_utils.c */
bool gp_add_poll(struct bContext *C);
bool gp_active_layer_poll(struct bContext *C);
bool gp_active_brush_poll(struct bContext *C);
-bool gp_active_palette_poll(struct bContext *C);
-bool gp_active_palettecolor_poll(struct bContext *C);
bool gp_brush_crt_presets_poll(bContext *C);
/* Copy/Paste Buffer --------------------------------- */
@@ -107,18 +236,20 @@ bool gp_brush_crt_presets_poll(bContext *C);
extern ListBase gp_strokes_copypastebuf;
/* Build a map for converting between old colornames and destination-color-refs */
-struct GHash *gp_copybuf_validate_colormap(bGPdata *gpd);
+struct GHash *gp_copybuf_validate_colormap(struct bContext *C);
/* Stroke Editing ------------------------------------ */
-void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags);
-
+void gp_stroke_delete_tagged_points(
+ bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke,
+ int tag_flags, bool select);
+int gp_delete_selected_point_wrap(bContext *C);
bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure);
bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf);
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf);
-void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints);
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, struct RNG *rng);
+void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide);
+void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, struct RNG *rng);
/* Layers Enums -------------------------------------- */
@@ -129,22 +260,18 @@ const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
bool *r_free);
-/* Enums of GP Brushes */
-const EnumPropertyItem *ED_gpencil_brushes_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free);
-
-/* Enums of GP palettes */
-const EnumPropertyItem *ED_gpencil_palettes_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free);
-
/* ***************************************************** */
/* Operator Defines */
+/* annotations ------ */
+
+void GPENCIL_OT_annotate(struct wmOperatorType *ot);
+
+
/* drawing ---------- */
void GPENCIL_OT_draw(struct wmOperatorType *ot);
+void GPENCIL_OT_fill(struct wmOperatorType *ot);
/* Paint Modes for operator */
typedef enum eGPencil_PaintModes {
@@ -160,6 +287,9 @@ typedef enum eGPencil_PaintModes {
/* stroke editing ----- */
void GPENCIL_OT_editmode_toggle(struct wmOperatorType *ot);
+void GPENCIL_OT_paintmode_toggle(struct wmOperatorType *ot);
+void GPENCIL_OT_sculptmode_toggle(struct wmOperatorType *ot);
+void GPENCIL_OT_weightmode_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_selection_opacity_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_select(struct wmOperatorType *ot);
@@ -174,6 +304,7 @@ void GPENCIL_OT_select_more(struct wmOperatorType *ot);
void GPENCIL_OT_select_less(struct wmOperatorType *ot);
void GPENCIL_OT_select_first(struct wmOperatorType *ot);
void GPENCIL_OT_select_last(struct wmOperatorType *ot);
+void GPENCIL_OT_select_alternate(struct wmOperatorType *ot);
void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
void GPENCIL_OT_delete(struct wmOperatorType *ot);
@@ -218,6 +349,8 @@ void GPENCIL_OT_blank_frame_add(struct wmOperatorType *ot);
void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
void GPENCIL_OT_active_frames_delete_all(struct wmOperatorType *ot);
+void GPENCIL_OT_frame_duplicate(struct wmOperatorType *ot);
+void GPENCIL_OT_frame_clean_fill(struct wmOperatorType *ot);
void GPENCIL_OT_convert(struct wmOperatorType *ot);
@@ -226,6 +359,13 @@ enum {
GP_STROKE_JOINCOPY = 1
};
+enum {
+ GP_STROKE_BOX = -1,
+ GP_STROKE_LINE = 1,
+ GP_STROKE_CIRCLE = 2
+};
+
+
void GPENCIL_OT_stroke_arrange(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_change_color(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_lock_color(struct wmOperatorType *ot);
@@ -234,30 +374,15 @@ void GPENCIL_OT_stroke_cyclical_set(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_join(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_flip(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_subdivide(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_simplify(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_simplify_fixed(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_separate(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_split(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_add(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_remove(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_change(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_move(struct wmOperatorType *ot);
void GPENCIL_OT_brush_presets_create(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_copy(struct wmOperatorType *ot);
void GPENCIL_OT_brush_select(struct wmOperatorType *ot);
-void GPENCIL_OT_palette_add(struct wmOperatorType *ot);
-void GPENCIL_OT_palette_remove(struct wmOperatorType *ot);
-void GPENCIL_OT_palette_change(struct wmOperatorType *ot);
-void GPENCIL_OT_palette_lock_layer(struct wmOperatorType *ot);
-
-void GPENCIL_OT_palettecolor_add(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_remove(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_isolate(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_hide(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_reveal(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_lock_all(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_unlock_all(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_move(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_select(struct wmOperatorType *ot);
-void GPENCIL_OT_palettecolor_copy(struct wmOperatorType *ot);
+void GPENCIL_OT_sculpt_select(struct wmOperatorType *ot);
/* undo stack ---------- */
@@ -271,6 +396,30 @@ void GPENCIL_OT_interpolate(struct wmOperatorType *ot);
void GPENCIL_OT_interpolate_sequence(struct wmOperatorType *ot);
void GPENCIL_OT_interpolate_reverse(struct wmOperatorType *ot);
+/* primitives ---------- */
+
+void GPENCIL_OT_primitive(struct wmOperatorType *ot);
+
+/* vertex groups ------------ */
+void GPENCIL_OT_vertex_group_assign(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_group_remove_from(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_group_select(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_group_deselect(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_group_invert(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_group_smooth(struct wmOperatorType *ot);
+
+/* color handle */
+void GPENCIL_OT_lock_layer(struct wmOperatorType *ot);
+void GPENCIL_OT_color_isolate(struct wmOperatorType *ot);
+void GPENCIL_OT_color_hide(struct wmOperatorType *ot);
+void GPENCIL_OT_color_reveal(struct wmOperatorType *ot);
+void GPENCIL_OT_color_lock_all(struct wmOperatorType *ot);
+void GPENCIL_OT_color_unlock_all(struct wmOperatorType *ot);
+void GPENCIL_OT_color_select(struct wmOperatorType *ot);
+
+/* convert old 2.7 files to 2.8 */
+void GPENCIL_OT_convert_old_files(struct wmOperatorType *ot);
+
/* ****************************************************** */
/* FILTERED ACTION DATA - TYPES ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */
@@ -331,24 +480,37 @@ typedef enum ACTCONT_TYPES {
*/
#define GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) \
{ \
+ Depsgraph *depsgraph_ = CTX_data_depsgraph(C); \
+ Object *obact_ = CTX_data_active_object(C); \
+ bGPdata *gpd_ = CTX_data_gpencil_data(C); \
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
CTX_DATA_BEGIN(C, bGPDlayer*, gpl, editable_gpencil_layers) \
{ \
- if (gpl->actframe == NULL) \
- continue; \
- /* calculate difference matrix if parent object */ \
- float diff_mat[4][4]; \
- ED_gpencil_parent_location(gpl, diff_mat); \
- /* loop over strokes */ \
- for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) { \
- /* 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; \
- /* ... Do Stuff With Strokes ... */
+ bGPDframe *init_gpf = gpl->actframe; \
+ if (is_multiedit) { \
+ init_gpf = gpl->frames.first; \
+ } \
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { \
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { \
+ /* calculate difference matrix */ \
+ float diff_mat[4][4]; \
+ ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, diff_mat); \
+ /* loop over strokes */ \
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { \
+ /* 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(obact_, gpl, gps) == false) \
+ continue; \
+ /* ... Do Stuff With Strokes ... */
#define GP_EDITABLE_STROKES_END \
+ } \
+ } \
+ if (!is_multiedit) { \
+ break; \
+ } \
} \
} \
CTX_DATA_END; \
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index cc30d7ec266..6541e9f012a 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -47,6 +47,7 @@
#include "DNA_color_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -60,6 +61,7 @@
#include "BKE_library.h"
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "BKE_deform.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -79,6 +81,9 @@
#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* ************************************************ */
@@ -108,11 +113,13 @@ static bool gpencil_view3d_poll(bContext *C)
static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
{
bGPDspoint *prev, *pt, *next;
+ MDeformVert *dvert;
/* update points */
for (int i = 0; i < new_stroke->totpoints; i++) {
prev = &gps_from->points[i];
pt = &new_stroke->points[i];
+ dvert = &new_stroke->dvert[i];
next = &gps_to->points[i];
/* Interpolate all values */
@@ -120,6 +127,9 @@ static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_t
pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor);
pt->strength = interpf(prev->strength, next->strength, 1.0f - factor);
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
}
}
@@ -128,6 +138,7 @@ static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_t
/* Helper: Update all strokes interpolated */
static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
{
+ bGPdata *gpd = tgpi->gpd;
tGPDinterpolate_layer *tgpil;
const float shift = tgpi->shift;
@@ -156,12 +167,14 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
}
}
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
/* Helper: Verify valid strokes for interpolation */
static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
{
+ Object *ob = CTX_data_active_object(C);
ToolSettings *ts = CTX_data_tool_settings(C);
eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
@@ -190,7 +203,7 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
continue;
}
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
continue;
}
@@ -213,6 +226,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
bGPdata *gpd = tgpi->gpd;
bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
bGPDframe *actframe = active_gpl->actframe;
+ Object *ob = CTX_data_active_object(C);
/* save initial factor for active layer to define shift limits */
tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) / (actframe->next->framenum - actframe->framenum + 1);
@@ -255,7 +269,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
bGPDstroke *gps_to;
int fFrame;
- bGPDstroke *new_stroke;
+ bGPDstroke *new_stroke = NULL;
bool valid = true;
@@ -269,7 +283,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(tgpil->gpl, gps_from) == false) {
+ if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) {
valid = false;
}
@@ -281,16 +295,13 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* create new stroke */
- new_stroke = MEM_dupallocN(gps_from);
- new_stroke->points = MEM_dupallocN(gps_from->points);
- new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
+ new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert) * gps_to->totpoints);
new_stroke->totpoints = gps_to->totpoints;
new_stroke->tot_triangles = 0;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
@@ -302,6 +313,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
/* need an empty stroke to keep index correct for lookup, but resize to smallest size */
new_stroke->totpoints = 0;
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
+ new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert));
new_stroke->tot_triangles = 0;
new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
@@ -317,17 +329,17 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
/* Drawing Callbacks */
/* Drawing callback for modal operator in screen mode */
-static void gpencil_interpolate_draw_screen(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void gpencil_interpolate_draw_screen(const struct bContext *C, ARegion *UNUSED(ar), void *arg)
{
tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_PIXEL);
+ ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_PIXEL);
}
/* Drawing callback for modal operator in 3d mode */
-static void gpencil_interpolate_draw_3d(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
{
tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_VIEW);
+ ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW);
}
/* ----------------------- */
@@ -392,6 +404,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
{
tGPDinterpolate *tgpi = op->customdata;
tGPDinterpolate_layer *tgpil;
+ bGPdata *gpd = tgpi->gpd;
/* don't assume that operator data exists at all */
if (tgpi) {
@@ -416,6 +429,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
BLI_freelistN(&tgpi->ilayers);
MEM_freeN(tgpi);
}
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
/* clear pointer */
@@ -483,9 +497,10 @@ static int gpencil_interpolate_init(bContext *C, wmOperator *op)
static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
bGPDframe *actframe = gpl->actframe;
tGPDinterpolate *tgpi = NULL;
@@ -496,7 +511,7 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
}
/* cannot interpolate in extremes */
- if (ELEM(CFRA, actframe->framenum, actframe->next->framenum)) {
+ if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
return OPERATOR_CANCELLED;
}
@@ -529,6 +544,7 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
/* update shift indicator in header */
gpencil_interpolate_status_indicators(C, tgpi);
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
/* add a modal handler for this operator */
@@ -571,6 +587,8 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
/* make copy of source stroke, then adjust pointer to points too */
gps_dst = MEM_dupallocN(gps_src);
gps_dst->points = MEM_dupallocN(gps_src->points);
+ gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
gps_dst->flag |= GP_STROKE_RECALC_CACHES;
BLI_addtail(&gpf_dst->strokes, gps_dst);
@@ -902,8 +920,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
bGPDframe *actframe = active_gpl->actframe;
- Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
eGP_Interpolate_SettingsFlag flag = ipo_settings->flag;
@@ -913,7 +934,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* cannot interpolate in extremes */
- if (ELEM(CFRA, actframe->framenum, actframe->next->framenum)) {
+ if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
return OPERATOR_CANCELLED;
}
@@ -961,7 +982,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
/* create new strokes data with interpolated points reading original stroke */
for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
- bGPDstroke *new_stroke;
+ bGPDstroke *new_stroke = NULL;
/* only selected */
if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
@@ -972,7 +993,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
continue;
}
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
continue;
}
@@ -990,15 +1011,15 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* create new stroke */
- new_stroke = MEM_dupallocN(gps_from);
- new_stroke->points = MEM_dupallocN(gps_from->points);
- new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
+ /* free weights of removed points */
+ BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints, gps_from->totpoints - gps_to->totpoints);
+
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
+ new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert) * gps_to->totpoints);
new_stroke->totpoints = gps_to->totpoints;
new_stroke->tot_triangles = 0;
new_stroke->flag |= GP_STROKE_RECALC_CACHES;
@@ -1014,6 +1035,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -1055,6 +1077,8 @@ static bool gpencil_interpolate_reverse_poll(bContext *C)
static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
/* Go through each layer, deleting the breakdowns around the current frame,
* but only if there is a keyframe nearby to stop at
*/
@@ -1123,6 +1147,7 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* notifiers */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/gpencil_old.c b/source/blender/editors/gpencil/gpencil_old.c
new file mode 100644
index 00000000000..76d519fe371
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_old.c
@@ -0,0 +1,219 @@
+/*
+ * ***** 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) 2018, Blender Foundation,
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Use deprecated data to convert old 2.7x files
+ */
+
+/** \file blender/editors/gpencil/gpencil_old.c
+ * \ingroup edgpencil
+ */
+
+ /* allow to use deprecated functionality */
+#define DNA_DEPRECATED_ALLOW
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_main.h"
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_object.h"
+#include "BKE_material.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_gpencil.h"
+
+#include "gpencil_intern.h"
+
+ /* Free all of a gp-colors */
+static void free_gpencil_colors(bGPDpalette *palette)
+{
+ /* error checking */
+ if (palette == NULL) {
+ return;
+ }
+
+ /* free colors */
+ BLI_freelistN(&palette->colors);
+}
+
+/* Free all of the gp-palettes and colors */
+static void free_palettes(ListBase *list)
+{
+ bGPDpalette *palette_next;
+
+ /* error checking */
+ if (list == NULL) {
+ return;
+ }
+
+ /* delete palettes */
+ for (bGPDpalette *palette = list->first; palette; palette = palette_next) {
+ palette_next = palette->next;
+ /* free palette colors */
+ free_gpencil_colors(palette);
+
+ MEM_freeN(palette);
+ }
+ BLI_listbase_clear(list);
+}
+
+/* ***************** Convert old 2.7 files to 2.8 ************************ */
+static bool gpencil_convert_old_files_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ return (int) (scene->gpd != NULL);
+}
+
+static int gpencil_convert_old_files_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Convert grease pencil scene datablock to GP object */
+ if ((scene->gpd) && (view_layer != NULL)) {
+ Object *ob;
+ ob = BKE_object_add_for_data(bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false);
+ zero_v3(ob->loc);
+
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ }
+
+ /* convert grease pencil palettes (version >= 2.78) to materials and weights */
+ bGPdata *gpd = scene->gpd;
+ for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
+ for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
+
+ /* create material slot */
+ BKE_object_material_slot_add(bmain, ob);
+ Material *ma = BKE_material_add_gpencil(bmain, palcolor->info);
+ assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+
+ /* copy color settings */
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ copy_v4_v4(gp_style->stroke_rgba, palcolor->color);
+ copy_v4_v4(gp_style->fill_rgba, palcolor->fill);
+ gp_style->flag = palcolor->flag;
+
+ /* fix strokes */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if ((gps->colorname[0] != '\0') &&
+ (STREQ(gps->colorname, palcolor->info)))
+ {
+ gps->mat_nr = ob->totcol - 1;
+ gps->colorname[0] = '\0';
+ /* create weights array */
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* free palettes */
+ free_palettes(&gpd->palettes);
+
+ /* disable all GP modes */
+ ED_gpencil_setup_modes(C, gpd, 0);
+
+ /* set cache as dirty */
+ BKE_gpencil_batch_cache_dirty(ob->data);
+
+ scene->gpd = NULL;
+ }
+
+#if 0 /* GPXX */
+ /* Handle object-linked grease pencil datablocks */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->gpd) {
+ if (ob->type == OB_GPENCIL) {
+ /* GP Object - remap the links */
+ ob->data = ob->gpd;
+ ob->gpd = NULL;
+ }
+ else if (ob->type == OB_EMPTY) {
+ /* Empty with GP data - This should be able to be converted
+ * to a GP object with little data loss
+ */
+ ob->data = ob->gpd;
+ ob->gpd = NULL;
+ ob->type = OB_GPENCIL;
+ }
+ else {
+ /* FIXME: What to do in this case?
+ *
+ * We cannot create new objects for these, as we don't have a scene & scene layer
+ * to put them into from here...
+ */
+ printf("WARNING: Old Grease Pencil data ('%s') still exists on Object '%s'\n",
+ ob->gpd->id.name + 2, ob->id.name + 2);
+ }
+ }
+ }
+#endif
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_convert_old_files(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Convert 2.7 Grease Pencil File";
+ ot->idname = "GPENCIL_OT_convert_old_files";
+ ot->description = "Convert 2.7x grease pencil files to 2.8";
+
+ /* callbacks */
+ ot->exec = gpencil_convert_old_files_exec;
+ ot->poll = gpencil_convert_old_files_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 3f114a4dd4a..b2e1758b169 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -35,8 +35,14 @@
#include "BLI_sys_types.h"
#include "BKE_context.h"
+#include "BKE_brush.h"
+#include "BKE_gpencil.h"
+#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,7 +58,7 @@
/* ****************************************** */
/* Grease Pencil Keymaps */
-/* Generic Drawing Keymap */
+/* Generic Drawing Keymap - Annotations */
static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0);
@@ -60,36 +66,22 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
/* Draw --------------------------------------- */
/* draw */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_annotate", LEFTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
/* draw - straight lines */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_annotate", LEFTMOUSE, KM_PRESS, KM_ALT, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
/* draw - poly lines */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_annotate", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
/* erase */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
- RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
- RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-
- /* Tablet Mappings for Drawing ------------------ */
- /* For now, only support direct drawing using the eraser, as most users using a tablet
- * may still want to use that as their primary pointing device!
- */
-#if 0
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_STYLUS, KM_PRESS, 0, 0);
- RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
- RNA_boolean_set(kmi->ptr, "wait_for_input", false);
-#endif
-
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_annotate", RIGHTMOUSE, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
RNA_boolean_set(kmi->ptr, "wait_for_input", false);
@@ -121,67 +113,85 @@ static bool gp_stroke_editmode_poll(bContext *C)
return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
}
-/* Stroke Editing Keymap - Only when editmode is enabled */
-static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
+/* Poll callback for stroke painting mode */
+static bool gp_stroke_paintmode_poll(bContext *C)
{
- wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
- wmKeyMapItem *kmi;
-
- /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
- keymap->poll = gp_stroke_editmode_poll;
-
- /* ----------------------------------------------- */
-
- /* Exit EditMode */
- WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
-
- /* Pie Menu - For settings/tools easy access */
- WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_sculpt", EKEY, KM_PRESS, 0, DKEY);
-
- /* Brush Settings */
- /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
- * in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
- * that the only data being edited is that of the Grease Pencil strokes
- */
-
- /* CTRL + FKEY = Eraser Radius */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
-
- /* Interpolation */
- WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate", EKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate_sequence", EKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE));
+}
- /* Sculpting ------------------------------------- */
+/* Poll callback for stroke painting (draw brush) */
+static bool gp_stroke_paintmode_draw_poll(bContext *C)
+{
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush) &&
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW));
+}
- /* Brush-Based Editing:
- * EKEY + LMB = Single stroke, draw immediately
- * + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc.
- *
- * For the modal version, use D+E -> Sculpt
- */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, EKEY);
- RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+/* Poll callback for stroke painting (erase brush) */
+static bool gp_stroke_paintmode_erase_poll(bContext *C)
+{
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush) &&
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE));
+}
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, EKEY);
- RNA_boolean_set(kmi->ptr, "wait_for_input", false);
- /*RNA_boolean_set(kmi->ptr, "use_invert", true);*/
+/* Poll callback for stroke painting (fill) */
+static bool gp_stroke_paintmode_fill_poll(bContext *C)
+{
+ /* TODO: limit this to mode, but review 2D editors */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+ return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush) &&
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_FILL));
+}
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, EKEY);
- RNA_boolean_set(kmi->ptr, "wait_for_input", false);
- /*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/
+/* Poll callback for stroke sculpting mode */
+static bool gp_stroke_sculptmode_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = CTX_data_active_object(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ /* if not gpencil object and not view3d, need sculpt keys if edit mode */
+ if (sa->spacetype != SPACE_VIEW3D) {
+ return ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+ }
+ else {
+ /* weight paint is a submode of sculpt */
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd);
+ }
+ }
+
+ return 0;
+}
+/* Poll callback for stroke weight paint mode */
+static bool gp_stroke_weightmode_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = CTX_data_active_object(C);
- /* Shift-FKEY = Sculpt Strength */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.strength");
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return (gpd && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE));
+ }
- /* FKEY = Sculpt Brush Size */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.size");
+ return 0;
+}
+static void ed_keymap_gpencil_selection(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
- /* Selection ------------------------------------- */
/* select all */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0);
RNA_enum_set(kmi->ptr, "action", SEL_SELECT);
@@ -204,17 +214,14 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", true);
/* In the Node Editor, lasso select needs ALT modifier too (as somehow CTRL+LMB drag gets taken for "cut" quite early)
- * There probably isn't too much harm adding this for other editors too as part of standard GP editing keymap. This hotkey
- * combo doesn't seem to see much use under standard scenarios?
- */
+ * There probably isn't too much harm adding this for other editors too as part of standard GP editing keymap. This hotkey
+ * combo doesn't seem to see much use under standard scenarios?
+ */
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
- /* normal select */
- WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
-
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "toggle", true);
@@ -223,17 +230,130 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "entire_strokes", true);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "entire_strokes", true);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+
/* select linked */
/* NOTE: While LKEY is redundant, not having it breaks the mode illusion too much */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+ /* select alternate */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_alternate", LKEY, KM_PRESS, KM_SHIFT, 0);
+
/* select grouped */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
/* select more/less */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+}
+
+static void ed_keymap_gpencil_display(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.overlay.use_gpencil_edit_lines");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.overlay.use_gpencil_multiedit_line_only");
+}
+
+static void ed_keymap_gpencil_sculpt(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+ /* Pie Menu - For settings/tools easy access */
+ WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_sculpt", EKEY, KM_PRESS, 0, DKEY);
+
+ /* Sculpting ------------------------------------- */
+
+ /* Brush-Based Editing:
+ * EKEY + LMB = Single stroke, draw immediately
+ * + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc.
+ *
+ * For the modal version, use D+E -> Sculpt
+ */
+ /* GPXX: disabled to make toolsystem works */
+ //kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+ //RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ RNA_boolean_set(kmi->ptr, "keep_brush", true);
+ /*RNA_boolean_set(kmi->ptr, "use_invert", true);*/
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ RNA_boolean_set(kmi->ptr, "keep_brush", true);
+ /*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/
+
+ /* Shift-FKEY = Sculpt Strength */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.strength");
+
+ /* FKEY = Sculpt Brush Size */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.size");
+
+ /* menu sculpt specials */
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_gpencil_sculpt_specials", WKEY, KM_PRESS, 0, 0);
+}
+
+static void ed_keymap_gpencil_weight(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+
+ /* Brush-Based Editing:
+ * EKEY + LMB = Single stroke, draw immediately
+ * + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc.
+ *
+ * For the modal version, use D+E -> Sculpt
+ */
+ /* GPXX: disabled to make toolsystem works */
+ //kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+ //RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ RNA_boolean_set(kmi->ptr, "keep_brush", true);
+ /*RNA_boolean_set(kmi->ptr, "use_invert", true);*/
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ RNA_boolean_set(kmi->ptr, "keep_brush", true);
+ /*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/
+}
+
+/* Stroke Editing Keymap - Only when editmode is enabled */
+static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
+ keymap->poll = gp_stroke_editmode_poll;
+
+ /* ----------------------------------------------- */
+
+ /* Brush Settings */
+ /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
+ * in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
+ * that the only data being edited is that of the Grease Pencil strokes
+ */
+
+ /* Interpolation */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate", EKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate_sequence", EKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+
+ /* normal select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+
+ /* Selection */
+ ed_keymap_gpencil_selection(keymap);
/* Editing ----------------------------------------- */
@@ -251,7 +371,13 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", DELKEY, KM_PRESS, KM_SHIFT, 0);
/* menu edit specials */
- WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_edit_specials", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_gpencil_edit_specials", WKEY, KM_PRESS, 0, 0);
+
+ /* menu separate */
+ WM_keymap_add_menu(keymap, "GPENCIL_MT_separate", PKEY, KM_PRESS, 0, 0);
+
+ /* split strokes */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_split", VKEY, KM_PRESS, 0, 0);
/* join strokes */
WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL, 0);
@@ -271,7 +397,6 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
/* snap */
WM_keymap_add_menu(keymap, "GPENCIL_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
-
/* convert to geometry */
WM_keymap_add_item(keymap, "GPENCIL_OT_convert", CKEY, KM_PRESS, KM_ALT, 0);
@@ -288,6 +413,9 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "GPENCIL_OT_selection_opacity_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
+ /* Display. */
+ ed_keymap_gpencil_display(keymap);
+
/* Isolate Layer */
WM_keymap_add_item(keymap, "GPENCIL_OT_layer_isolate", PADASTERKEY, KM_PRESS, 0, 0);
@@ -317,27 +445,233 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
/* Proportional Editing */
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_editmode(keyconf, keymap, true);
+
+ /* menu - add GP object (3d view only) */
+ WM_keymap_add_item(keymap, "OBJECT_OT_gpencil_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* menu vertex group */
+ WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_vertex_group", GKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* toggle edit mode */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
+}
+
+/* keys for draw with a drawing brush (no fill) */
+static void ed_keymap_gpencil_painting_draw(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback */
+ keymap->poll = gp_stroke_paintmode_draw_poll;
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* draw - straight lines */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* draw - poly lines */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* erase */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* Tablet Mappings for Drawing ------------------ */
+ /* For now, only support direct drawing using the eraser, as most users using a tablet
+ * may still want to use that as their primary pointing device!
+ */
+#if 0
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_STYLUS, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+#endif
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* Selection (used by eraser) */
+ /* border select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* lasso select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+}
+
+/* keys for draw with a eraser brush (erase) */
+static void ed_keymap_gpencil_painting_erase(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback */
+ keymap->poll = gp_stroke_paintmode_erase_poll;
+
+ /* erase */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+
+ /* Selection (used by eraser) */
+ /* border select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* lasso select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+}
+
+/* keys for draw with a fill brush */
+static void ed_keymap_gpencil_painting_fill(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback */
+ keymap->poll = gp_stroke_paintmode_fill_poll;
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_fill", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "on_back", false);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_fill", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "on_back", true);
+
+ /* if press alternative key, the brush now it's for drawing areas */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ /* disable straight lines */
+ RNA_boolean_set(kmi->ptr, "disable_straight", true);
+
+ /* if press alternative key, the brush now it's for drawing lines */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_ALT, 0);
+ RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
+ RNA_boolean_set(kmi->ptr, "wait_for_input", false);
+ /* disable straight lines */
+ RNA_boolean_set(kmi->ptr, "disable_straight", true);
+ /* enable special stroke with no fill flag */
+ RNA_boolean_set(kmi->ptr, "disable_fill", true);
+}
+
+/* Stroke Painting Keymap - Only when paintmode is enabled */
+static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Paint Mode", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback - so that this keymap only gets enabled when stroke paintmode is enabled */
+ keymap->poll = gp_stroke_paintmode_poll;
+
+ /* FKEY = Brush Size */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_paint.brush.size");
+
+ /* CTRL + FKEY = Eraser Radius */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
+
+ /* menu draw specials */
+ WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_draw_specials", WKEY, KM_PRESS, 0, 0);
+
+ /* menu draw delete */
+ WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_draw_delete", XKEY, KM_PRESS, 0, 0);
+
}
+/* Stroke Sculpting Keymap - Only when sculptmode is enabled */
+static void ed_keymap_gpencil_sculpting(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
+
+ /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
+ keymap->poll = gp_stroke_sculptmode_poll;
+
+ /* Selection */
+ ed_keymap_gpencil_selection(keymap);
+
+ /* sculpt */
+ ed_keymap_gpencil_sculpt(keymap);
+
+ /* Display. */
+ ed_keymap_gpencil_display(keymap);
+}
+
+/* Stroke Weight Paint Keymap - Only when weight is enabled */
+static void ed_keymap_gpencil_weightpainting(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0);
+ wmKeyMapItem *kmi;
+
+ /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
+ keymap->poll = gp_stroke_weightmode_poll;
+
+ /* Selection */
+ ed_keymap_gpencil_selection(keymap);
+
+ /* sculpt */
+ ed_keymap_gpencil_weight(keymap);
+
+ /* Shift-FKEY = Sculpt Strength */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.weight_brush.strength");
+
+ /* FKEY = Sculpt Brush Size */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.weight_brush.size");
+
+ /* Display. */
+ ed_keymap_gpencil_display(keymap);
+}
/* ==================== */
void ED_keymap_gpencil(wmKeyConfig *keyconf)
{
ed_keymap_gpencil_general(keyconf);
ed_keymap_gpencil_editing(keyconf);
+ ed_keymap_gpencil_painting(keyconf);
+ ed_keymap_gpencil_painting_draw(keyconf);
+ ed_keymap_gpencil_painting_erase(keyconf);
+ ed_keymap_gpencil_painting_fill(keyconf);
+ ed_keymap_gpencil_sculpting(keyconf);
+ ed_keymap_gpencil_weightpainting(keyconf);
}
/* ****************************************** */
void ED_operatortypes_gpencil(void)
{
+ /* Annotations -------------------- */
+
+ WM_operatortype_append(GPENCIL_OT_annotate);
+
/* Drawing ----------------------- */
WM_operatortype_append(GPENCIL_OT_draw);
+ WM_operatortype_append(GPENCIL_OT_fill);
/* Editing (Strokes) ------------ */
WM_operatortype_append(GPENCIL_OT_editmode_toggle);
+ WM_operatortype_append(GPENCIL_OT_paintmode_toggle);
+ WM_operatortype_append(GPENCIL_OT_sculptmode_toggle);
+ WM_operatortype_append(GPENCIL_OT_weightmode_toggle);
WM_operatortype_append(GPENCIL_OT_selection_opacity_toggle);
WM_operatortype_append(GPENCIL_OT_select);
@@ -352,6 +686,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_select_less);
WM_operatortype_append(GPENCIL_OT_select_first);
WM_operatortype_append(GPENCIL_OT_select_last);
+ WM_operatortype_append(GPENCIL_OT_select_alternate);
WM_operatortype_append(GPENCIL_OT_duplicate);
WM_operatortype_append(GPENCIL_OT_delete);
@@ -391,6 +726,8 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_active_frame_delete);
WM_operatortype_append(GPENCIL_OT_active_frames_delete_all);
+ WM_operatortype_append(GPENCIL_OT_frame_duplicate);
+ WM_operatortype_append(GPENCIL_OT_frame_clean_fill);
WM_operatortype_append(GPENCIL_OT_convert);
@@ -402,36 +739,46 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_stroke_join);
WM_operatortype_append(GPENCIL_OT_stroke_flip);
WM_operatortype_append(GPENCIL_OT_stroke_subdivide);
+ WM_operatortype_append(GPENCIL_OT_stroke_simplify);
+ WM_operatortype_append(GPENCIL_OT_stroke_simplify_fixed);
+ WM_operatortype_append(GPENCIL_OT_stroke_separate);
+ WM_operatortype_append(GPENCIL_OT_stroke_split);
- WM_operatortype_append(GPENCIL_OT_palette_add);
- WM_operatortype_append(GPENCIL_OT_palette_remove);
- WM_operatortype_append(GPENCIL_OT_palette_change);
- WM_operatortype_append(GPENCIL_OT_palette_lock_layer);
- WM_operatortype_append(GPENCIL_OT_palettecolor_add);
- WM_operatortype_append(GPENCIL_OT_palettecolor_remove);
- WM_operatortype_append(GPENCIL_OT_palettecolor_isolate);
- WM_operatortype_append(GPENCIL_OT_palettecolor_hide);
- WM_operatortype_append(GPENCIL_OT_palettecolor_reveal);
- WM_operatortype_append(GPENCIL_OT_palettecolor_lock_all);
- WM_operatortype_append(GPENCIL_OT_palettecolor_unlock_all);
- WM_operatortype_append(GPENCIL_OT_palettecolor_move);
- WM_operatortype_append(GPENCIL_OT_palettecolor_select);
- WM_operatortype_append(GPENCIL_OT_palettecolor_copy);
-
- WM_operatortype_append(GPENCIL_OT_brush_add);
- WM_operatortype_append(GPENCIL_OT_brush_remove);
- WM_operatortype_append(GPENCIL_OT_brush_change);
- WM_operatortype_append(GPENCIL_OT_brush_move);
WM_operatortype_append(GPENCIL_OT_brush_presets_create);
- WM_operatortype_append(GPENCIL_OT_brush_copy);
WM_operatortype_append(GPENCIL_OT_brush_select);
+ WM_operatortype_append(GPENCIL_OT_sculpt_select);
+
+ /* vertex groups */
+ WM_operatortype_append(GPENCIL_OT_vertex_group_assign);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_remove_from);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_select);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_deselect);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_invert);
+ WM_operatortype_append(GPENCIL_OT_vertex_group_smooth);
+
+ /* color handle */
+ WM_operatortype_append(GPENCIL_OT_lock_layer);
+ WM_operatortype_append(GPENCIL_OT_color_isolate);
+ WM_operatortype_append(GPENCIL_OT_color_hide);
+ WM_operatortype_append(GPENCIL_OT_color_reveal);
+ WM_operatortype_append(GPENCIL_OT_color_lock_all);
+ WM_operatortype_append(GPENCIL_OT_color_unlock_all);
+ WM_operatortype_append(GPENCIL_OT_color_select);
+
/* Editing (Time) --------------- */
/* Interpolation */
WM_operatortype_append(GPENCIL_OT_interpolate);
WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
WM_operatortype_append(GPENCIL_OT_interpolate_reverse);
+
+ /* Primitives */
+ WM_operatortype_append(GPENCIL_OT_primitive);
+
+ /* convert old 2.7 files to 2.8 */
+ WM_operatortype_append(GPENCIL_OT_convert_old_files);
+
}
void ED_operatormacros_gpencil(void)
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index ec8a213301f..d4371926eb4 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -46,26 +46,32 @@
#include "PIL_time.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_windowmanager_types.h"
+
#include "BKE_colortools.h"
+#include "BKE_main.h"
+#include "BKE_brush.h"
+#include "BKE_paint.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_main.h"
-#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_layer.h"
+#include "BKE_material.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_windowmanager_types.h"
-
#include "UI_view2d.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
+#include "ED_object.h"
#include "ED_view3d.h"
#include "ED_clip.h"
@@ -82,6 +88,7 @@
#include "WM_types.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "gpencil_intern.h"
@@ -110,6 +117,8 @@ typedef enum eGPencil_PaintFlags {
GP_PAINTFLAG_STROKEADDED = (1 << 1),
GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
GP_PAINTFLAG_SELECTMASK = (1 << 3),
+ GP_PAINTFLAG_HARD_ERASER = (1 << 4),
+ GP_PAINTFLAG_STROKE_ERASER = (1 << 5),
} eGPencil_PaintFlags;
@@ -117,10 +126,13 @@ typedef enum eGPencil_PaintFlags {
* "p" = op->customdata
*/
typedef struct tGPsdata {
- Main *bmain;
+ bContext *C;
+
+ Main *bmain; /* main database pointer */
Scene *scene; /* current scene from context */
struct Depsgraph *depsgraph;
+ Object *ob; /* current object */
wmWindow *win; /* window where painting originated */
ScrArea *sa; /* area where painting originated */
ARegion *ar; /* region where painting originated */
@@ -165,14 +177,23 @@ typedef struct tGPsdata {
void *erasercursor; /* radial cursor data for drawing eraser */
- bGPDpalettecolor *palettecolor; /* current palette color */
- bGPDbrush *brush; /* current drawing brush */
+ /* mat settings are only used for 3D view */
+ Material *material; /* current material */
+
+ Brush *brush; /* current drawing brush */
+ Brush *eraser; /* default eraser brush */
short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
int lock_axis; /* lock drawing to one axis */
+ bool disable_fill; /* the stroke is no fill mode */
RNG *rng;
short keymodifier; /* key used for invoking the operator */
+ short shift; /* shift modifier flag */
+
+ float totpixlen; /* size in pixels for uv calculation */
+
+ ReportList *reports;
} tGPsdata;
/* ------ */
@@ -183,6 +204,14 @@ typedef struct tGPsdata {
/* minimum length of new segment before new point can be added */
#define MIN_EUCLIDEAN_PX (U.gp_euclideandist)
+static void gp_update_cache(bGPdata *gpd)
+{
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ }
+}
+
static bool gp_stroke_added_check(tGPsdata *p)
{
return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
@@ -192,6 +221,9 @@ static void gp_stroke_added_enable(tGPsdata *p)
{
BLI_assert(p->gpf->strokes.last != NULL);
p->flags |= GP_PAINTFLAG_STROKEADDED;
+
+ /* drawing batch cache is dirty now */
+ gp_update_cache(p->gpd);
}
/* ------ */
@@ -206,30 +238,42 @@ static void gp_session_validatebuffer(tGPsdata *p);
static bool gpencil_draw_poll(bContext *C)
{
if (ED_operator_regionactive(C)) {
- /* check if current context can support GPencil data */
- if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
- /* check if Grease Pencil isn't already running */
- if (ED_gpencil_session_active() == 0)
- return 1;
- else
- CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
+ ScrArea *sa = CTX_wm_area(C);
+ if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
+ /* check if current context can support GPencil data */
+ if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
+ /* check if Grease Pencil isn't already running */
+ if (ED_gpencil_session_active() == 0)
+ return 1;
+ else
+ CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
+ }
+ return 0;
}
+ /* 3D Viewport */
else {
- CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
+ if (ED_gpencil_session_active() == 0) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
}
else {
CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ return 0;
}
-
- return 0;
}
/* check if projecting strokes into 3d-geometry in the 3D-View */
static bool gpencil_project_check(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
- return ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
+ return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
}
/* ******************************************* */
@@ -241,38 +285,39 @@ static bool gpencil_project_check(tGPsdata *p)
static void gp_get_3d_reference(tGPsdata *p, float vec[3])
{
View3D *v3d = p->sa->spacedata.first;
- const float *fp = ED_view3d_cursor3d_get(p->scene, v3d)->location;
-
- /* the reference point used depends on the owner... */
-#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
+ Object *ob = NULL;
if (p->ownerPtr.type == &RNA_Object) {
- Object *ob = (Object *)p->ownerPtr.data;
-
- /* active Object
- * - use relative distance of 3D-cursor from object center
- */
- sub_v3_v3v3(vec, fp, ob->loc);
- }
- else
-#endif
- {
- /* use 3D-cursor */
- copy_v3_v3(vec, fp);
+ ob = (Object *)p->ownerPtr.data;
}
+ ED_gp_get_drawing_reference(v3d, p->scene, ob, p->gpl, *p->align_flag, vec);
}
/* Stroke Editing ---------------------------- */
-
/* check if the current mouse position is suitable for adding a new point */
static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
{
+ Brush *brush = p->brush;
int dx = abs(mval[0] - pmval[0]);
int dy = abs(mval[1] - pmval[1]);
+ brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
/* if buffer is empty, just let this go through (i.e. so that dots will work) */
- if (p->gpd->sbuffer_size == 0)
+ if (p->gpd->runtime.sbuffer_size == 0) {
return true;
-
+ }
+ /* if lazy mouse, check minimum distance */
+ else if (GPENCIL_LAZY_MODE(brush, p->shift)) {
+ brush->gpencil_settings->flag |= GP_BRUSH_STABILIZE_MOUSE_TEMP;
+ if ((dx * dx + dy * dy) > (brush->smooth_stroke_radius * brush->smooth_stroke_radius)) {
+ return true;
+ }
+ else {
+ /* If the mouse is moving within the radius of the last move,
+ * don't update the mouse position. This allows sharp turns. */
+ copy_v2_v2_int(p->mval, p->mvalo);
+ return false;
+ }
+ }
/* check if mouse moved at least certain distance on both axes (best case)
* - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
*/
@@ -291,47 +336,17 @@ static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
return false;
}
-/* reproject the points of the stroke to a plane locked to axis to avoid stroke offset */
-static void gp_project_points_to_plane(RegionView3D *rv3d, bGPDstroke *gps, const float origin[3], const int axis)
-{
- float plane_normal[3];
- float vn[3];
-
- float ray[3];
- float rpoint[3];
-
- /* normal vector for a plane locked to axis */
- zero_v3(plane_normal);
- plane_normal[axis] = 1.0f;
-
- /* Reproject the points in the plane */
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
-
- /* get a vector from the point with the current view direction of the viewport */
- ED_view3d_global_to_vector(rv3d, &pt->x, vn);
-
- /* calculate line extrem point to create a ray that cross the plane */
- mul_v3_fl(vn, -50.0f);
- add_v3_v3v3(ray, &pt->x, vn);
-
- /* if the line never intersect, the point is not changed */
- if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
- copy_v3_v3(&pt->x, rpoint);
- }
- }
-}
-
/* reproject stroke to plane locked to axis in 3d cursor location */
static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
{
bGPdata *gpd = p->gpd;
+ Object *obact = (Object *)p->ownerPtr.data;
+
float origin[3];
- float cursor[3];
RegionView3D *rv3d = p->ar->regiondata;
/* verify the stroke mode is CURSOR 3d space mode */
- if ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
+ if ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
return;
}
if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
@@ -341,12 +356,9 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
return;
}
- /* get 3d cursor and set origin for locked axis only. Uses axis-1 because the enum for XYZ start with 1 */
- gp_get_3d_reference(p, cursor);
- zero_v3(origin);
- origin[p->lock_axis - 1] = cursor[p->lock_axis - 1];
-
- gp_project_points_to_plane(rv3d, gps, origin, p->lock_axis - 1);
+ /* get drawing origin */
+ gp_get_3d_reference(p, origin);
+ ED_gp_project_stroke_to_plane(obact, rv3d, gps, origin, p->lock_axis - 1);
}
/* convert screen-coordinates to buffer-coordinates */
@@ -356,7 +368,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
bGPdata *gpd = p->gpd;
/* in 3d-space - pt->x/y/z are 3 side-by-side floats */
- if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval, out, 0, depth))) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
@@ -365,7 +377,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
else {
float mval_prj[2];
float rvec[3], dvec[3];
- float mval_f[2] = {UNPACK2(mval)};
+ float mval_f[2];
+ copy_v2fl_v2i(mval_f, mval);
float zfac;
/* Current method just converts each point in screen-coordinates to
@@ -390,42 +403,23 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
}
}
}
-
- /* 2d - on 'canvas' (assume that p->v2d is set) */
- else if ((gpd->sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
- UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]);
- mul_v3_m4v3(out, p->imat, out);
- }
-
- /* 2d - relative to screen (viewport area) */
- else {
- if (p->subrect == NULL) { /* normal 3D view */
- out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
- out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
- }
- else { /* camera view, use subrect */
- out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
- out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
- }
- }
}
/* apply jitter to stroke */
-static void gp_brush_jitter(
- bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2], RNG *rng)
+static void gp_brush_jitter(bGPdata *gpd, Brush *brush, tGPspoint *pt, const int mval[2], int r_mval[2], RNG *rng)
{
float pressure = pt->pressure;
float tmp_pressure = pt->pressure;
- if (brush->draw_jitter > 0.0f) {
- float curvef = curvemapping_evaluateF(brush->cur_jitter, 0, pressure);
- tmp_pressure = curvef * brush->draw_sensitivity;
+ if (brush->gpencil_settings->draw_jitter > 0.0f) {
+ float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, pressure);
+ tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
}
- const float exfactor = (brush->draw_jitter + 2.0f) * (brush->draw_jitter + 2.0f); /* exponential value */
+ const float exfactor = (brush->gpencil_settings->draw_jitter + 2.0f) * (brush->gpencil_settings->draw_jitter + 2.0f); /* exponential value */
const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure;
/* Jitter is applied perpendicular to the mouse movement vector (2D space) */
float mvec[2], svec[2];
/* mouse movement in ints -> floats */
- if (gpd->sbuffer_size > 1) {
+ if (gpd->runtime.sbuffer_size > 1) {
mvec[0] = (float)(mval[0] - (pt - 1)->x);
mvec[1] = (float)(mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -451,18 +445,18 @@ static void gp_brush_jitter(
}
/* apply pressure change depending of the angle of the stroke to simulate a pen with shape */
-static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2])
+static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const int mval[2])
{
float mvec[2];
- float sen = brush->draw_angle_factor; /* sensitivity */;
+ float sen = brush->gpencil_settings->draw_angle_factor; /* sensitivity */;
float fac;
float mpressure;
- float angle = brush->draw_angle; /* default angle of brush in radians */;
+ float angle = brush->gpencil_settings->draw_angle; /* default angle of brush in radians */;
float v0[2] = { cos(angle), sin(angle) }; /* angle vector of the brush with full thickness */
/* Apply to first point (only if there are 2 points because before no data to do it ) */
- if (gpd->sbuffer_size == 1) {
+ if (gpd->runtime.sbuffer_size == 1) {
mvec[0] = (float)(mval[0] - (pt - 1)->x);
mvec[1] = (float)(mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -475,7 +469,7 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
}
/* apply from second point */
- if (gpd->sbuffer_size >= 1) {
+ if (gpd->runtime.sbuffer_size >= 1) {
mvec[0] = (float)(mval[0] - (pt - 1)->x);
mvec[1] = (float)(mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -490,21 +484,83 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
}
+/* Apply smooth to buffer while drawing
+* to smooth point C, use 2 before (A, B) and current point (D):
+*
+* A----B-----C------D
+*
+* \param p Temp data
+* \param inf Influence factor
+* \param idx Index of the last point (need minimum 3 points in the array)
+*/
+static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
+{
+ bGPdata *gpd = p->gpd;
+ short num_points = gpd->runtime.sbuffer_size;
+
+ /* Do nothing if not enough points to smooth out */
+ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
+ return;
+ }
+
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ float steps = 4.0f;
+ if (idx < 4) {
+ steps--;
+ }
+
+ tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
+ tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
+ tGPspoint *ptc = idx >= 2 ? &points[idx - 2] : NULL;
+ tGPspoint *ptd = &points[idx - 1];
+
+ float sco[2] = { 0.0f };
+ float a[2], b[2], c[2], d[2];
+ const float average_fac = 1.0f / steps;
+
+ /* Compute smoothed coordinate by taking the ones nearby */
+ if (pta) {
+ copy_v2fl_v2i(a, &pta->x);
+ madd_v2_v2fl(sco, a, average_fac);
+ }
+ if (ptb) {
+ copy_v2fl_v2i(b, &ptb->x);
+ madd_v2_v2fl(sco, b, average_fac);
+ }
+ if (ptc) {
+ copy_v2fl_v2i(c, &ptc->x);
+ madd_v2_v2fl(sco, c, average_fac);
+ }
+ if (ptd) {
+ copy_v2fl_v2i(d, &ptd->x);
+ madd_v2_v2fl(sco, d, average_fac);
+ }
+
+ /* Based on influence factor, blend between original and optimal smoothed coordinate */
+ interp_v2_v2v2(c, c, sco, inf);
+ round_v2i_v2fl(&ptc->x, c);
+}
+
/* add current stroke-point to buffer (returns whether point was successfully added) */
static short gp_stroke_addpoint(
tGPsdata *p, const int mval[2], float pressure, double curtime)
{
bGPdata *gpd = p->gpd;
- bGPDbrush *brush = p->brush;
+ Brush *brush = p->brush;
tGPspoint *pt;
ToolSettings *ts = p->scene->toolsettings;
+ Object *obact = (Object *)p->ownerPtr.data;
+ Depsgraph *depsgraph = p->depsgraph; \
+ RegionView3D *rv3d = p->ar->regiondata;
+ View3D *v3d = p->sa->spacedata.first;
+ MaterialGPencilStyle *gp_style = p->material->gp_style;
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
- if (gpd->sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_size == 0) {
/* first point in buffer (start point) */
- pt = (tGPspoint *)(gpd->sbuffer);
+ pt = (tGPspoint *)(gpd->runtime.sbuffer);
/* store settings */
copy_v2_v2_int(&pt->x, mval);
@@ -513,13 +569,13 @@ static short gp_stroke_addpoint(
pt->time = (float)(curtime - p->inittime);
/* increment buffer size */
- gpd->sbuffer_size++;
+ gpd->runtime.sbuffer_size++;
}
else {
/* just reset the endpoint to the latest value
* - assume that pointers for this are always valid...
*/
- pt = ((tGPspoint *)(gpd->sbuffer) + 1);
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
/* store settings */
copy_v2_v2_int(&pt->x, mval);
@@ -528,31 +584,35 @@ static short gp_stroke_addpoint(
pt->time = (float)(curtime - p->inittime);
/* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
- gpd->sbuffer_size = 2;
+ gpd->runtime.sbuffer_size = 2;
}
+ /* tag depsgraph to update object */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
/* can keep carrying on this way :) */
return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
/* check if still room in buffer */
- if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX)
+ if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
return GP_STROKEADD_OVERFLOW;
/* get pointer to destination point */
- pt = ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size);
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
/* store settings */
/* pressure */
- if (brush->flag & GP_BRUSH_USE_PRESSURE) {
- float curvef = curvemapping_evaluateF(brush->cur_sensitivity, 0, pressure);
- pt->pressure = curvef * brush->draw_sensitivity;
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_sensitivity, 0, pressure);
+ pt->pressure = curvef * brush->gpencil_settings->draw_sensitivity;
}
else {
pt->pressure = 1.0f;
}
+
/* Apply jitter to position */
- if (brush->draw_jitter > 0.0f) {
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush->gpencil_settings->draw_jitter > 0.0f)) {
int r_mval[2];
gp_brush_jitter(gpd, brush, pt, mval, r_mval, p->rng);
copy_v2_v2_int(&pt->x, r_mval);
@@ -561,42 +621,62 @@ static short gp_stroke_addpoint(
copy_v2_v2_int(&pt->x, mval);
}
/* apply randomness to pressure */
- if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_PRESSURE)) {
- float curvef = curvemapping_evaluateF(brush->cur_sensitivity, 0, pressure);
- float tmp_pressure = curvef * brush->draw_sensitivity;
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
+ (brush->gpencil_settings->draw_random_press > 0.0f))
+ {
+ float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_sensitivity, 0, pressure);
+ float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
+ pt->pressure -= tmp_pressure * brush->gpencil_settings->draw_random_press * BLI_rng_get_float(p->rng);
}
else {
- pt->pressure += tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
+ pt->pressure += tmp_pressure * brush->gpencil_settings->draw_random_press * BLI_rng_get_float(p->rng);
}
CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
}
+ /* apply randomness to uv texture rotation */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush->gpencil_settings->uv_random > 0.0f)) {
+ if (BLI_rng_get_float(p->rng) > 0.5f) {
+ pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI * -1) * brush->gpencil_settings->uv_random;
+ }
+ else {
+ pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI) * brush->gpencil_settings->uv_random;
+ }
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
+ }
+ else {
+ pt->uv_rot = 0.0f;
+ }
+
/* apply angle of stroke to brush size */
- if (brush->draw_angle_factor > 0.0f) {
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
+ (brush->gpencil_settings->draw_angle_factor > 0.0f))
+ {
gp_brush_angle(gpd, brush, pt, mval);
}
/* color strength */
- if (brush->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- float curvef = curvemapping_evaluateF(brush->cur_strength, 0, pressure);
- float tmp_pressure = curvef * brush->draw_sensitivity;
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_strength, 0, pressure);
+ float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
- pt->strength = tmp_pressure * brush->draw_strength;
+ pt->strength = tmp_pressure * brush->gpencil_settings->draw_strength;
}
else {
- pt->strength = brush->draw_strength;
+ pt->strength = brush->gpencil_settings->draw_strength;
}
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
/* apply randomness to color strength */
- if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_STRENGTH)) {
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
+ (brush->gpencil_settings->draw_random_strength > 0.0f))
+ {
if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->strength -= pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
+ pt->strength -= pt->strength * brush->gpencil_settings->draw_random_strength * BLI_rng_get_float(p->rng);
}
else {
- pt->strength += pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
+ pt->strength += pt->strength * brush->gpencil_settings->draw_random_strength * BLI_rng_get_float(p->rng);
}
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
@@ -604,11 +684,49 @@ static short gp_stroke_addpoint(
/* point time */
pt->time = (float)(curtime - p->inittime);
+ /* point uv (only 3d view) */
+ if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_size > 1)) {
+ float pixsize = gp_style->texture_pixsize / 1000000.0f;
+ tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 2;
+ bGPDspoint spt, spt2;
+
+ /* get origin to reproject point */
+ float origin[3];
+ gp_get_3d_reference(p, origin);
+ /* reproject current */
+ ED_gpencil_tpoint_to_point(p->ar, origin, pt, &spt);
+ ED_gp_project_point_to_plane(obact, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &spt);
+
+ /* reproject previous */
+ ED_gpencil_tpoint_to_point(p->ar, origin, ptb, &spt2);
+ ED_gp_project_point_to_plane(obact, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &spt2);
+
+ p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ pt->uv_fac = p->totpixlen;
+ if ((gp_style) && (gp_style->sima)) {
+ pt->uv_fac /= gp_style->sima->gen_x;
+ }
+ }
+ else {
+ p->totpixlen = 0.0f;
+ pt->uv_fac = 0.0f;
+ }
+
/* increment counters */
- gpd->sbuffer_size++;
+ gpd->runtime.sbuffer_size++;
+
+ /* smooth while drawing previous points with a reduction factor for previous */
+ if (brush->gpencil_settings->active_smooth > 0.0f) {
+ for (int s = 0; s < 3; s++) {
+ gp_smooth_buffer(p, brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_size - s);
+ }
+ }
+
+ /* tag depsgraph to update object */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
/* check if another operation can still occur */
- if (gpd->sbuffer_size == GP_STROKE_BUFFER_MAX)
+ if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
return GP_STROKEADD_FULL;
else
return GP_STROKEADD_NORMAL;
@@ -617,7 +735,7 @@ static short gp_stroke_addpoint(
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
/* get pointer to destination point */
- pt = (tGPspoint *)(gpd->sbuffer);
+ pt = (tGPspoint *)(gpd->runtime.sbuffer);
/* store settings */
copy_v2_v2_int(&pt->x, mval);
@@ -632,14 +750,17 @@ static short gp_stroke_addpoint(
if (gp_stroke_added_check(p)) {
bGPDstroke *gps = p->gpf->strokes.last;
bGPDspoint *pts;
+ MDeformVert *dvert;
/* first time point is adding to temporary buffer -- need to allocate new point in stroke */
- if (gpd->sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_size == 0) {
gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
+ gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
gps->totpoints++;
}
pts = &gps->points[gps->totpoints - 1];
+ dvert = &gps->dvert[gps->totpoints - 1];
/* special case for poly lines: normally,
* depth is needed only when creating new stroke from buffer,
@@ -647,8 +768,6 @@ static short gp_stroke_addpoint(
* so initialize depth buffer before converting coordinates
*/
if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
-
view3d_region_operator_needs_opengl(p->win, p->ar);
ED_view3d_autodist_init(
p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
@@ -656,25 +775,32 @@ static short gp_stroke_addpoint(
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
- /* if axis locked, reproject to plane locked (only in 3d space) */
- if (p->lock_axis > GP_LOCKAXIS_NONE) {
- gp_reproject_toplane(p, gps);
- }
+ /* reproject to plane (only in 3d space) */
+ gp_reproject_toplane(p, gps);
/* if parented change position relative to parent object */
- if (gpl->parent != NULL) {
- gp_apply_parent_point(gpl, pts);
- }
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pts);
/* copy pressure and time */
pts->pressure = pt->pressure;
pts->strength = pt->strength;
pts->time = pt->time;
+ pts->uv_fac = pt->uv_fac;
+ pts->uv_rot = pt->uv_rot;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+
/* force fill recalc */
gps->flag |= GP_STROKE_RECALC_CACHES;
+ /* drawing batch cache is dirty now */
+ gp_update_cache(p->gpd);
}
/* increment counters */
- if (gpd->sbuffer_size == 0)
- gpd->sbuffer_size++;
+ if (gpd->runtime.sbuffer_size == 0)
+ gpd->runtime.sbuffer_size++;
+
+ /* tag depsgraph to update object */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
return GP_STROKEADD_NORMAL;
}
@@ -690,9 +816,9 @@ static short gp_stroke_addpoint(
static void gp_stroke_simplify(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
- tGPspoint *old_points = (tGPspoint *)gpd->sbuffer;
- short num_points = gpd->sbuffer_size;
- short flag = gpd->sbuffer_sflag;
+ tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
+ short num_points = gpd->runtime.sbuffer_size;
+ short flag = gpd->runtime.sbuffer_sflag;
short i, j;
/* only simplify if simplification is enabled, and we're not doing a straight line */
@@ -707,9 +833,9 @@ static void gp_stroke_simplify(tGPsdata *p)
* - firstly set sbuffer to NULL, so a new one is allocated
* - secondly, reset flag after, as it gets cleared auto
*/
- gpd->sbuffer = NULL;
+ gpd->runtime.sbuffer = NULL;
gp_session_validatebuffer(p);
- gpd->sbuffer_sflag = flag;
+ gpd->runtime.sbuffer_sflag = flag;
/* macro used in loop to get position of new point
* - used due to the mixture of datatypes in use here
@@ -766,8 +892,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
bGPDstroke *gps;
bGPDspoint *pt;
tGPspoint *ptc;
- bGPDbrush *brush = p->brush;
+ MDeformVert *dvert;
+ Brush *brush = p->brush;
ToolSettings *ts = p->scene->toolsettings;
+ Depsgraph *depsgraph = p->depsgraph;
+ Object *obact = (Object *)p->ownerPtr.data;
int i, totelem;
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
@@ -777,14 +906,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
* - drawing straight-lines only requires the endpoints
*/
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
- totelem = (gpd->sbuffer_size >= 2) ? 2 : gpd->sbuffer_size;
+ totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
else
- totelem = gpd->sbuffer_size;
+ totelem = gpd->runtime.sbuffer_size;
/* exit with error if no valid points from this stroke */
if (totelem == 0) {
if (G.debug & G_DEBUG)
- printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->sbuffer_size);
+ printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->runtime.sbuffer_size);
return;
}
@@ -793,6 +922,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
* interactive behavior
*/
if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
+ /* be sure to hide any lazy cursor */
+ ED_gpencil_toggle_brush_cursor(p->C, true, NULL);
+
if (gp_stroke_added_check(p)) {
return;
}
@@ -803,95 +935,94 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* copy appropriate settings for stroke */
gps->totpoints = totelem;
- gps->thickness = brush->thickness;
- gps->flag = gpd->sbuffer_sflag;
+ gps->thickness = brush->size;
+ gps->flag = gpd->runtime.sbuffer_sflag;
gps->inittime = p->inittime;
/* enable recalculation flag by default (only used if hq fill) */
gps->flag |= GP_STROKE_RECALC_CACHES;
/* allocate enough memory for a continuous array for storage points */
- int sublevel = brush->sublevel;
- int new_totpoints = gps->totpoints;
+ const int subdivide = brush->gpencil_settings->draw_subdivide;
+
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
- for (i = 0; i < sublevel; i++) {
- new_totpoints += new_totpoints - 1;
- }
- gps->points = MEM_callocN(sizeof(bGPDspoint) * new_totpoints, "gp_stroke_points");
/* initialize triangle memory to dummy data */
gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
gps->flag |= GP_STROKE_RECALC_CACHES;
gps->tot_triangles = 0;
+ /* drawing batch cache is dirty now */
+ gp_update_cache(p->gpd);
/* set pointer to first non-initialized point */
pt = gps->points + (gps->totpoints - totelem);
+ dvert = gps->dvert + (gps->totpoints - totelem);
/* copy points from the buffer to the stroke */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only -> only endpoints */
{
/* first point */
- ptc = gpd->sbuffer;
+ ptc = gpd->runtime.sbuffer;
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* if axis locked, reproject to plane locked (only in 3d space) */
- if (p->lock_axis > GP_LOCKAXIS_NONE) {
- gp_reproject_toplane(p, gps);
- }
- /* if parented change position relative to parent object */
- if (gpl->parent != NULL) {
- gp_apply_parent_point(gpl, pt);
- }
/* copy pressure and time */
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+
pt++;
+ dvert++;
}
if (totelem == 2) {
/* last point if applicable */
- ptc = ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* if axis locked, reproject to plane locked (only in 3d space) */
- if (p->lock_axis > GP_LOCKAXIS_NONE) {
- gp_reproject_toplane(p, gps);
- }
- /* if parented change position relative to parent object */
- if (gpl->parent != NULL) {
- gp_apply_parent_point(gpl, pt);
- }
-
/* copy pressure and time */
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ }
+
+ /* reproject to plane (only in 3d space) */
+ gp_reproject_toplane(p, gps);
+ pt = gps->points;
+ for (i = 0; i < gps->totpoints; i++, pt++) {
+ /* if parented change position relative to parent object */
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
}
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
/* first point */
- ptc = gpd->sbuffer;
+ ptc = gpd->runtime.sbuffer;
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* if axis locked, reproject to plane locked (only in 3d space) */
- if (p->lock_axis > GP_LOCKAXIS_NONE) {
- gp_reproject_toplane(p, gps);
- }
+ /* reproject to plane (only in 3d space) */
+ gp_reproject_toplane(p, gps);
/* if parented change position relative to parent object */
- if (gpl->parent != NULL) {
- gp_apply_parent_point(gpl, pt);
- }
+ gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
/* copy pressure and time */
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+
}
else {
float *depth_arr = NULL;
@@ -902,9 +1033,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int interp_depth = 0;
int found_depth = 0;
- depth_arr = MEM_mallocN(sizeof(float) * gpd->sbuffer_size, "depth_points");
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
- for (i = 0, ptc = gpd->sbuffer; i < gpd->sbuffer_size; i++, ptc++, pt++) {
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) {
copy_v2_v2_int(mval, &ptc->x);
if ((ED_view3d_autodist_depth(p->ar, mval, depth_margin, depth_arr + i) == 0) &&
@@ -921,7 +1052,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if (found_depth == false) {
/* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
- for (i = gpd->sbuffer_size - 1; i >= 0; i--)
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
depth_arr[i] = 0.9999f;
}
else {
@@ -930,13 +1061,13 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int first_valid = 0;
int last_valid = 0;
- for (i = 0; i < gpd->sbuffer_size; i++) {
+ for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
if (depth_arr[i] != FLT_MAX)
break;
}
first_valid = i;
- for (i = gpd->sbuffer_size - 1; i >= 0; i--) {
+ for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
if (depth_arr[i] != FLT_MAX)
break;
}
@@ -950,16 +1081,15 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
if (interp_depth) {
- interp_sparse_array(depth_arr, gpd->sbuffer_size, FLT_MAX);
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
}
}
}
-
pt = gps->points;
/* convert all points (normal behavior) */
- for (i = 0, ptc = gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++, pt++) {
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; i++, ptc++, pt++) {
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
@@ -968,20 +1098,18 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+ pt->uv_fac = ptc->uv_fac;
+ pt->uv_rot = ptc->uv_rot;
}
- /* subdivide the stroke */
- if (sublevel > 0) {
- int totpoints = gps->totpoints;
- for (i = 0; i < sublevel; i++) {
- /* we're adding one new point between each pair of verts on each step */
- totpoints += totpoints - 1;
-
- gp_subdivide_stroke(gps, totpoints);
- }
+ /* subdivide and smooth the stroke */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) && (subdivide > 0)) {
+ gp_subdivide_stroke(gps, subdivide);
}
/* apply randomness to stroke */
- if (brush->draw_random_sub > 0.0f) {
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
+ (brush->gpencil_settings->draw_random_sub > 0.0f))
+ {
gp_randomize_stroke(gps, brush, p->rng);
}
@@ -989,34 +1117,43 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
* for each iteration, the factor is reduced to get a better smoothing without changing too much
* the original stroke
*/
- if (brush->draw_smoothfac > 0.0f) {
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
+ (brush->gpencil_settings->draw_smoothfac > 0.0f))
+ {
float reduce = 0.0f;
- for (int r = 0; r < brush->draw_smoothlvl; ++r) {
+ for (int r = 0; r < brush->gpencil_settings->draw_smoothlvl; r++) {
for (i = 0; i < gps->totpoints; i++) {
- /* NOTE: No pressure smoothing, or else we get annoying thickness changes while drawing... */
- gp_smooth_stroke(gps, i, brush->draw_smoothfac - reduce, false);
+ BKE_gpencil_smooth_stroke(gps, i, brush->gpencil_settings->draw_smoothfac - reduce);
+ BKE_gpencil_smooth_stroke_strength(gps, i, brush->gpencil_settings->draw_smoothfac);
}
reduce += 0.25f; // reduce the factor
}
}
-
- /* if axis locked, reproject to plane locked (only in 3d space) */
- if (p->lock_axis > GP_LOCKAXIS_NONE) {
- gp_reproject_toplane(p, gps);
- }
- /* if parented change position relative to parent object */
- if (gpl->parent != NULL) {
- gp_apply_parent(gpl, gps);
+ /* smooth thickness */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
+ (brush->gpencil_settings->thick_smoothfac > 0.0f))
+ {
+ for (int r = 0; r < brush->gpencil_settings->thick_smoothlvl * 2; r++) {
+ for (i = 0; i < gps->totpoints; i++) {
+ BKE_gpencil_smooth_stroke_thickness(gps, i, brush->gpencil_settings->thick_smoothfac);
+ }
+ }
}
+ /* reproject to plane (only in 3d space) */
+ gp_reproject_toplane(p, gps);
+ /* change position relative to parent object */
+ gp_apply_parent(depsgraph, obact, gpd, gpl, gps);
+
if (depth_arr)
MEM_freeN(depth_arr);
}
- /* Save palette color */
- bGPDpalette *palette = BKE_gpencil_palette_getactive(p->gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
- gps->palcolor = palcolor;
- BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
+
+ /* Save material index */
+ gps->mat_nr = BKE_gpencil_get_material_index(p->ob, p->material) - 1;
+
+ /* calculate UVs along the stroke */
+ ED_gpencil_calc_stroke_uv(obact, gps);
/* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head
* because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist
@@ -1047,6 +1184,8 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
/* only erase stroke points that are visible */
static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
{
+ Object *obact = (Object *)p->ownerPtr.data;
+
if ((p->sa->spacetype == SPACE_VIEW3D) &&
(p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
{
@@ -1059,7 +1198,7 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, cons
float diff_mat[4][4];
/* calculate difference matrix if parent object */
- ED_gpencil_parent_location(gpl, diff_mat);
+ ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat);
if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
@@ -1092,6 +1231,24 @@ static float gp_stroke_eraser_calc_influence(tGPsdata *p, const int mval[2], con
return fac;
}
+/* helper to free a stroke */
+static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps)
+{
+ if (gps->points) {
+ MEM_freeN(gps->points);
+ }
+
+ if (gps->dvert) {
+ BKE_gpencil_free_stroke_weights(gps);
+ MEM_freeN(gps->dvert);
+ }
+
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+ gp_update_cache(gpd);
+}
+
/* eraser tool - evaluation per stroke */
/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
static void gp_stroke_eraser_dostroke(tGPsdata *p,
@@ -1099,46 +1256,58 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
const int mval[2], const int mvalo[2],
const int radius, const rcti *rect)
{
+ Depsgraph *depsgraph = p->depsgraph;
+ Object *obact = (Object *)p->ownerPtr.data;
+ Brush *eraser = p->eraser;
bGPDspoint *pt1, *pt2;
int pc1[2] = {0};
int pc2[2] = {0};
int i;
float diff_mat[4][4];
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- }
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, p->gpd, gpl, diff_mat);
if (gps->totpoints == 0) {
/* just free stroke */
- if (gps->points)
- MEM_freeN(gps->points);
- if (gps->triangles)
- MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ gp_free_stroke(p->gpd, gpf, gps);
}
else if (gps->totpoints == 1) {
/* only process if it hasn't been masked out... */
if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
- if (gpl->parent == NULL) {
- gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]);
- }
- else {
- bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
+ bGPDspoint pt_temp;
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval, pc1) <= radius) {
+ /* free stroke */
+ gp_free_stroke(p->gpd, gpf, gps);
+ }
}
+ }
+ }
+ else if ((p->flags & GP_PAINTFLAG_STROKE_ERASER) || (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_STROKE)) {
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ /* get points to work with */
+ pt1 = gps->points + i;
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]);
+
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
/* only check if point is inside */
if (len_v2v2_int(mval, pc1) <= radius) {
/* free stroke */
- // XXX: pressure sensitive eraser should apply here too?
- MEM_freeN(gps->points);
- if (gps->triangles)
- MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ gp_free_stroke(p->gpd, gpf, gps);
+ return;
}
}
}
@@ -1181,18 +1350,12 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
continue;
- if (gpl->parent == NULL) {
- gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
- gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
- }
- else {
- bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
- gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]);
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]);
- gp_point_to_parent_space(pt2, diff_mat, &npt);
- gp_point_to_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]);
- }
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]);
/* Check that point segment of the boundbox of the eraser stroke */
if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
@@ -1215,11 +1378,15 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength / 2.0f;
/* 2) Tag any point with overly low influence for removal in the next pass */
- if (pt1->pressure < cull_thresh) {
+ if ((pt1->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
+ (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD))
+ {
pt1->flag |= GP_SPOINT_TAG;
do_cull = true;
}
- if (pt2->pressure < cull_thresh) {
+ if ((pt2->pressure < cull_thresh) || (p->flags & GP_PAINTFLAG_HARD_ERASER) ||
+ (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_HARD))
+ {
pt2->flag |= GP_SPOINT_TAG;
do_cull = true;
}
@@ -1230,8 +1397,9 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* Second Pass: Remove any points that are tagged */
if (do_cull) {
- gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG);
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false);
}
+ gp_update_cache(p->gpd);
}
}
@@ -1275,7 +1443,7 @@ static void gp_stroke_doeraser(tGPsdata *p)
for (gps = gpf->strokes.first; gps; gps = gpn) {
gpn = gps->next;
/* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
+ if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) {
continue;
}
/* Not all strokes in the datablock may be valid in the current editor/context
@@ -1295,107 +1463,178 @@ static void gp_stroke_doeraser(tGPsdata *p)
static void gp_session_validatebuffer(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
+ Brush *brush = p->brush;
/* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->sbuffer) {
+ if (gpd->runtime.sbuffer) {
/* printf("\t\tGP - reset sbuffer\n"); */
- memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
+ memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
}
else {
/* printf("\t\tGP - allocate sbuffer\n"); */
- gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
+ gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
}
/* reset indices */
- gpd->sbuffer_size = 0;
+ gpd->runtime.sbuffer_size = 0;
/* reset flags */
- gpd->sbuffer_sflag = 0;
+ gpd->runtime.sbuffer_sflag = 0;
/* reset inittime */
p->inittime = 0.0;
+
+ /* reset lazy */
+ if (brush) {
+ brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
+ }
}
-/* create a new palette color */
-static bGPDpalettecolor *gp_create_new_color(bGPDpalette *palette)
+/* helper to get default eraser and create one if no eraser brush */
+static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts)
{
- bGPDpalettecolor *palcolor;
+ Brush *brush_dft = NULL;
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ Brush *brush_old = paint->brush;
+ for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if ((brush->ob_mode == OB_MODE_GPENCIL_PAINT) &&
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ {
+ /* save first eraser to use later if no default */
+ if (brush_dft == NULL) {
+ brush_dft = brush;
+ }
+ /* found default */
+ if (brush->gpencil_settings->flag & GP_BRUSH_DEFAULT_ERASER) {
+ return brush;
+ }
+ }
+ }
+ /* if no default, but exist eraser brush, return this and set as default */
+ if (brush_dft) {
+ brush_dft->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
+ return brush_dft;
+ }
+ /* create a new soft eraser brush */
+ else {
+ brush_dft = BKE_brush_add_gpencil(bmain, ts, "Soft Eraser");
+ brush_dft->size = 30.0f;
+ brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
+ brush_dft->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
+ brush_dft->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE;
+ brush_dft->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
- palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true);
+ /* reset current brush */
+ BKE_paint_brush_set(paint, brush_old);
- return palcolor;
+ return brush_dft;
+ }
}
/* initialize a drawing brush */
-static void gp_init_drawing_brush(ToolSettings *ts, tGPsdata *p)
+static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
{
- bGPDbrush *brush;
+ Brush *brush;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
/* if not exist, create a new one */
- if (BLI_listbase_is_empty(&ts->gp_brushes)) {
+ if (paint->brush == NULL) {
/* create new brushes */
- BKE_gpencil_brush_init_presets(ts);
- brush = BKE_gpencil_brush_getactive(ts);
+ BKE_brush_gpencil_presets(C);
+ brush = BKE_brush_getactive_gpencil(ts);
}
else {
/* Use the current */
- brush = BKE_gpencil_brush_getactive(ts);
+ brush = BKE_brush_getactive_gpencil(ts);
}
/* be sure curves are initializated */
- curvemapping_initialize(brush->cur_sensitivity);
- curvemapping_initialize(brush->cur_strength);
- curvemapping_initialize(brush->cur_jitter);
+ curvemapping_initialize(brush->gpencil_settings->curve_sensitivity);
+ curvemapping_initialize(brush->gpencil_settings->curve_strength);
+ curvemapping_initialize(brush->gpencil_settings->curve_jitter);
/* asign to temp tGPsdata */
p->brush = brush;
+ if (brush->gpencil_settings->brush_type != GP_BRUSH_TYPE_ERASE) {
+ p->eraser = gp_get_default_eraser(p->bmain, ts);
+ }
+ else {
+ p->eraser = brush;
+ }
+ /* use radius of eraser */
+ p->radius = (short)p->eraser->size;
+
+ /* GPXX: Need this update to synchronize brush with draw manager.
+ * Maybe this update can be removed when the new tool system
+ * will be in place, but while, we need this to keep drawing working.
+ *
+ */
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
}
-/* initialize a paint palette brush and a default color if not exist */
-static void gp_init_palette(tGPsdata *p)
+/* initialize a paint brush and a default color if not exist */
+static void gp_init_colors(tGPsdata *p)
{
- bGPdata *gpd;
- bGPDpalette *palette;
- bGPDpalettecolor *palcolor;
+ bGPdata *gpd = p->gpd;
+ Brush *brush = p->brush;
- gpd = p->gpd;
+ Material *ma = NULL;
+ MaterialGPencilStyle *gp_style = NULL;
+
+ /* use brush material */
+ ma = BKE_gpencil_get_material_from_brush(brush);
+
+ /* if no brush defaults, get material and color info
+ * NOTE: Ensures that everything we need will exist...
+ */
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ BKE_gpencil_material_ensure(p->bmain, p->ob);
- /* if not exist, create a new palette */
- if (BLI_listbase_is_empty(&gpd->palettes)) {
- /* create new palette */
- palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true);
- /* now create a default color */
- palcolor = gp_create_new_color(palette);
+ /* assign always the first material to the brush */
+ p->material = give_current_material(p->ob, 1);
+ brush->gpencil_settings->material = p->material;
}
else {
- /* Use the current palette and color */
- palette = BKE_gpencil_palette_getactive(gpd);
- /* the palette needs one color */
- if (BLI_listbase_is_empty(&palette->colors)) {
- palcolor = gp_create_new_color(palette);
- }
- else {
- palcolor = BKE_gpencil_palettecolor_getactive(palette);
- }
- /* in some situations can be null, so use first */
- if (palcolor == NULL) {
- BKE_gpencil_palettecolor_setactive(palette, palette->colors.first);
- palcolor = palette->colors.first;
- }
+ p->material = ma;
}
- /* asign to temp tGPsdata */
- p->palettecolor = palcolor;
+ /* check if the material is already on object material slots and add it if missing */
+ if (BKE_gpencil_get_material_index(p->ob, p->material) == 0) {
+ BKE_object_material_slot_add(p->bmain, p->ob);
+ assign_material(p->bmain, p->ob, ma, p->ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+ }
+
+ /* assign color information to temp tGPsdata */
+ gp_style = p->material->gp_style;
+ if (gp_style) {
+
+ /* set colors */
+ copy_v4_v4(gpd->runtime.scolor, gp_style->stroke_rgba);
+ copy_v4_v4(gpd->runtime.sfill, gp_style->fill_rgba);
+ /* add some alpha to make easy the filling without hide strokes */
+ if (gpd->runtime.sfill[3] > 0.8f) {
+ gpd->runtime.sfill[3] = 0.8f;
+ }
+
+ gpd->runtime.mode = (short)gp_style->mode;
+ gpd->runtime.bstroke_style = gp_style->stroke_style;
+ gpd->runtime.bfill_style = gp_style->fill_style;
+ }
}
/* (re)init new painting data */
-static bool gp_session_initdata(bContext *C, tGPsdata *p)
+static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
{
Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *obact = CTX_data_active_object(C);
+ View3D *v3d = curarea->spacedata.first;
/* make sure the active view (at the starting time) is a 3d-view */
if (curarea == NULL) {
@@ -1406,10 +1645,12 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
}
/* pass on current scene and window */
+ p->C = C;
p->bmain = CTX_data_main(C);
p->scene = CTX_data_scene(C);
p->depsgraph = CTX_data_depsgraph(C);
p->win = CTX_wm_window(C);
+ p->disable_fill = RNA_boolean_get(op->ptr, "disable_fill");
unit_m4(p->imat);
unit_m4(p->mat);
@@ -1424,7 +1665,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* set current area
* - must verify that region data is 3D-view (and not something else)
*/
- /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
+ /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
p->sa = curarea;
p->ar = ar;
p->align_flag = &ts->gpencil_v3d_align;
@@ -1435,92 +1676,19 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable\n");
return 0;
}
- break;
- }
- case SPACE_NODE:
- {
- /* SpaceNode *snode = curarea->spacedata.first; */
-
- /* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_v2d_align;
- break;
- }
- case SPACE_SEQ:
- {
- SpaceSeq *sseq = curarea->spacedata.first;
-
- /* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_seq_align;
- /* check that gpencil data is allowed to be drawn */
- if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
- p->status = GP_STATUS_ERROR;
- if (G.debug & G_DEBUG)
- printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil\n");
- return 0;
+ /* if active object doesn't exist or isn't a GP Object, create one */
+ float *cur = ED_view3d_cursor3d_get(p->scene, v3d)->location;
+ if ((!obact) || (obact->type != OB_GPENCIL)) {
+ /* create new default object */
+ obact = ED_add_gpencil_object(C, p->scene, cur);
}
- break;
- }
- case SPACE_IMAGE:
- {
- /* SpaceImage *sima = curarea->spacedata.first; */
+ /* assign object after all checks to be sure we have one active */
+ p->ob = obact;
- /* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_ima_align;
break;
}
- case SPACE_CLIP:
- {
- SpaceClip *sc = curarea->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip == NULL) {
- p->status = GP_STATUS_ERROR;
- return false;
- }
-
- /* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
- p->align_flag = &ts->gpencil_v2d_align;
-
- invert_m4_m4(p->imat, sc->unistabmat);
-
- /* custom color for new layer */
- p->custom_color[0] = 1.0f;
- p->custom_color[1] = 0.0f;
- p->custom_color[2] = 0.5f;
- p->custom_color[3] = 0.9f;
-
- if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
- MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
-
- if (marker) {
- p->imat[3][0] -= marker->pos[0];
- p->imat[3][1] -= marker->pos[1];
- }
- else {
- p->status = GP_STATUS_ERROR;
- return false;
- }
- }
- invert_m4_m4(p->mat, p->imat);
- copy_m4_m4(p->gsc.mat, p->mat);
- break;
- }
/* unsupported views */
default:
{
@@ -1533,7 +1701,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* get gp-data */
gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
- if (gpd_ptr == NULL) {
+ if ((gpd_ptr == NULL) || ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
p->status = GP_STATUS_ERROR;
if (G.debug & G_DEBUG)
printf("Error: Current context doesn't allow for any Grease Pencil data\n");
@@ -1555,16 +1723,18 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* clear out buffer (stored in gp-data), in case something contaminated it */
gp_session_validatebuffer(p);
+
/* set brush and create a new one if null */
- gp_init_drawing_brush(ts, p);
- /* set palette info and create a new one if null */
- gp_init_palette(p);
- /* set palette colors */
- bGPDpalettecolor *palcolor = p->palettecolor;
- bGPdata *pdata = p->gpd;
- copy_v4_v4(pdata->scolor, palcolor->color);
- copy_v4_v4(pdata->sfill, palcolor->fill);
- pdata->sflag = palcolor->flag;
+ gp_init_drawing_brush(C, p);
+
+ /* setup active color */
+ if (curarea->spacetype == SPACE_VIEW3D) {
+ /* NOTE: This is only done for 3D view, as Materials aren't used for
+ * annotations in 2D editors
+ */
+ gp_init_colors(p);
+ }
+
/* lock axis */
p->lock_axis = ts->gp_sculpt.lock_axis;
@@ -1572,20 +1742,24 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
}
/* init new painting session */
-static tGPsdata *gp_session_initpaint(bContext *C)
+static tGPsdata *gp_session_initpaint(bContext *C, wmOperator *op)
{
tGPsdata *p = NULL;
- /* create new context data */
+ /* Create new context data */
p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
- gp_session_initdata(C, p);
-
- /* radius for eraser circle is defined in userprefs now */
- /* NOTE: we do this here, so that if we exit immediately,
- * erase size won't get lost
+ /* Try to initialise context data
+ * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
*/
- p->radius = U.gp_eraser;
+ if (gp_session_initdata(C, op, p) == 0) {
+ /* Invalid state - Exit
+ * NOTE: It should be safe to just free the data, since failing context checks should
+ * only happen when no data has been allocated.
+ */
+ MEM_freeN(p);
+ return NULL;
+ }
/* Random generator, only init once. */
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
@@ -1606,15 +1780,15 @@ static void gp_session_cleanup(tGPsdata *p)
return;
/* free stroke buffer */
- if (gpd->sbuffer) {
+ if (gpd->runtime.sbuffer) {
/* printf("\t\tGP - free sbuffer\n"); */
- MEM_freeN(gpd->sbuffer);
- gpd->sbuffer = NULL;
+ MEM_freeN(gpd->runtime.sbuffer);
+ gpd->runtime.sbuffer = NULL;
}
/* clear flags */
- gpd->sbuffer_size = 0;
- gpd->sbuffer_sflag = 0;
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer_sflag = 0;
p->inittime = 0.0;
}
@@ -1632,11 +1806,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
{
Scene *scene = p->scene;
ToolSettings *ts = scene->toolsettings;
+ int cfra_eval = (int)DEG_get_ctime(p->depsgraph);
/* get active layer (or add a new one if non-existent) */
p->gpl = BKE_gpencil_layer_getactive(p->gpd);
if (p->gpl == NULL) {
- p->gpl = BKE_gpencil_layer_addnew(p->gpd, "GP_Layer", true);
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
if (p->custom_color[3])
copy_v3_v3(p->gpl->color, p->custom_color);
@@ -1670,7 +1845,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
* -> If there are no strokes in that frame, don't add a new empty frame
*/
if (gpl->actframe && gpl->actframe->strokes.first) {
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_COPY);
has_layer_to_erase = true;
}
@@ -1708,7 +1883,9 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
else
add_frame_mode = GP_GETFRAME_ADD_NEW;
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_getframe(p->gpl, cfra_eval, add_frame_mode);
+ /* set as dirty draw manager cache */
+ gp_update_cache(p->gpd);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
@@ -1724,7 +1901,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* set 'eraser' for this stroke if using eraser */
p->paintmode = paintmode;
if (p->paintmode == GP_PAINTMODE_ERASER) {
- p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
/* check if we should respect depth while erasing */
if (p->sa->spacetype == SPACE_VIEW3D) {
@@ -1735,7 +1912,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
}
else {
/* disable eraser flags - so that we can switch modes during a session */
- p->gpd->sbuffer_sflag &= ~GP_STROKE_ERASER;
+ p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->gpl->flag & GP_LAYER_NO_XRAY) {
@@ -1744,10 +1921,16 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
}
}
+ /* set special fill stroke mode */
+ if (p->disable_fill == true) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_NOFILL;
+ /* replace stroke color with fill color */
+ copy_v4_v4(p->gpd->runtime.scolor, p->gpd->runtime.sfill);
+ }
+
/* set 'initial run' flag, which is only used to denote when a new stroke is starting */
p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
/* when drawing in the camera view, in 2D space, set the subrect */
p->subrect = NULL;
if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
@@ -1782,41 +1965,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
switch (p->sa->spacetype) {
case SPACE_VIEW3D:
{
- p->gpd->sbuffer_sflag |= GP_STROKE_3DSPACE;
- break;
- }
- case SPACE_NODE:
- {
- p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
- break;
- }
- case SPACE_SEQ:
- {
- p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
- break;
- }
- case SPACE_IMAGE:
- {
- SpaceImage *sima = (SpaceImage *)p->sa->spacedata.first;
-
- /* only set these flags if the image editor doesn't have an image active,
- * otherwise user will be confused by strokes not appearing after they're drawn
- *
- * Admittedly, this is a bit hacky, but it works much nicer from an ergonomic standpoint!
- */
- if (ELEM(NULL, sima, sima->image)) {
- /* make strokes be drawn in screen space */
- p->gpd->sbuffer_sflag &= ~GP_STROKE_2DSPACE;
- *(p->align_flag) &= ~GP_PROJECT_VIEWSPACE;
- }
- else {
- p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
- }
- break;
- }
- case SPACE_CLIP:
- {
- p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
break;
}
}
@@ -1839,7 +1988,7 @@ static void gp_paint_strokeend(tGPsdata *p)
}
/* check if doing eraser or not */
- if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* simplify stroke before transferring? */
gp_stroke_simplify(p);
@@ -1875,8 +2024,8 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
tGPsdata *p = (tGPsdata *)p_ptr;
if (p->paintmode == GP_PAINTMODE_ERASER) {
- Gwn_VertFormat *format = immVertexFormat();
- const uint shdr_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_smooth(true);
@@ -1920,10 +2069,12 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en
p->erasercursor = NULL;
}
else if (enable && !p->erasercursor) {
+ ED_gpencil_toggle_brush_cursor(p->C, false, NULL);
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- NULL, /* XXX */
- gpencil_draw_eraser, p);
+ p->erasercursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C),
+ NULL, /* XXX */
+ gpencil_draw_eraser, p);
}
}
@@ -1944,12 +2095,6 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
{
tGPsdata *p = op->customdata;
- /* clear undo stack */
- gpencil_undo_finish();
-
- /* restore cursor to indicate end of drawing */
- WM_cursor_modal_restore(CTX_wm_window(C));
-
/* don't assume that operator data exists at all */
if (p) {
/* check size of buffer before cleanup, to determine if anything happened here */
@@ -1962,12 +2107,38 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
* NOTE: Do this even when not in eraser mode, as eraser may
* have been toggled at some point.
*/
- U.gp_eraser = p->radius;
+ if (p->eraser) {
+ p->eraser->size = p->radius;
+ }
+
+ /* restore cursor to indicate end of drawing */
+ if (p->sa->spacetype != SPACE_VIEW3D) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ }
+ else {
+ /* or restore paint if 3D view */
+ if ((p) && (p->paintmode == GP_PAINTMODE_ERASER)) {
+ WM_cursor_modal_set(p->win, CURSOR_STD);
+ }
+
+ /* drawing batch cache is dirty now */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (gpd) {
+ gp_update_cache(gpd);
+ }
+ }
+
+ /* clear undo stack */
+ gpencil_undo_finish();
/* cleanup */
gp_paint_cleanup(p);
gp_session_cleanup(p);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+
+ /* finally, free the temp data */
gp_session_free(p);
+ p = NULL;
}
op->customdata = NULL;
@@ -1986,9 +2157,18 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p;
eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_brush_getactive_gpencil(ts);
+
+ /* if mode is draw and the brush is eraser, cancel */
+ if (paintmode != GP_PAINTMODE_ERASER) {
+ if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) {
+ return 0;
+ }
+ }
/* check context */
- p = op->customdata = gp_session_initpaint(C);
+ p = op->customdata = gp_session_initpaint(C, op);
if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
/* something wasn't set correctly in context */
gpencil_draw_exit(C, op);
@@ -2009,6 +2189,8 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
p->keymodifier = -1;
}
+ p->reports = op->reports;
+
/* everything is now setup ok */
return 1;
}
@@ -2019,10 +2201,15 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
/* ensure that the correct cursor icon is set */
static void gpencil_draw_cursor_set(tGPsdata *p)
{
- if (p->paintmode == GP_PAINTMODE_ERASER)
+ Brush *brush = p->brush;
+ if ((p->paintmode == GP_PAINTMODE_ERASER) ||
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ {
WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */
- else
- WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
+ }
+ else {
+ WM_cursor_modal_set(p->win, CURSOR_STD);
+ }
}
/* update UI indicators of status, including cursor and header prints */
@@ -2030,11 +2217,24 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
/* header prints */
switch (p->status) {
- case GP_STATUS_PAINTING:
- /* only print this for paint-sessions, otherwise it gets annoying */
- if (GPENCIL_SKETCH_SESSIONS_ON(p->scene))
- ED_workspace_status_text(C, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke"));
- break;
+
+#if 0 /* FIXME, this never runs! */
+ switch (p->paintmode) {
+ case GP_PAINTMODE_DRAW_POLY:
+ /* Provide usage tips, since this is modal, and unintuitive without hints */
+ ED_workspace_status_text(
+ C, IFACE_(
+ "Annotation Create Poly: LMB click to place next stroke vertex | "
+ "ESC/Enter to end (or click outside this area)"
+ ));
+ break;
+ default:
+ /* Do nothing - the others are self explanatory, exit quickly once the mouse is released
+ * Showing any text would just be annoying as it would flicker.
+ */
+ break;
+ }
+#endif
case GP_STATUS_IDLING:
/* print status info */
@@ -2048,12 +2248,11 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
"ESC/Enter to end (or click outside this area)"));
break;
case GP_PAINTMODE_DRAW:
- ED_workspace_status_text(C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw | "
- "E/ESC/Enter to end (or click outside this area)"));
+ ED_workspace_status_text(C, IFACE_("Grease Pencil Freehand Session: Hold and drag LMB to draw"));
break;
case GP_PAINTMODE_DRAW_POLY:
ED_workspace_status_text(C, IFACE_("Grease Pencil Poly Session: LMB click to place next stroke vertex | "
- "ESC/Enter to end (or click outside this area)"));
+ "Release Shift/ESC/Enter to end (or click outside this area)"));
break;
default: /* unhandled future cases */
@@ -2067,14 +2266,19 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
/* clear status string */
ED_workspace_status_text(C, NULL);
break;
+ case GP_STATUS_PAINTING:
+ break;
}
}
/* ------------------------------- */
/* create a new stroke point at the point indicated by the painting context */
-static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
+static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
{
+ bGPdata *gpd = p->gpd;
+ tGPspoint *pt = NULL;
+
/* handle drawing/erasing -> test for erasing first */
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* do 'live' erasing now */
@@ -2087,6 +2291,17 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
}
/* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */
else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
+
+ /* if lazy mouse, interpolate the last and current mouse positions */
+ if (GPENCIL_LAZY_MODE(p->brush, p->shift)) {
+ float now_mouse[2];
+ float last_mouse[2];
+ copy_v2fl_v2i(now_mouse, p->mval);
+ copy_v2fl_v2i(last_mouse, p->mvalo);
+ interp_v2_v2v2(now_mouse, now_mouse, last_mouse, p->brush->smooth_stroke_factor);
+ round_v2i_v2fl(p->mval, now_mouse);
+ }
+
/* try to add point */
short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
@@ -2124,11 +2339,24 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
p->mvalo[1] = p->mval[1];
p->opressure = p->pressure;
p->ocurtime = p->curtime;
+
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
+ }
+ }
+ else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) &&
+ (gpd->runtime.sbuffer_size > 0))
+ {
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
+ }
}
}
/* handle draw event */
-static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsgraph *depsgraph)
+static void gpencil_draw_apply_event(bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, int x, int y)
{
tGPsdata *p = op->customdata;
PointerRNA itemptr;
@@ -2136,13 +2364,15 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
int tablet = 0;
/* convert from window-space to area-space mouse coordinates
+ * add any x,y override position for fake events
* NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding...
*/
- p->mval[0] = event->mval[0] + 1;
- p->mval[1] = event->mval[1] + 1;
+ p->mval[0] = event->mval[0] + 1 - x;
+ p->mval[1] = event->mval[1] + 1 - y;
+ p->shift = event->shift;
/* verify key status for straight lines */
- if ((event->ctrl > 0) || (event->alt > 0)) {
+ if ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false)) {
if (p->straight[0] == 0) {
int dx = abs(p->mval[0] - p->mvalo[0]);
int dy = abs(p->mval[1] - p->mvalo[1]);
@@ -2151,12 +2381,12 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
if (dx >= dy) {
/* horizontal */
p->straight[0] = 1;
- p->straight[1] = p->mval[1]; /* save y */
+ p->straight[1] = (short)p->mval[1]; /* save y */
}
else {
/* vertical */
p->straight[0] = 2;
- p->straight[1] = p->mval[0]; /* save x */
+ p->straight[1] = (short)p->mval[0]; /* save x */
}
}
}
@@ -2191,6 +2421,22 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
p->pressure = 1.0f;
}
+ /* special eraser modes */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ if (event->shift > 0) {
+ p->flags |= GP_PAINTFLAG_HARD_ERASER;
+ }
+ else {
+ p->flags &= ~GP_PAINTFLAG_HARD_ERASER;
+ }
+ if (event->alt > 0) {
+ p->flags |= GP_PAINTFLAG_STROKE_ERASER;
+ }
+ else {
+ p->flags &= ~GP_PAINTFLAG_STROKE_ERASER;
+ }
+ }
+
/* special exception for start of strokes (i.e. maybe for just a dot) */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
@@ -2233,7 +2479,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsg
RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
/* apply the current latest drawing point */
- gpencil_draw_apply(op, p, depsgraph);
+ gpencil_draw_apply(C, op, p, depsgraph);
/* force refresh */
ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
@@ -2251,7 +2497,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op, NULL)) {
- if (op->customdata) MEM_freeN(op->customdata);
+ MEM_SAFE_FREE(op->customdata);
/* printf("\tGP - no valid data\n"); */
return OPERATOR_CANCELLED;
}
@@ -2298,7 +2544,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
}
/* apply this data as necessary now (as per usual) */
- gpencil_draw_apply(op, p, depsgraph);
+ gpencil_draw_apply(C, op, p, depsgraph);
}
RNA_END;
@@ -2324,6 +2570,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
if (G.debug & G_DEBUG)
printf("GPencil - Starting Drawing\n");
+ /* support for tablets eraser pen */
+ if (gpencil_is_tablet_eraser_active(event)) {
+ RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
+ }
+
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op, event)) {
if (op->customdata)
@@ -2344,6 +2595,9 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
}
+ else {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
/* set cursor
* NOTE: This may change later (i.e. intentionally via brush toggle,
* or unintentionally if the user scrolls outside the area)...
@@ -2357,7 +2611,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), 0, 0);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
else {
@@ -2366,9 +2620,29 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
+ /* enable paint mode */
+ if (p->sa->spacetype == SPACE_VIEW3D) {
+ Object *ob = CTX_data_active_object(C);
+ if (ob && (ob->type == OB_GPENCIL) && ((p->gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)) {
+ /* Just set paintmode flag... */
+ p->gpd->flag |= GP_DATA_STROKE_PAINTMODE;
+ /* disable other GP modes */
+ p->gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ p->gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ p->gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ /* set workspace mode */
+ ob->restore_mode = ob->mode;
+ ob->mode = OB_MODE_GPENCIL_PAINT;
+ /* redraw mode on screen */
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+ }
+ }
+
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
/* add a modal handler for this operator, so that we can then draw continuous strokes */
WM_event_add_modal_handler(C, op);
+
return OPERATOR_RUNNING_MODAL;
}
@@ -2397,7 +2671,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
/* XXX: watch it with the paintmode! in future,
* it'd be nice to allow changing paint-mode when in sketching-sessions */
- if (gp_session_initdata(C, p))
+ if (gp_session_initdata(C, op, p))
gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
if (p->status != GP_STATUS_ERROR) {
@@ -2448,6 +2722,76 @@ static void gpencil_move_last_stroke_to_back(bContext *C)
BLI_insertlinkbefore(&gpf->strokes, gpf->strokes.first, gps);
}
+/* add events for missing mouse movements when the artist draw very fast */
+static void gpencil_add_missing_events(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p)
+{
+ Brush *brush = p->brush;
+ if (brush->gpencil_settings->input_samples == 0) {
+ return;
+ }
+ RegionView3D *rv3d = p->ar->regiondata;
+ float defaultpixsize = rv3d->pixsize * 1000.0f;
+ int samples = (GP_MAX_INPUT_SAMPLES - brush->gpencil_settings->input_samples + 1);
+ float thickness = (float)brush->size;
+
+ float pt[2], a[2], b[2];
+ float vec[3];
+ float scale = 1.0f;
+
+ /* get pixel scale */
+ gp_get_3d_reference(p, vec);
+ mul_m4_v3(rv3d->persmat, vec);
+ if (rv3d->is_persp) {
+ scale = vec[2] * defaultpixsize;
+ }
+ else {
+ scale = defaultpixsize;
+ }
+
+ /* The thickness of the brush is reduced of thickness to get overlap dots */
+ float dot_factor = 0.50f;
+ if (samples < 2) {
+ dot_factor = 0.05f;
+ }
+ else if (samples < 4) {
+ dot_factor = 0.10f;
+ }
+ else if (samples < 7) {
+ dot_factor = 0.3f;
+ }
+ else if (samples < 10) {
+ dot_factor = 0.4f;
+ }
+ float factor = ((thickness * dot_factor) / scale) * samples;
+
+ copy_v2fl_v2i(a, p->mvalo);
+ b[0] = event->mval[0] + 1;
+ b[1] = event->mval[1] + 1;
+
+ /* get distance in pixels */
+ float dist = len_v2v2(a, b);
+
+ /* for very small distances, add a half way point */
+ if (dist <= 2.0f) {
+ interp_v2_v2v2(pt, a, b, 0.5f);
+ sub_v2_v2v2(pt, b, pt);
+ /* create fake event */
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C),
+ (int)pt[0], (int)pt[1]);
+ }
+ else if (dist >= factor) {
+ int slices = 2 + (int)((dist - 1.0) / factor);
+ float n = 1.0f / slices;
+ for (int i = 1; i < slices; i++) {
+ interp_v2_v2v2(pt, a, b, n * i);
+ sub_v2_v2v2(pt, b, pt);
+ /* create fake event */
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C),
+ (int)pt[0], (int)pt[1]);
+ }
+ }
+}
+
/* events handling during interactive drawing part of operator */
static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -2488,10 +2832,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((ELEM(event->type, p->keymodifier)) && (event->val == KM_RELEASE)) {
- /* enable continuous if release D key in mid drawing */
- p->scene->toolsettings->gpencil_flags |= GP_TOOL_FLAG_PAINTSESSIONS_ON;
- }
else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
/* Add Blank Frame
* - Since this operator is non-modal, we can just call it here, and keep going...
@@ -2510,7 +2850,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* exit painting mode (and/or end current stroke)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
*/
- if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) {
+ /* if polyline and release shift must cancel */
+ if ((ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) ||
+ ((p->paintmode == GP_PAINTMODE_DRAW_POLY) && (event->shift == 0)))
+ {
/* exit() ends the current stroke before cleaning up */
/* printf("\t\tGP - end of paint op + end of stroke\n"); */
/* if drawing polygon and enable on back, must move stroke */
@@ -2537,10 +2880,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
int sketch = 0;
/* basically, this should be mouse-button up = end stroke
- * BUT what happens next depends on whether we 'painting sessions' is enabled
+ * BUT, polyline drawing is an exception -- all knots should be added during one session
*/
- sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene);
- /* polyline drawing is also 'sketching' -- all knots should be added during one session */
sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY);
if (sketch) {
@@ -2585,6 +2926,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
+ /* drawing batch cache is dirty now */
+ gp_update_cache(p->gpd);
+
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
@@ -2689,7 +3033,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
/* handle drawing event */
/* printf("\t\tGP - add point\n"); */
- gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
+ gpencil_add_missing_events(C, op, event, p);
+
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph(C), 0, 0);
/* finish painting operation if anything went wrong just now */
if (p->status == GP_STATUS_ERROR) {
@@ -2791,7 +3137,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
/* identifiers */
ot->name = "Grease Pencil Draw";
ot->idname = "GPENCIL_OT_draw";
- ot->description = "Make annotations on the active data";
+ ot->description = "Draw a new stroke in the active Grease Pencil Object";
/* api callbacks */
ot->exec = gpencil_draw_exec;
@@ -2811,5 +3157,11 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
/* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "disable_straight", false, "No Straight lines", "Disable key for straight lines");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "disable_fill", false, "No Fill Areas", "Disable fill to use stroke as fill boundary");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
new file mode 100644
index 00000000000..2dfdeeba0b6
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -0,0 +1,716 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for creating new Grease Pencil primitives (boxes, circles, ...)
+ */
+
+/** \file blender/editors/gpencil/gpencil_primitive.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_main.h"
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "ED_gpencil.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_space_api.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+#define MIN_EDGES 2
+#define MAX_EDGES 100
+
+#define IDLE 0
+#define IN_PROGRESS 1
+
+/* ************************************************ */
+/* Core/Shared Utilities */
+
+/* Poll callback for primitive operators */
+static bool gpencil_primitive_add_poll(bContext *C)
+{
+ /* only 3D view */
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
+ return 0;
+ }
+
+ /* need data to create primitive */
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (gpd == NULL) {
+ return 0;
+ }
+
+ /* only in edit and paint modes
+ * - paint as it's the "drawing/creation mode"
+ * - edit as this is more of an atomic editing operation
+ * (similar to copy/paste), and also for consistency
+ */
+ if ((gpd->flag & (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE)) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Primitives can only be added in Draw or Edit modes");
+ return 0;
+ }
+
+ /* don't allow operator to function if the active layer is locked/hidden
+ * (BUT, if there isn't an active layer, we are free to add new layer when the time comes)
+ */
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ if ((gpl) && (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE))) {
+ CTX_wm_operator_poll_msg_set(C, "Primitives cannot be added as active layer is locked or hidden");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/* ****************** Primitive Interactive *********************** */
+
+/* Helper: Create internal strokes primitives data */
+static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ Brush *brush;
+
+ /* if brush doesn't exist, create a new one */
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ brush = BKE_brush_getactive_gpencil(ts);
+ }
+ else {
+ /* Use the current */
+ brush = BKE_brush_getactive_gpencil(ts);
+ }
+ tgpi->brush = brush;
+
+ /* if layer doesn't exist, create a new one */
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true);
+ }
+ tgpi->gpl = gpl;
+
+ /* create a new temporary frame */
+ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe");
+ tgpi->gpf->framenum = tgpi->cframe = cfra_eval;
+
+ /* create new temp stroke */
+ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke");
+ gps->thickness = 2.0f;
+ gps->inittime = 0.0f;
+
+ /* enable recalculation flag by default */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ /* the polygon must be closed, so enabled cyclic */
+ gps->flag |= GP_STROKE_CYCLIC;
+ gps->flag |= GP_STROKE_3DSPACE;
+
+ gps->mat_nr = BKE_gpencil_get_material_index(tgpi->ob, tgpi->mat) - 1;
+
+ /* allocate memory for storage points, but keep empty */
+ gps->totpoints = 0;
+ gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert), "gp_stroke_weights");
+ /* initialize triangle memory to dummy data */
+ gps->tot_triangles = 0;
+ gps->triangles = NULL;
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* add to strokes */
+ BLI_addtail(&tgpi->gpf->strokes, gps);
+}
+
+/* ----------------------- */
+/* Drawing Callbacks */
+
+/* Drawing callback for modal operator in 3d mode */
+static void gpencil_primitive_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
+{
+ tGPDprimitive *tgpi = (tGPDprimitive *)arg;
+ ED_gp_draw_primitives(C, tgpi, REGION_DRAW_POST_VIEW);
+}
+
+/* ----------------------- */
+
+/* Helper: Draw status message while the user is running the operator */
+static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi)
+{
+ Scene *scene = tgpi->scene;
+ char status_str[UI_MAX_DRAW_STR];
+ char msg_str[UI_MAX_DRAW_STR];
+
+ if (tgpi->type == GP_STROKE_BOX) {
+ BLI_strncpy(msg_str, IFACE_("Rectangle: ESC/RMB to cancel, LMB set origin, Enter/LMB to confirm, Shift to square"), UI_MAX_DRAW_STR);
+ }
+ else if (tgpi->type == GP_STROKE_LINE) {
+ BLI_strncpy(msg_str, IFACE_("Line: ESC/RMB to cancel, LMB set origin, Enter/LMB to confirm"), UI_MAX_DRAW_STR);
+ }
+ else {
+ BLI_strncpy(msg_str, IFACE_("Circle: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL to adjust edge number, Shift to square"), UI_MAX_DRAW_STR);
+ }
+
+ if (tgpi->type == GP_STROKE_CIRCLE) {
+ if (hasNumInput(&tgpi->num)) {
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&tgpi->num, str_offs, &scene->unit);
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs);
+ }
+ else {
+ if (tgpi->flag == IN_PROGRESS) {
+ BLI_snprintf(
+ status_str, sizeof(status_str), "%s: %d (%d, %d) (%d, %d)", msg_str, (int)tgpi->tot_edges,
+ tgpi->top[0], tgpi->top[1], tgpi->bottom[0], tgpi->bottom[1]);
+ }
+ else {
+ BLI_snprintf(
+ status_str, sizeof(status_str), "%s: %d (%d, %d)", msg_str, (int)tgpi->tot_edges,
+ tgpi->bottom[0], tgpi->bottom[1]);
+ }
+ }
+ }
+ else {
+ if (tgpi->flag == IN_PROGRESS) {
+ BLI_snprintf(
+ status_str, sizeof(status_str), "%s: (%d, %d) (%d, %d)", msg_str,
+ tgpi->top[0], tgpi->top[1], tgpi->bottom[0], tgpi->bottom[1]);
+ }
+ else {
+ BLI_snprintf(
+ status_str, sizeof(status_str), "%s: (%d, %d)", msg_str,
+ tgpi->bottom[0], tgpi->bottom[1]);
+ }
+ }
+ ED_workspace_status_text(C, status_str);
+}
+
+/* ----------------------- */
+
+/* create a rectangle */
+static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D)
+{
+ BLI_assert(tgpi->tot_edges == 4);
+
+ points2D[0].x = tgpi->top[0];
+ points2D[0].y = tgpi->top[1];
+
+ points2D[1].x = tgpi->bottom[0];
+ points2D[1].y = tgpi->top[1];
+
+ points2D[2].x = tgpi->bottom[0];
+ points2D[2].y = tgpi->bottom[1];
+
+ points2D[3].x = tgpi->top[0];
+ points2D[3].y = tgpi->bottom[1];
+}
+
+/* create a line */
+static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D)
+{
+ BLI_assert(tgpi->tot_edges == 2);
+
+ points2D[0].x = tgpi->top[0];
+ points2D[0].y = tgpi->top[1];
+
+ points2D[1].x = tgpi->bottom[0];
+ points2D[1].y = tgpi->bottom[1];
+}
+
+/* create a circle */
+static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
+{
+ const int totpoints = tgpi->tot_edges;
+ const float step = (2.0f * M_PI) / (float)(totpoints);
+ float center[2];
+ float radius[2];
+ float a = 0.0f;
+
+ /* TODO: Use math-lib functions for these? */
+ center[0] = tgpi->top[0] + ((tgpi->bottom[0] - tgpi->top[0]) / 2.0f);
+ center[1] = tgpi->top[1] + ((tgpi->bottom[1] - tgpi->top[1]) / 2.0f);
+ radius[0] = fabsf(((tgpi->bottom[0] - tgpi->top[0]) / 2.0f));
+ radius[1] = fabsf(((tgpi->bottom[1] - tgpi->top[1]) / 2.0f));
+
+ for (int i = 0; i < totpoints; i++) {
+ tGPspoint *p2d = &points2D[i];
+
+ p2d->x = (int)(center[0] + cosf(a) * radius[0]);
+ p2d->y = (int)(center[1] + sinf(a) * radius[1]);
+ a += step;
+ }
+}
+
+/* Helper: Update shape of the stroke */
+static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
+{
+ ToolSettings *ts = tgpi->scene->toolsettings;
+ bGPdata *gpd = tgpi->gpd;
+ bGPDstroke *gps = tgpi->gpf->strokes.first;
+
+ /* realloc points to new size */
+ /* TODO: only do this if the size has changed? */
+ gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * tgpi->tot_edges);
+ gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * tgpi->tot_edges);
+ gps->totpoints = tgpi->tot_edges;
+
+ /* compute screen-space coordinates for points */
+ tGPspoint *points2D = MEM_callocN(sizeof(tGPspoint) * tgpi->tot_edges, "gp primitive points2D");
+ switch (tgpi->type) {
+ case GP_STROKE_BOX:
+ gp_primitive_rectangle(tgpi, points2D);
+ break;
+ case GP_STROKE_LINE:
+ gp_primitive_line(tgpi, points2D);
+ break;
+ case GP_STROKE_CIRCLE:
+ gp_primitive_circle(tgpi, points2D);
+ break;
+ default:
+ break;
+ }
+
+ /* convert screen-coordinates to 3D coordinates */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+ tGPspoint *p2d = &points2D[i];
+
+
+ /* convert screen-coordinates to 3D coordinates */
+ gp_stroke_convertcoords_tpoint(tgpi->scene, tgpi->ar, tgpi->v3d, tgpi->ob, tgpi->gpl, p2d, NULL, &pt->x);
+
+ pt->pressure = 1.0f;
+ pt->strength = tgpi->brush->gpencil_settings->draw_strength;
+ pt->time = 0.0f;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
+ }
+
+ /* if axis locked, reproject to plane locked */
+ if (tgpi->lock_axis > GP_LOCKAXIS_NONE) {
+ bGPDspoint *tpt = gps->points;
+ float origin[3];
+ ED_gp_get_drawing_reference(tgpi->v3d, tgpi->scene, tgpi->ob, tgpi->gpl,
+ ts->gpencil_v3d_align, origin);
+
+ for (int i = 0; i < gps->totpoints; i++, tpt++) {
+ ED_gp_project_point_to_plane(tgpi->ob, tgpi->rv3d, origin,
+ ts->gp_sculpt.lock_axis - 1,
+ tpt);
+ }
+ }
+
+ /* if parented change position relative to parent object */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ gp_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpd, tgpi->gpl, pt);
+ }
+
+ /* force fill recalc */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* free temp data */
+ MEM_SAFE_FREE(points2D);
+
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+}
+
+/* Update screen and stroke */
+static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive *tgpi)
+{
+ /* update indicator in header */
+ gpencil_primitive_status_indicators(C, tgpi);
+ /* apply... */
+ tgpi->type = RNA_enum_get(op->ptr, "type");
+ tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
+ /* update points position */
+ gp_primitive_update_strokes(C, tgpi);
+}
+
+/* ----------------------- */
+
+/* Exit and free memory */
+static void gpencil_primitive_exit(bContext *C, wmOperator *op)
+{
+ tGPDprimitive *tgpi = op->customdata;
+ bGPdata *gpd = tgpi->gpd;
+
+ /* don't assume that operator data exists at all */
+ if (tgpi) {
+ /* remove drawing handler */
+ if (tgpi->draw_handle_3d) {
+ ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
+ }
+
+ /* clear status message area */
+ ED_workspace_status_text(C, NULL);
+
+ /* finally, free memory used by temp data */
+ BKE_gpencil_free_strokes(tgpi->gpf);
+ MEM_freeN(tgpi->gpf);
+ MEM_freeN(tgpi);
+ }
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* clear pointer */
+ op->customdata = NULL;
+}
+
+/* Init new temporary primitive data */
+static void gpencil_primitive_init(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ /* create temporary operator data */
+ tGPDprimitive *tgpi = MEM_callocN(sizeof(tGPDprimitive), "GPencil Primitive Data");
+ op->customdata = tgpi;
+
+ /* set current scene and window info */
+ tgpi->scene = scene;
+ tgpi->ob = CTX_data_active_object(C);
+ tgpi->sa = CTX_wm_area(C);
+ tgpi->ar = CTX_wm_region(C);
+ tgpi->rv3d = tgpi->ar->regiondata;
+ tgpi->v3d = tgpi->sa->spacedata.first;
+ tgpi->depsgraph = CTX_data_depsgraph(C);
+ tgpi->win = CTX_wm_window(C);
+
+ /* set current frame number */
+ tgpi->cframe = cfra_eval;
+
+ /* set GP datablock */
+ tgpi->gpd = gpd;
+
+ /* getcolor info */
+ tgpi->mat = BKE_gpencil_material_ensure(bmain, tgpi->ob);
+
+ /* set parameters */
+ tgpi->type = RNA_enum_get(op->ptr, "type");
+
+ /* if circle set default to 32 */
+ if (tgpi->type == GP_STROKE_CIRCLE) {
+ RNA_int_set(op->ptr, "edges", 32);
+ }
+ else if (tgpi->type == GP_STROKE_BOX) {
+ RNA_int_set(op->ptr, "edges", 4);
+ }
+ else { /* LINE */
+ RNA_int_set(op->ptr, "edges", 2);
+ }
+
+ tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
+ tgpi->flag = IDLE;
+
+ tgpi->lock_axis = ts->gp_sculpt.lock_axis;
+
+ /* set temp layer, frame and stroke */
+ gp_primitive_set_initdata(C, tgpi);
+}
+
+/* ----------------------- */
+
+/* Invoke handler: Initialize the operator */
+static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wmWindow *win = CTX_wm_window(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ tGPDprimitive *tgpi = NULL;
+
+ /* initialize operator runtime data */
+ gpencil_primitive_init(C, op);
+ tgpi = op->customdata;
+
+ /* if in tools region, wait till we get to the main (3d-space)
+ * region before allowing drawing to take place.
+ */
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
+ /* Enable custom drawing handlers */
+ tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_primitive_draw_3d, tgpi, REGION_DRAW_POST_VIEW);
+
+ /* set cursor to indicate modal */
+ WM_cursor_modal_set(win, BC_CROSSCURSOR);
+
+ /* update sindicator in header */
+ gpencil_primitive_status_indicators(C, tgpi);
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Helper to complete a primitive */
+static void gpencil_primitive_done(bContext *C, wmOperator *op, wmWindow *win, tGPDprimitive *tgpi)
+{
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+
+ /* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* insert keyframes as required... */
+ gpf = BKE_gpencil_layer_getframe(tgpi->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
+
+ /* prepare stroke to get transfered */
+ gps = tgpi->gpf->strokes.first;
+ if (gps) {
+ gps->thickness = tgpi->brush->size;
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ }
+
+ /* transfer stroke from temporary buffer to the actual frame */
+ BLI_movelisttolist(&gpf->strokes, &tgpi->gpf->strokes);
+ BLI_assert(BLI_listbase_is_empty(&tgpi->gpf->strokes));
+
+ /* clean up temp data */
+ gpencil_primitive_exit(C, op);
+}
+
+/* Modal handler: Events handling during interactive part */
+static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGPDprimitive *tgpi = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ const bool has_numinput = hasNumInput(&tgpi->num);
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if ((event->val == KM_PRESS) && (tgpi->flag == IDLE)) {
+ /* start drawing primitive */
+ /* TODO: Ignore if not in main region yet */
+ tgpi->flag = IN_PROGRESS;
+
+ tgpi->top[0] = event->mval[0];
+ tgpi->top[1] = event->mval[1];
+
+ tgpi->bottom[0] = event->mval[0];
+ tgpi->bottom[1] = event->mval[1];
+ }
+ else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
+ /* stop drawing primitive */
+ tgpi->flag = IDLE;
+ gpencil_primitive_done(C, op, win, tgpi);
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ if (G.debug & G_DEBUG) {
+ printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag);
+ }
+ }
+ break;
+ case RETKEY: /* confirm */
+ {
+ tgpi->flag = IDLE;
+ gpencil_primitive_done(C, op, win, tgpi);
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY: /* cancel */
+ case RIGHTMOUSE:
+ {
+ /* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* clean up temp data */
+ gpencil_primitive_exit(C, op);
+
+ /* canceled! */
+ return OPERATOR_CANCELLED;
+ }
+
+ case WHEELUPMOUSE:
+ {
+ if (tgpi->type == GP_STROKE_CIRCLE) {
+ tgpi->tot_edges = tgpi->tot_edges + 1;
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case WHEELDOWNMOUSE:
+ {
+ if (tgpi->type == GP_STROKE_CIRCLE) {
+ tgpi->tot_edges = tgpi->tot_edges - 1;
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ case MOUSEMOVE: /* calculate new position */
+ {
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* update position of mouse */
+ tgpi->bottom[0] = event->mval[0];
+ tgpi->bottom[1] = event->mval[1];
+ if (tgpi->flag == IDLE) {
+ tgpi->top[0] = event->mval[0];
+ tgpi->top[1] = event->mval[1];
+ }
+ /* Keep square if shift key */
+ if (event->shift) {
+ tgpi->bottom[1] = tgpi->top[1] - (tgpi->bottom[0] - tgpi->top[0]);
+ }
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+ }
+ break;
+ }
+ default:
+ {
+ if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
+ float value;
+
+ /* Grab data from numeric input, and store this new value (the user see an int) */
+ value = tgpi->tot_edges;
+ applyNumInput(&tgpi->num, &value);
+ tgpi->tot_edges = value;
+
+ CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
+ RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
+
+ /* update screen */
+ gpencil_primitive_update(C, op, tgpi);
+
+ break;
+ }
+ else {
+ /* unhandled event - allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
+ }
+ }
+
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Cancel handler */
+static void gpencil_primitive_cancel(bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ gpencil_primitive_exit(C, op);
+}
+
+void GPENCIL_OT_primitive(wmOperatorType *ot)
+{
+ static EnumPropertyItem primitive_type[] = {
+ { GP_STROKE_BOX, "BOX", 0, "Box", "" },
+ { GP_STROKE_LINE, "LINE", 0, "Line", "" },
+ { GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", "" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* identifiers */
+ ot->name = "Grease Pencil Shapes";
+ ot->idname = "GPENCIL_OT_primitive";
+ ot->description = "Create predefined grease pencil stroke shapes";
+
+ /* callbacks */
+ ot->invoke = gpencil_primitive_invoke;
+ ot->modal = gpencil_primitive_modal;
+ ot->cancel = gpencil_primitive_cancel;
+ ot->poll = gpencil_primitive_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ RNA_def_int(ot->srna, "edges", 4, MIN_EDGES, MAX_EDGES, "Edges", "Number of polygon edges", MIN_EDGES, MAX_EDGES);
+ RNA_def_enum(ot->srna, "type", primitive_type, GP_STROKE_BOX, "Type", "Type of shape");
+}
+
+/* *************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index dd556e99264..3e0caa8d5d8 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -43,6 +43,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_object_types.h"
@@ -62,6 +63,9 @@
#include "ED_gpencil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* ********************************************** */
@@ -71,8 +75,8 @@ static bool gpencil_select_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- /* we just need some visible strokes, and to be in editmode */
- if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
+ /* we just need some visible strokes, and to be in editmode or other modes only to catch event */
+ if (GPENCIL_ANY_MODE(gpd)) {
/* TODO: include a check for visible strokes? */
if (gpd->layers.first)
return true;
@@ -94,6 +98,11 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
/* for "toggle", test for existing selected strokes */
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
@@ -180,6 +189,11 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
}
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -213,6 +227,11 @@ static int gpencil_select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
/* select all points in selected strokes */
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
@@ -228,6 +247,11 @@ static int gpencil_select_linked_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -248,6 +272,86 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot)
}
/* ********************************************** */
+/* Select Alternate */
+
+static int gpencil_select_alternate_exec(bContext *C, wmOperator *op)
+{
+ const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* select all points in selected strokes */
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
+ bGPDspoint *pt;
+ int row = 0;
+ int start = 0;
+ if (unselect_ends) {
+ start = 1;
+ }
+
+ for (int i = start; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ if ((row % 2) == 0) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ row++;
+ }
+
+ /* unselect start and end points */
+ if (unselect_ends) {
+ pt = &gps->points[0];
+ pt->flag &= ~GP_SPOINT_SELECT;
+
+ pt = &gps->points[gps->totpoints - 1];
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_alternate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Alternated";
+ ot->idname = "GPENCIL_OT_select_alternate";
+ ot->description = "Select alternative points in same strokes as already selected points";
+
+ /* callbacks */
+ ot->exec = gpencil_select_alternate_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "unselect_ends", true, "Unselect Ends", "Do not select the first and last point of the stroke");
+}
+
+/* ********************************************** */
/* Select Grouped */
typedef enum eGP_SelectGrouped {
@@ -266,11 +370,12 @@ typedef enum eGP_SelectGrouped {
/* On each visible layer, check for selected strokes - if found, select all others */
static void gp_select_same_layer(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, 0);
bGPDstroke *gps;
bool found = false;
@@ -309,10 +414,7 @@ static void gp_select_same_layer(bContext *C)
/* Select all strokes with same colors as selected ones */
static void gp_select_same_color(bContext *C)
{
- /* First, build set containing all the colors of selected strokes
- * - We use the palette names, so that we can select all strokes with one
- * (potentially missing) color, and remap them to something else
- */
+ /* First, build set containing all the colors of selected strokes */
GSet *selected_colors = BLI_gset_str_new("GP Selected Colors");
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
@@ -321,7 +423,7 @@ static void gp_select_same_color(bContext *C)
/* add instead of insert here, otherwise the uniqueness check gets skipped,
* and we get many duplicate entries...
*/
- BLI_gset_add(selected_colors, gps->colorname);
+ BLI_gset_add(selected_colors, &gps->mat_nr);
}
}
CTX_DATA_END;
@@ -329,7 +431,7 @@ static void gp_select_same_color(bContext *C)
/* Second, select any visible stroke that uses these colors */
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
- if (BLI_gset_haskey(selected_colors, gps->colorname)) {
+ if (BLI_gset_haskey(selected_colors, &gps->mat_nr)) {
/* select this stroke */
bGPDspoint *pt;
int i;
@@ -342,6 +444,11 @@ static void gp_select_same_color(bContext *C)
}
}
CTX_DATA_END;
+
+ /* free memomy */
+ if (selected_colors != NULL) {
+ BLI_gset_free(selected_colors, NULL);
+ }
}
@@ -350,6 +457,11 @@ static void gp_select_same_color(bContext *C)
static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
{
eGP_SelectGrouped mode = RNA_enum_get(op->ptr, "type");
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
switch (mode) {
case GP_SEL_SAME_LAYER:
@@ -365,6 +477,11 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
}
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -399,6 +516,12 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot)
static int gpencil_select_first_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
const bool extend = RNA_boolean_get(op->ptr, "extend");
@@ -429,6 +552,11 @@ static int gpencil_select_first_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -459,6 +587,12 @@ void GPENCIL_OT_select_first(wmOperatorType *ot)
static int gpencil_select_last_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes");
const bool extend = RNA_boolean_get(op->ptr, "extend");
@@ -489,6 +623,11 @@ static int gpencil_select_last_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -519,6 +658,12 @@ void GPENCIL_OT_select_last(wmOperatorType *ot)
static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
if (gps->flag & GP_STROKE_SELECT) {
@@ -565,6 +710,11 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -589,6 +739,12 @@ void GPENCIL_OT_select_more(wmOperatorType *ot)
static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
if (gps->flag & GP_STROKE_SELECT) {
@@ -636,6 +792,11 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* updates */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -665,7 +826,7 @@ void GPENCIL_OT_select_less(wmOperatorType *ot)
static bool gp_stroke_do_circle_sel(
bGPDstroke *gps, GP_SpaceConversion *gsc,
const int mx, const int my, const int radius,
- const bool select, rcti *rect, const bool parented, float diff_mat[4][4])
+ const bool select, rcti *rect, float diff_mat[4][4])
{
bGPDspoint *pt1, *pt2;
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
@@ -673,14 +834,9 @@ static bool gp_stroke_do_circle_sel(
bool changed = false;
if (gps->totpoints == 1) {
- if (!parented) {
- gp_point_to_xy(gsc, gps, gps->points, &x0, &y0);
- }
- else {
- bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0);
- }
+ bGPDspoint pt_temp;
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0);
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) {
@@ -708,18 +864,12 @@ static bool gp_stroke_do_circle_sel(
/* get points to work with */
pt1 = gps->points + i;
pt2 = gps->points + i + 1;
- if (!parented) {
- gp_point_to_xy(gsc, gps, pt1, &x0, &y0);
- gp_point_to_xy(gsc, gps, pt2, &x1, &y1);
- }
- else {
- bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &x0, &y0);
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &x0, &y0);
- gp_point_to_parent_space(pt2, diff_mat, &npt);
- gp_point_to_xy(gsc, gps, &npt, &x1, &y1);
- }
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &x1, &y1);
/* check that point segment of the boundbox of the selection stroke */
if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
@@ -763,6 +913,12 @@ static bool gp_stroke_do_circle_sel(
static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ /* if not edit/sculpt mode, the event is catched but not processed */
+ if (GPENCIL_NONE_EDIT_MODE(gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
ScrArea *sa = CTX_wm_area(C);
const int mx = RNA_int_get(op->ptr, "x");
@@ -798,13 +954,17 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
{
changed |= gp_stroke_do_circle_sel(
- gps, &gsc, mx, my, radius, select, &rect,
- (gpl->parent != NULL), diff_mat);
+ gps, &gsc, mx, my, radius, select, &rect, diff_mat);
}
GP_EDITABLE_STROKES_END;
/* updates */
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
@@ -826,7 +986,7 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
ot->cancel = WM_gesture_circle_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
WM_operator_properties_gesture_circle_select(ot);
@@ -837,10 +997,11 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
static int gpencil_border_select_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
ScrArea *sa = CTX_wm_area(C);
const bool select = !RNA_boolean_get(op->ptr, "deselect");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend") && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0);
GP_SpaceConversion gsc = {NULL};
rcti rect = {0};
@@ -888,14 +1049,9 @@ static int gpencil_border_select_exec(bContext *C, wmOperator *op)
int x0, y0;
/* convert point coords to screenspace */
- if (gpl->parent == NULL) {
- gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
- }
- else {
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy(&gsc, gps, &pt2, &x0, &y0);
- }
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(&gsc, gps, &pt2, &x0, &y0);
/* test if in selection rect */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0)) {
@@ -915,8 +1071,20 @@ static int gpencil_border_select_exec(bContext *C, wmOperator *op)
}
GP_EDITABLE_STROKES_END;
+ /* if paint mode,delete selected points */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ gp_delete_selected_point_wrap(C);
+ changed = true;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+
/* updates */
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
@@ -939,7 +1107,7 @@ void GPENCIL_OT_select_border(wmOperatorType *ot)
ot->poll = gpencil_select_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* rna */
WM_operator_properties_gesture_border_select(ot);
@@ -950,10 +1118,11 @@ void GPENCIL_OT_select_border(wmOperatorType *ot)
static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
GP_SpaceConversion gsc = {NULL};
rcti rect = {0};
- const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend") && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0);
const bool select = !RNA_boolean_get(op->ptr, "deselect");
int mcords_tot;
@@ -997,14 +1166,9 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
int x0, y0;
/* convert point coords to screenspace */
- if (gpl->parent == NULL) {
- gp_point_to_xy(&gsc, gps, pt, &x0, &y0);
- }
- else {
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy(&gsc, gps, &pt2, &x0, &y0);
- }
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(&gsc, gps, &pt2, &x0, &y0);
/* test if in lasso boundbox + within the lasso noose */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0) &&
BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX))
@@ -1028,8 +1192,20 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
/* cleanup */
MEM_freeN((void *)mcords);
+ /* if paint mode,delete selected points */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ gp_delete_selected_point_wrap(C);
+ changed = true;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+
/* updates */
if (changed) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
@@ -1049,7 +1225,7 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot)
ot->cancel = WM_gesture_lasso_cancel;
/* flags */
- ot->flag = OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
WM_operator_properties_gesture_lasso_select(ot);
@@ -1061,6 +1237,7 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot)
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
/* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
const float radius = 0.75f * U.widget_unit;
@@ -1102,14 +1279,9 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
int xy[2];
- if (gpl->parent == NULL) {
- gp_point_to_xy(&gsc, gps, pt, &xy[0], &xy[1]);
- }
- else {
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, diff_mat, &pt2);
- gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
- }
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
/* do boundbox check first */
if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
@@ -1197,6 +1369,11 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
/* updates */
if (hit_point != NULL) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
}
@@ -1224,7 +1401,7 @@ void GPENCIL_OT_select(wmOperatorType *ot)
ot->poll = gpencil_select_poll;
/* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
WM_operator_properties_mouse_select(ot);
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index d35df8bc380..708d8f37e58 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "DNA_listBase.h"
#include "DNA_windowmanager_types.h"
@@ -51,6 +52,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "gpencil_intern.h"
typedef struct bGPundonode {
@@ -111,6 +114,9 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
}
}
}
+ /* drawing batch cache is dirty now */
+ DEG_id_tag_update(&new_gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ new_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 8b65855f7c4..cd352579b4a 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -40,7 +40,9 @@
#include "BLT_translation.h"
#include "BLI_rand.h"
+#include "DNA_meshdata_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -48,9 +50,13 @@
#include "DNA_view3d_types.h"
#include "BKE_action.h"
+#include "BKE_main.h"
+#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_material.h"
#include "BKE_tracking.h"
#include "WM_api.h"
@@ -65,8 +71,14 @@
#include "ED_gpencil.h"
#include "ED_clip.h"
#include "ED_view3d.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "gpencil_intern.h"
@@ -76,7 +88,7 @@
/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it,
* when context info is not available.
*/
-bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob, PointerRNA *ptr)
+bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr)
{
/* if there's an active area, check if the particular editor may
* have defined any special Grease Pencil context for editing...
@@ -85,26 +97,37 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
SpaceLink *sl = sa->spacedata.first;
switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3D-View */
+ /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
+ case SPACE_BUTS: /* properties */
+ case SPACE_INFO: /* header info (needed after workspaces merge) */
{
- BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src,
- GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT));
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* GP Object */
+ if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
+ return (bGPdata **)&ob->data;
+ }
+ else {
+ return NULL;
+ }
- if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) {
- /* legacy behaviour for usage with old addons requiring object-linked to objects */
+ break;
+ }
- /* just in case no active/selected object... */
- if (ob && (ob->flag & SELECT)) {
- /* for now, as long as there's an object, default to using that in 3D-View */
- if (ptr) RNA_id_pointer_create(&ob->id, ptr);
- return &ob->gpd;
- }
- /* else: defaults to scene... */
+ case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */
+ case SPACE_VIEW3D: /* 3D-View */
+ {
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* GP Object */
+ if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
+ return (bGPdata **)&ob->data;
}
else {
- if (ptr) RNA_id_pointer_create(&scene->id, ptr);
+ /* Annotations */
+ /* XXX: */
+ if (r_ptr) RNA_id_pointer_create(&scene->id, r_ptr);
return &scene->gpd;
}
+
break;
}
case SPACE_NODE: /* Nodes Editor */
@@ -114,7 +137,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
/* return the GP data for the active node block/node */
if (snode && snode->nodetree) {
/* for now, as long as there's an active node tree, default to using that in the Nodes Editor */
- if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr);
+ if (r_ptr) RNA_id_pointer_create(&snode->nodetree->id, r_ptr);
return &snode->nodetree->gpd;
}
@@ -127,7 +150,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
/* for now, Grease Pencil data is associated with the space (actually preview region only) */
/* XXX our convention for everything else is to link to data though... */
- if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr);
+ if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr);
return &sseq->gpd;
}
case SPACE_IMAGE: /* Image/UV Editor */
@@ -136,7 +159,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
/* for now, Grease Pencil data is associated with the space... */
/* XXX our convention for everything else is to link to data though... */
- if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr);
+ if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr);
return &sima->gpd;
}
case SPACE_CLIP: /* Nodes Editor */
@@ -151,15 +174,11 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
if (!track)
return NULL;
- if (ptr)
- RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr);
-
+ if (r_ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr);
return &track->gpd;
}
else {
- if (ptr)
- RNA_id_pointer_create(&clip->id, ptr);
-
+ if (r_ptr) RNA_id_pointer_create(&clip->id, r_ptr);
return &clip->gpd;
}
}
@@ -170,79 +189,102 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
}
}
- /* just fall back on the scene's GP data */
- if (ptr) RNA_id_pointer_create((ID *)scene, ptr);
- return (scene) ? &scene->gpd : NULL;
+ return NULL;
}
/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
-bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
+bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
{
ID *screen_id = (ID *)CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
Object *ob = CTX_data_active_object(C);
- return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr);
+ return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr);
}
/* -------------------------------------------------------- */
/* Get the active Grease Pencil datablock, when context is not available */
-bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob)
+bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, NULL);
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL);
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
-/* Get the active Grease Pencil datablock */
+/**
+ * Get the active Grease Pencil datablock
+ * \note This is the original (bmain) copy of the datablock, stored in files.
+ * Do not use for reading evaluated copies of GP Objects data
+ */
bGPdata *ED_gpencil_data_get_active(const bContext *C)
{
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
+/**
+ * Get the evaluated copy of the active Grease Pencil datablock (where applicable)
+ * - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP datablock
+ * (i.e. a copy of the active GP datablock for the active object, where modifiers have been
+ * applied). This is needed to correctly work with "Copy-on-Write"
+ * - For all other editors (i.e. "GP Annotations"), this just gives the active datablock
+ * like for ED_gpencil_data_get_active()
+ */
+bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
+{
+ ID *screen_id = (ID *)CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob = CTX_data_active_object(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */
+ return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval);
+}
+
+/* -------------------------------------------------------- */
+
+/**
+ * Utility to check whether the r_ptr output of ED_gpencil_data_get_pointers()
+ * is for annotation usage.
+ */
+bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
+{
+ /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data.
+ * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else)
+ */
+ return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
+}
+
/* -------------------------------------------------------- */
// XXX: this should be removed... We really shouldn't duplicate logic like this!
-bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, ViewLayer *view_layer)
+bGPdata *ED_gpencil_data_get_active_v3d(ViewLayer *view_layer)
{
Base *base = view_layer->basact;
bGPdata *gpd = NULL;
+
/* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
* to be consistent with ED_gpencil_data_get_active's behavior.
*/
-
if (base && TESTBASE(base)) {
- gpd = base->object->gpd;
+ if (base->object->type == OB_GPENCIL)
+ gpd = base->object->data;
}
- return gpd ? gpd : scene->gpd;
+ return gpd ? gpd : NULL;
}
/* ******************************************************** */
/* Keyframe Indicator Checks */
/* Check whether there's an active GP keyframe on the current frame */
-bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra)
+bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
{
- /* just check both for now... */
- // XXX: this could get confusing (e.g. if only on the object, but other places don't show this)
- if (scene->gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(scene->gpd);
- if (gpl) {
- if (gpl->actframe) {
- // XXX: assumes that frame has been fetched already
- return (gpl->actframe->framenum == cfra);
- }
- else {
- /* XXX: disabled as could be too much of a penalty */
- /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
- }
- }
- }
-
- if (ob && ob->gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->gpd);
+ if (ob && ob->data && (ob->type == OB_GPENCIL)) {
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
if (gpl) {
if (gpl->actframe) {
// XXX: assumes that frame has been fetched already
@@ -281,28 +323,13 @@ bool gp_active_layer_poll(bContext *C)
bool gp_active_brush_poll(bContext *C)
{
ToolSettings *ts = CTX_data_tool_settings(C);
- bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
-
- return (brush != NULL);
-}
-
-/* poll callback for checking if there is an active palette */
-bool gp_active_palette_poll(bContext *C)
-{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
-
- return (palette != NULL);
-}
-
-/* poll callback for checking if there is an active palette color */
-bool gp_active_palettecolor_poll(bContext *C)
-{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
-
- return (palcolor != NULL);
+ Paint *paint = &ts->gp_paint->paint;
+ if (paint) {
+ return (paint->brush != NULL);
+ }
+ else {
+ return false;
+ }
}
/* ******************************************************** */
@@ -360,7 +387,7 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
/* Create new layer */
/* TODO: have some way of specifying that we don't want this? */
{
- /* active Keying Set */
+ /* "New Layer" entry */
item_tmp.identifier = "__CREATE__";
item_tmp.name = "New Layer";
item_tmp.value = -1;
@@ -392,7 +419,6 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
}
-
/* ******************************************************** */
/* Brush Tool Core */
@@ -426,7 +452,7 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
/* Stroke Validity Testing */
/* Check whether given stroke can be edited given the supplied context */
-// XXX: do we need additional flags for screenspace vs dataspace?
+/* TODO: do we need additional flags for screenspace vs dataspace? */
bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
{
/* sanity check */
@@ -436,7 +462,7 @@ bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
/* filter stroke types by flags + spacetype */
if (gps->flag & GP_STROKE_3DSPACE) {
/* 3D strokes - only in 3D view */
- return (sa->spacetype == SPACE_VIEW3D);
+ return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_BUTS));
}
else if (gps->flag & GP_STROKE_2DIMAGE) {
/* Special "image" strokes - only in Image Editor */
@@ -460,59 +486,21 @@ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
}
/* Check whether given stroke can be edited for the current color */
-bool ED_gpencil_stroke_color_use(const bGPDlayer *gpl, const bGPDstroke *gps)
+bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
{
/* check if the color is editable */
- bGPDpalettecolor *palcolor = gps->palcolor;
- if (palcolor != NULL) {
- if (palcolor->flag & PC_COLOR_HIDE)
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ if (gp_style != NULL) {
+ if (gp_style->flag & GP_STYLE_COLOR_HIDE)
return false;
- if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (palcolor->flag & PC_COLOR_LOCKED))
+ if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED))
return false;
}
return true;
}
-/* Get palette color or create a new one */
-bGPDpalettecolor *ED_gpencil_stroke_getcolor(bGPdata *gpd, bGPDstroke *gps)
-{
- bGPDpalette *palette;
- bGPDpalettecolor *palcolor;
-
- if ((gps->palcolor != NULL) && ((gps->flag & GP_STROKE_RECALC_COLOR) == 0))
- return gps->palcolor;
-
- /* get palette */
- palette = BKE_gpencil_palette_getactive(gpd);
- if (palette == NULL) {
- palette = BKE_gpencil_palette_addnew(gpd, DATA_("GP_Palette"), true);
- }
- /* get color */
- palcolor = BKE_gpencil_palettecolor_getbyname(palette, gps->colorname);
- if (palcolor == NULL) {
- if (gps->palcolor == NULL) {
- palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true);
- /* set to a different color */
- ARRAY_SET_ITEMS(palcolor->color, 1.0f, 0.0f, 1.0f, 0.9f);
- }
- else {
- palcolor = BKE_gpencil_palettecolor_addnew(palette, gps->colorname, true);
- /* set old color and attributes */
- bGPDpalettecolor *gpscolor = gps->palcolor;
- copy_v4_v4(palcolor->color, gpscolor->color);
- copy_v4_v4(palcolor->fill, gpscolor->fill);
- palcolor->flag = gpscolor->flag;
- }
- }
-
- /* clear flag and set pointer */
- gps->flag &= ~GP_STROKE_RECALC_COLOR;
- gps->palcolor = palcolor;
-
- return palcolor;
-}
-
/* ******************************************************** */
/* Space Conversion */
@@ -573,9 +561,9 @@ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *
}
/**
- * Change points position relative to parent object
+ * Change position relative to parent object
*/
-void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
+void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
bGPDspoint *pt;
int i;
@@ -585,7 +573,7 @@ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(gpl, diff_mat);
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
for (i = 0; i < gps->totpoints; i++) {
@@ -598,14 +586,14 @@ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
/**
* Change point position relative to parent object
*/
-void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt)
+void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
{
/* undo matrix */
float diff_mat[4][4];
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(gpl, diff_mat);
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
@@ -770,194 +758,259 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen
}
/**
- * Apply smooth to stroke point
- * \param gps Stroke to smooth
- * \param i Point index
- * \param inf Amount of smoothing to apply
- * \param affect_pressure Apply smoothing to pressure values too?
+ * Convert tGPspoint (temporary 2D/screenspace point data used by GP modal operators)
+ * to 3D coordinates.
+ *
+ * \param point2D: The screenspace 2D point data to convert
+ * \param depth: Depth array (via ED_view3d_autodist_depth())
+ * \param[out] r_out: The resulting 2D point data
*/
-bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
+void gp_stroke_convertcoords_tpoint(
+ Scene *scene, ARegion *ar, View3D *v3d,
+ Object *ob, bGPDlayer *gpl,
+ const tGPspoint *point2D, float *depth,
+ float r_out[3])
{
- bGPDspoint *pt = &gps->points[i];
- float pressure = 0.0f;
- float sco[3] = {0.0f};
+ ToolSettings *ts = scene->toolsettings;
+ const int mval[2] = {point2D->x, point2D->y};
- /* Do nothing if not enough points to smooth out */
- if (gps->totpoints <= 2) {
- return false;
+ if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval, r_out, 0, depth))) {
+ /* projecting onto 3D-Geometry
+ * - nothing more needs to be done here, since view_autodist_simple() has already done it
+ */
}
-
- /* Only affect endpoints by a fraction of the normal strength,
- * to prevent the stroke from shrinking too much
- */
- if ((i == 0) || (i == gps->totpoints - 1)) {
- inf *= 0.1f;
- }
-
- /* Compute smoothed coordinate by taking the ones nearby */
- /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
- {
- // XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
- const int steps = 2;
- const float average_fac = 1.0f / (float)(steps * 2 + 1);
- int step;
-
- /* add the point itself */
- madd_v3_v3fl(sco, &pt->x, average_fac);
-
- if (affect_pressure) {
- pressure += pt->pressure * average_fac;
+ else {
+ float mval_f[2] = {(float)point2D->x, (float)point2D->y};
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float zfac;
+
+ /* Current method just converts each point in screen-coordinates to
+ * 3D-coordinates using the 3D-cursor as reference.
+ */
+ ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, rvec);
+ zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
+
+ if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ sub_v2_v2v2(mval_f, mval_prj, mval_f);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(r_out, rvec, dvec);
+ }
+ else {
+ zero_v3(r_out);
}
+ }
+}
- /* n-steps before/after current point */
- // XXX: review how the endpoints are treated by this algorithm
- // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
- for (step = 1; step <= steps; step++) {
- bGPDspoint *pt1, *pt2;
- int before = i - step;
- int after = i + step;
-
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
-
- pt1 = &gps->points[before];
- pt2 = &gps->points[after];
-
- /* add both these points to the average-sum (s += p[i]/n) */
- madd_v3_v3fl(sco, &pt1->x, average_fac);
- madd_v3_v3fl(sco, &pt2->x, average_fac);
-
-#if 0
- /* XXX: Disabled because get weird result */
- /* do pressure too? */
- if (affect_pressure) {
- pressure += pt1->pressure * average_fac;
- pressure += pt2->pressure * average_fac;
+/**
+ * Get drawing reference point for conversion or projection of the stroke
+ * \param[out] r_vec : Reference point found
+ */
+void ED_gp_get_drawing_reference(
+ View3D *v3d, Scene *scene, Object *ob, bGPDlayer *UNUSED(gpl),
+ char align_flag, float r_vec[3])
+{
+ const float *fp = ED_view3d_cursor3d_get(scene, v3d)->location;
+
+ /* if using a gpencil object at cursor mode, can use the location of the object */
+ if (align_flag & GP_PROJECT_VIEWSPACE) {
+ if (ob && (ob->type == OB_GPENCIL)) {
+ /* fallback (no strokes) - use cursor or object location */
+ if (align_flag & GP_PROJECT_CURSOR) {
+ /* use 3D-cursor */
+ copy_v3_v3(r_vec, fp);
+ }
+ else {
+ /* use object location */
+ copy_v3_v3(r_vec, ob->obmat[3]);
}
-#endif
}
}
-
- /* Based on influence factor, blend between original and optimal smoothed coordinate */
- interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
-
-#if 0
- /* XXX: Disabled because get weird result */
- if (affect_pressure) {
- pt->pressure = pressure;
+ else {
+ /* use 3D-cursor */
+ copy_v3_v3(r_vec, fp);
}
-#endif
-
- return true;
}
+
/**
-* Apply smooth for strength to stroke point
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
-bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf)
+ * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
+ */
+void ED_gp_project_stroke_to_plane(Object *ob, RegionView3D *rv3d, bGPDstroke *gps, const float origin[3], const int axis)
{
- bGPDspoint *ptb = &gps->points[i];
-
- /* Do nothing if not enough points */
- if (gps->totpoints <= 2) {
- return false;
+ float plane_normal[3];
+ float vn[3];
+
+ float ray[3];
+ float rpoint[3];
+
+ /* normal vector for a plane locked to axis */
+ zero_v3(plane_normal);
+ if (axis < 0) {
+ /* if the axis is not locked, need a vector to the view direction
+ * in order to get the right size of the stroke.
+ */
+ ED_view3d_global_to_vector(rv3d, origin, plane_normal);
+ }
+ else {
+ plane_normal[axis] = 1.0f;
+ /* if object, apply object rotation */
+ if (ob && (ob->type == OB_GPENCIL)) {
+ mul_mat3_m4_v3(ob->obmat, plane_normal);
+ }
}
- /* Compute theoretical optimal value using distances */
- bGPDspoint *pta, *ptc;
- int before = i - 1;
- int after = i + 1;
-
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
-
- pta = &gps->points[before];
- ptc = &gps->points[after];
+ /* Reproject the points in the plane */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
- /* the optimal value is the corresponding to the interpolation of the strength
- * at the distance of point b
- */
- const float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
- const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
+ /* get a vector from the point with the current view direction of the viewport */
+ ED_view3d_global_to_vector(rv3d, &pt->x, vn);
- /* Based on influence factor, blend between original and optimal */
- ptb->strength = (1.0f - inf) * ptb->strength + inf * optimal;
+ /* calculate line extreme point to create a ray that cross the plane */
+ mul_v3_fl(vn, -50.0f);
+ add_v3_v3v3(ray, &pt->x, vn);
- return true;
+ /* if the line never intersect, the point is not changed */
+ if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
+ copy_v3_v3(&pt->x, rpoint);
+ }
+ }
}
/**
-* Apply smooth for thickness to stroke point (use pressure)
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
-bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf)
+ * Reproject given point to a plane locked to axis to avoid stroke offset
+ * \param[in, out] pt : Point to affect
+ */
+void ED_gp_project_point_to_plane(Object *ob, RegionView3D *rv3d, const float origin[3], const int axis, bGPDspoint *pt)
{
- bGPDspoint *ptb = &gps->points[i];
-
- /* Do nothing if not enough points */
- if (gps->totpoints <= 2) {
- return false;
+ float plane_normal[3];
+ float vn[3];
+
+ float ray[3];
+ float rpoint[3];
+
+ /* normal vector for a plane locked to axis */
+ zero_v3(plane_normal);
+ if (axis < 0) {
+ /* if the axis is not locked, need a vector to the view direction
+ * in order to get the right size of the stroke.
+ */
+ ED_view3d_global_to_vector(rv3d, origin, plane_normal);
+ }
+ else {
+ plane_normal[axis] = 1.0f;
+ /* if object, apply object rotation */
+ if (ob && (ob->type == OB_GPENCIL)) {
+ mul_mat3_m4_v3(ob->obmat, plane_normal);
+ }
}
- /* Compute theoretical optimal value using distances */
- bGPDspoint *pta, *ptc;
- int before = i - 1;
- int after = i + 1;
-
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
-
- pta = &gps->points[before];
- ptc = &gps->points[after];
- /* the optimal value is the corresponding to the interpolation of the pressure
- * at the distance of point b
- */
- float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
- float optimal = (1.0f - fac) * pta->pressure + fac * ptc->pressure;
+ /* Reproject the points in the plane */
+ /* get a vector from the point with the current view direction of the viewport */
+ ED_view3d_global_to_vector(rv3d, &pt->x, vn);
- /* Based on influence factor, blend between original and optimal */
- ptb->pressure = (1.0f - inf) * ptb->pressure + inf * optimal;
+ /* calculate line extrem point to create a ray that cross the plane */
+ mul_v3_fl(vn, -50.0f);
+ add_v3_v3v3(ray, &pt->x, vn);
- return true;
+ /* if the line never intersect, the point is not changed */
+ if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
+ copy_v3_v3(&pt->x, rpoint);
+ }
}
+/* ******************************************************** */
+/* Stroke Operations */
+// XXX: Check if these functions duplicate stuff in blenkernel, and/or whether we should just deduplicate
+
/**
* Subdivide a stroke once, by adding a point half way between each pair of existing points
* \param gps Stroke data
- * \param new_totpoints Total number of points (after subdividing)
+ * \param subdivide Number of times to subdivide
*/
-void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
+void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
{
- /* Move points towards end of enlarged points array to leave space for new points */
- int y = 1;
- for (int i = gps->totpoints - 1; i > 0; i--) {
- gps->points[new_totpoints - y] = gps->points[i];
- y += 2;
- }
+ bGPDspoint *temp_points;
+ int totnewpoints, oldtotpoints;
+ int i2;
+
+ /* loop as many times as levels */
+ for (int s = 0; s < subdivide; s++) {
+ totnewpoints = gps->totpoints - 1;
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+
+ /* resize the points arrys */
+ gps->totpoints += totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* move points from last to first to new place */
+ i2 = gps->totpoints - 1;
+ for (int i = oldtotpoints - 1; i > 0; i--) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[i2];
+ MDeformVert *dvert = &gps->dvert[i];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+ pt_final->uv_fac = pt->uv_fac;
+ pt_final->uv_rot = pt->uv_rot;
+
+ dvert_final->totweight = dvert->totweight;
+ dvert_final->dw = dvert->dw;
+
+ i2 -= 2;
+ }
+ /* interpolate mid points */
+ i2 = 1;
+ for (int i = 0; i < oldtotpoints - 1; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i2];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
+ /* add a half way point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
+ pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
+ CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt_final->time = interpf(pt->time, next->time, 0.5f);
+ pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
+ pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
+
+ dvert_final->totweight = 0;
+ dvert_final->dw = NULL;
+
+ i2 += 2;
+ }
- /* Create interpolated points */
- for (int i = 0; i < new_totpoints - 1; i += 2) {
- bGPDspoint *prev = &gps->points[i];
- bGPDspoint *pt = &gps->points[i + 1];
- bGPDspoint *next = &gps->points[i + 2];
+ MEM_SAFE_FREE(temp_points);
- /* Interpolate all values */
- interp_v3_v3v3(&pt->x, &prev->x, &next->x, 0.5f);
+ /* move points to smooth stroke */
+ /* duplicate points in a temp area with the new subdivide data */
+ temp_points = MEM_dupallocN(gps->points);
- pt->pressure = interpf(prev->pressure, next->pressure, 0.5f);
- pt->strength = interpf(prev->strength, next->strength, 0.5f);
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = interpf(prev->time, next->time, 0.5f);
- }
+ /* extreme points are not changed */
+ for (int i = 0; i < gps->totpoints - 2; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i + 1];
- /* Update to new total number of points */
- gps->totpoints = new_totpoints;
+ /* move point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ }
+ /* free temp memory */
+ MEM_SAFE_FREE(temp_points);
+ }
}
/**
@@ -965,7 +1018,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
* \param gps Stroke data
* \param brush Brush data
*/
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng)
+void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng)
{
bGPDspoint *pt1, *pt2, *pt3;
float v1[3];
@@ -995,10 +1048,10 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng)
normalize_v3(ortho);
/* Read all points and apply shift vector (first and last point not modified) */
- for (int i = 1; i < gps->totpoints - 1; ++i) {
+ for (int i = 1; i < gps->totpoints - 1; i++) {
bGPDspoint *pt = &gps->points[i];
/* get vector with shift (apply a division because random is too sensitive */
- const float fac = BLI_rng_get_float(rng) * (brush->draw_random_sub / 10.0f);
+ const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f);
float svec[3];
copy_v3_v3(svec, ortho);
if (BLI_rng_get_float(rng) > 0.5f) {
@@ -1011,31 +1064,46 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng)
/* apply shift */
add_v3_v3(&pt->x, svec);
}
-
}
+
+/* ******************************************************** */
+/* Layer Parenting - Compute Parent Transforms */
+
/* calculate difference matrix */
-void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4])
+void ED_gpencil_parent_location(
+ const Depsgraph *depsgraph, Object *obact, bGPdata *UNUSED(gpd),
+ bGPDlayer *gpl, float diff_mat[4][4])
{
- Object *ob = gpl->parent;
-
- if (ob == NULL) {
+ Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
+ Object *obparent = gpl->parent;
+ Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : obparent;
+
+ /* if not layer parented, try with object parented */
+ if (obparent_eval == NULL) {
+ if (ob_eval != NULL) {
+ if (ob_eval->type == OB_GPENCIL) {
+ copy_m4_m4(diff_mat, ob_eval->obmat);
+ return;
+ }
+ }
+ /* not gpencil object */
unit_m4(diff_mat);
return;
}
else {
if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
- mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse);
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
return;
}
else if (gpl->partype == PARBONE) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, gpl->parsubstr);
+ bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
if (pchan) {
float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, ob->obmat, pchan->pose_mat);
+ mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
}
else {
- mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse); /* if bone not found use object (armature) */
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); /* if bone not found use object (armature) */
}
return;
}
@@ -1046,7 +1114,7 @@ void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4])
}
/* reset parent matrix for all layers */
-void ED_gpencil_reset_layers_parent(bGPdata *gpd)
+void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
{
bGPDspoint *pt;
int i;
@@ -1071,7 +1139,7 @@ void ED_gpencil_reset_layers_parent(bGPdata *gpd)
/* only redo if any change */
if (!equals_m4m4(gpl->inverse, cur_mat)) {
/* first apply current transformation to all strokes */
- ED_gpencil_parent_location(gpl, diff_mat);
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
@@ -1086,90 +1154,582 @@ void ED_gpencil_reset_layers_parent(bGPdata *gpd)
}
}
/* ******************************************************** */
-bool ED_gpencil_stroke_minmax(
- const bGPDstroke *gps, const bool use_select,
- float r_min[3], float r_max[3])
+/* GP Object Stuff */
+
+/* Helper function to create new OB_GPENCIL Object */
+Object *ED_add_gpencil_object(bContext *C, Scene *scene, const float loc[3])
{
- const bGPDspoint *pt;
- int i;
- bool changed = false;
+ float rot[3] = {0.0f};
+
+ Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, scene->lay);
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {;
- minmax_v3v3_v3(r_min, r_max, &pt->x);
- changed = true;
+ /* define size */
+ BKE_object_obdata_size_init(ob, GP_OBGPENCIL_DEFAULT_SIZE);
+ /* create default brushes and colors */
+ ED_gpencil_add_defaults(C);
+
+ return ob;
+}
+
+/* Helper function to create default colors and drawing brushes */
+void ED_gpencil_add_defaults(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ /* first try to reuse default material */
+ if (ob->actcol > 0) {
+ Material *ma = give_current_material(ob, ob->actcol);
+ if ((ma) && (ma->gp_style == NULL)) {
+ BKE_material_init_gpencil_settings(ma);
}
}
- return changed;
+
+ /* ensure color exist */
+ BKE_gpencil_material_ensure(bmain, ob);
+
+ Paint *paint = BKE_brush_get_gpencil_paint(ts);
+ /* if not exist, create a new one */
+ if (paint->brush == NULL) {
+ /* create new brushes */
+ BKE_brush_gpencil_presets(C);
+ }
+
}
-/* Dynamic Enums of GP Brushes */
-const EnumPropertyItem *ED_gpencil_brushes_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free)
+/* ******************************************************** */
+/* Vertex Groups */
+
+/* assign points to vertex group */
+void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPDbrush *brush;
- EnumPropertyItem *item = NULL, item_tmp = { 0 };
- int totitem = 0;
- int i = 0;
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
- if (ELEM(NULL, C, ts)) {
- return DummyRNA_DEFAULT_items;
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+ if (pt->flag & GP_SPOINT_SELECT) {
+ BKE_gpencil_vgroup_add_point_weight(dvert, def_nr, weight);
+ }
+ }
+ }
}
+ CTX_DATA_END;
+}
- /* Existing brushes */
- for (brush = ts->gp_brushes.first; brush; brush = brush->next, i++) {
- item_tmp.identifier = brush->info;
- item_tmp.name = brush->info;
- item_tmp.value = i;
+/* remove points from vertex group */
+void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
+{
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
- if (brush->flag & GP_BRUSH_ACTIVE)
- item_tmp.icon = ICON_BRUSH_DATA;
- else
- item_tmp.icon = ICON_NONE;
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
- RNA_enum_item_add(&item, &totitem, &item_tmp);
+ if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
+ BKE_gpencil_vgroup_remove_point_weight(dvert, def_nr);
+ }
+ }
}
+ CTX_DATA_END;
+}
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+/* select points of vertex group */
+void ED_gpencil_vgroup_select(bContext *C, Object *ob)
+{
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
- return item;
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ if (BKE_gpencil_vgroup_use_index(dvert, def_nr) > -1.0f) {
+ pt->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
}
-/* Dynamic Enums of GP Palettes */
-const EnumPropertyItem *ED_gpencil_palettes_enum_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
- bool *r_free)
+/* unselect points of vertex group */
+void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDpalette *palette;
- EnumPropertyItem *item = NULL, item_tmp = { 0 };
- int totitem = 0;
- int i = 0;
+ const int def_nr = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
- if (ELEM(NULL, C, gpd)) {
- return DummyRNA_DEFAULT_items;
+ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ if (BKE_gpencil_vgroup_use_index(dvert, def_nr) > -1.0f) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ }
+ }
}
+ CTX_DATA_END;
+}
- /* Existing palettes */
- for (palette = gpd->palettes.first; palette; palette = palette->next, i++) {
- item_tmp.identifier = palette->info;
- item_tmp.name = palette->info;
- item_tmp.value = i;
+/* ******************************************************** */
+/* Cursor drawing */
- if (palette->flag & PL_PALETTE_ACTIVE)
- item_tmp.icon = ICON_COLOR;
- else
- item_tmp.icon = ICON_NONE;
+/* check if cursor is in drawing region */
+static bool gp_check_cursor_region(bContext *C, int mval[2])
+{
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+ /* TODO: add more spacetypes */
+ if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
+ return false;
+ }
+ if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
+ return false;
+ }
+ else if (ar) {
+ rcti region_rect;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
+ /* Perform bounds check using */
+ ED_region_visible_rect(ar, &region_rect);
+ return BLI_rcti_isect_pt_v(&region_rect, mval);
+ }
+ else {
+ return false;
}
+}
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+/* draw eraser cursor */
+void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
+{
+ short radius = (short)brush->size;
- return item;
+ GPUVertFormat *format = immVertexFormat();
+ const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ imm_draw_circle_wire_2d(shdr_pos, x, y, radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, radius / 2)); /* was fixed 40 */
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+}
+
+/* Helper callback for drawing the cursor itself */
+static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ GP_EditBrush_Data *brush = NULL;
+ Brush *paintbrush = NULL;
+ Material *ma = NULL;
+ MaterialGPencilStyle *gp_style = NULL;
+ int *last_mouse_position = customdata;
+
+ if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) {
+ brush = &gset->brush[gset->weighttype];
+ }
+ else {
+ brush = &gset->brush[gset->brushtype];
+ }
+
+ /* default radius and color */
+ float color[3] = {1.0f, 1.0f, 1.0f};
+ float darkcolor[3];
+ float radius = 3.0f;
+
+ int mval[2] = {x, y};
+ /* check if cursor is in drawing region and has valid datablock */
+ if ((!gp_check_cursor_region(C, mval)) || (gpd == NULL)) {
+ return;
+ }
+
+ /* for paint use paint brush size and color */
+ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ paintbrush = BKE_brush_getactive_gpencil(scene->toolsettings);
+ /* while drawing hide */
+ if ((gpd->runtime.sbuffer_size > 0) &&
+ (paintbrush) && ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0))
+ {
+ return;
+ }
+
+ if (paintbrush) {
+ if ((paintbrush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
+ return;
+ }
+
+ /* eraser has special shape and use a different shader program */
+ if (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE) {
+ ED_gpencil_brush_draw_eraser(paintbrush, x, y);
+ return;
+ }
+
+ /* get current drawing color */
+ ma = BKE_gpencil_get_material_from_brush(paintbrush);
+ if (ma == NULL) {
+ BKE_gpencil_material_ensure(bmain, ob);
+ /* assign the first material to the brush */
+ ma = give_current_material(ob, 1);
+ paintbrush->gpencil_settings->material = ma;
+ }
+ gp_style = ma->gp_style;
+
+ /* after some testing, display the size of the brush is not practical because
+ * is too disruptive and the size of cursor does not change with zoom factor.
+ * The decision was to use a fix size, instead of paintbrush->thickness value.
+ */
+ if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
+ ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
+ (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW))
+ {
+ radius = 2.0f;
+ copy_v3_v3(color, gp_style->stroke_rgba);
+ }
+ else {
+ radius = 5.0f;
+ copy_v3_v3(color, paintbrush->add_col);
+ }
+ }
+ else {
+ return;
+ }
+ }
+
+ /* for sculpt use sculpt brush size */
+ if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) {
+ if (brush) {
+ if ((brush->flag & GP_EDITBRUSH_FLAG_ENABLE_CURSOR) == 0) {
+ return;
+ }
+
+ radius = brush->size;
+ if (brush->flag & (GP_EDITBRUSH_FLAG_INVERT | GP_EDITBRUSH_FLAG_TMP_INVERT)) {
+ copy_v3_v3(color, brush->curcolor_sub);
+ }
+ else {
+ copy_v3_v3(color, brush->curcolor_add);
+ }
+ }
+ }
+
+ /* draw icon */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ /* Inner Ring: Color from UI panel */
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+ if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
+ ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
+ ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
+ (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW))
+ {
+ imm_draw_circle_fill_2d(pos, x, y, radius, 40);
+ }
+ else {
+ imm_draw_circle_wire_2d(pos, x, y, radius, 40);
+ }
+
+ /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
+ mul_v3_v3fl(darkcolor, color, 0.40f);
+ immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
+ imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+
+ /* Draw line for lazy mouse */
+ if ((last_mouse_position) &&
+ (paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP))
+ {
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ copy_v3_v3(color, paintbrush->add_col);
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, x, y);
+ immVertex2f(
+ pos,
+ last_mouse_position[0] + ar->winrct.xmin,
+ last_mouse_position[1] + ar->winrct.ymin);
+ immEnd();
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ }
+
+ immUnbindProgram();
+}
+
+/* Turn brush cursor in on/off */
+void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
+{
+ Scene *scene = CTX_data_scene(C);
+ GP_BrushEdit_Settings *gset = &scene->toolsettings->gp_sculpt;
+ int *lastpost = customdata;
+
+ if (gset->paintcursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ gset->paintcursor = NULL;
+ }
+ else if (enable) {
+ /* in some situations cursor could be duplicated, so it is better disable first if exist */
+ if (gset->paintcursor) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ gset->paintcursor = NULL;
+ }
+ /* enable cursor */
+ gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
+ NULL,
+ gp_brush_drawcursor,
+ (lastpost) ? customdata : NULL);
+ }
+}
+
+/* verify if is using the right brush */
+static void gpencil_verify_brush_type(bContext *C, int newmode)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
+
+ switch (newmode) {
+ case OB_MODE_GPENCIL_SCULPT:
+ gset->flag &= ~GP_BRUSHEDIT_FLAG_WEIGHT_MODE;
+ if ((gset->brushtype < 0) || (gset->brushtype >= GP_EDITBRUSH_TYPE_WEIGHT)) {
+ gset->brushtype = GP_EDITBRUSH_TYPE_PUSH;
+ }
+ break;
+ case OB_MODE_GPENCIL_WEIGHT:
+ gset->flag |= GP_BRUSHEDIT_FLAG_WEIGHT_MODE;
+ if ((gset->weighttype < GP_EDITBRUSH_TYPE_WEIGHT) || (gset->weighttype >= TOT_GP_EDITBRUSH_TYPES)) {
+ gset->weighttype = GP_EDITBRUSH_TYPE_WEIGHT;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* set object modes */
+void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
+{
+ if (!gpd) {
+ return;
+ }
+
+ switch (newmode) {
+ case OB_MODE_GPENCIL_EDIT:
+ gpd->flag |= GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ break;
+ case OB_MODE_GPENCIL_PAINT:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag |= GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ case OB_MODE_GPENCIL_SCULPT:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag |= GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ gpencil_verify_brush_type(C, OB_MODE_GPENCIL_SCULPT);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ case OB_MODE_GPENCIL_WEIGHT:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
+ gpencil_verify_brush_type(C, OB_MODE_GPENCIL_WEIGHT);
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ default:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ break;
+ }
+}
+
+/* helper to convert 2d to 3d for simple drawing buffer */
+static void gpencil_stroke_convertcoords(ARegion *ar, const tGPspoint *point2D, float origin[3], float out[3])
+{
+ float mval_f[2] = { (float)point2D->x, (float)point2D->y };
+ float mval_prj[2];
+ float rvec[3], dvec[3];
+ float zfac;
+
+ copy_v3_v3(rvec, origin);
+
+ zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
+
+ if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ sub_v2_v2v2(mval_f, mval_prj, mval_f);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(out, rvec, dvec);
+ }
+ else {
+ zero_v3(out);
+ }
+}
+
+/* convert 2d tGPspoint to 3d bGPDspoint */
+void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
+{
+ float p3d[3];
+ /* conversion to 3d format */
+ gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
+ copy_v3_v3(&pt->x, p3d);
+
+ pt->pressure = tpt->pressure;
+ pt->strength = tpt->strength;
+ pt->uv_fac = tpt->uv_fac;
+ pt->uv_rot = tpt->uv_rot;
+}
+
+/* texture coordinate utilities */
+void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
+{
+ if (gps == NULL) {
+ return;
+ }
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ float pixsize;
+ if (gp_style) {
+ pixsize = gp_style->texture_pixsize / 1000000.0f;
+ }
+ else {
+ /* use this value by default */
+ pixsize = 0.000100f;
+ }
+ pixsize = MAX2(pixsize, 0.0000001f);
+
+ bGPDspoint *pt = NULL;
+ bGPDspoint *ptb = NULL;
+ int i;
+ float totlen = 0;
+
+ /* first read all points and calc distance */
+ for (i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ /* first point */
+ if (i == 0) {
+ pt->uv_fac = 0.0f;
+ continue;
+ }
+
+ ptb = &gps->points[i - 1];
+ totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
+ pt->uv_fac = totlen;
+ }
+ /* normalize the distance using a factor */
+ float factor;
+ /* if image, use texture width */
+ if ((gp_style) && (gp_style->sima)) {
+ factor = gp_style->sima->gen_x;
+ }
+ else {
+ factor = totlen;
+ }
+ for (i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ pt->uv_fac /= factor;
+ }
+}
+
+/* recalc uv for any stroke using the material */
+void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
+{
+ Material *gps_ma = NULL;
+ /* read all strokes */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ if (gpd == NULL) {
+ continue;
+ }
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (gpencil_layer_is_editable(gpl)) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* check if it is editable */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ gps_ma = give_current_material(ob, gps->mat_nr + 1);
+ /* update */
+ if ((gps_ma) && (gps_ma == mat)) {
+ ED_gpencil_calc_stroke_uv(ob, gps);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* ******************************************************** */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 59a54f03e56..ae86e4a5fbf 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -197,6 +197,8 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_NLATRACK,
ANIMTYPE_NLAACTION,
+ ANIMTYPE_PALETTE,
+
/* always as last item, the total number of channel types... */
ANIMTYPE_NUM_TYPES
} eAnim_ChannelType;
@@ -347,6 +349,9 @@ typedef enum eAnimFilter_Flags {
/* Movie clip only */
#define EXPANDED_MCLIP(clip) (clip->flag & MCLIP_DATA_EXPAND)
+/* Palette only */
+#define EXPANDED_PALETTE(palette) (palette->flag & PALETTE_DATA_EXPAND)
+
/* AnimData - NLA mostly... */
#define SEL_ANIMDATA(adt) (adt->flag & ADT_UI_SELECTED)
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 7d509d1243a..333e3d72615 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -42,6 +42,9 @@ extern char datatoc_preview_blend[];
extern int datatoc_preview_cycles_blend_size;
extern char datatoc_preview_cycles_blend[];
+extern int datatoc_preview_grease_pencil_blend_size;
+extern char datatoc_preview_grease_pencil_blend[];
+
extern int datatoc_blender_icons16_png_size;
extern char datatoc_blender_icons16_png[];
@@ -239,6 +242,66 @@ extern char datatoc_mc23_jpg[];
extern int datatoc_mc24_jpg_size;
extern char datatoc_mc24_jpg[];
+/* grease pencil sculpt brushes files */
+
+extern int datatoc_gp_brush_smooth_png_size;
+extern char datatoc_gp_brush_smooth_png[];
+
+extern int datatoc_gp_brush_thickness_png_size;
+extern char datatoc_gp_brush_thickness_png[];
+
+extern int datatoc_gp_brush_strength_png_size;
+extern char datatoc_gp_brush_strength_png[];
+
+extern int datatoc_gp_brush_grab_png_size;
+extern char datatoc_gp_brush_grab_png[];
+
+extern int datatoc_gp_brush_push_png_size;
+extern char datatoc_gp_brush_push_png[];
+
+extern int datatoc_gp_brush_twist_png_size;
+extern char datatoc_gp_brush_twist_png[];
+
+extern int datatoc_gp_brush_pinch_png_size;
+extern char datatoc_gp_brush_pinch_png[];
+
+extern int datatoc_gp_brush_randomize_png_size;
+extern char datatoc_gp_brush_randomize_png[];
+
+extern int datatoc_gp_brush_clone_png_size;
+extern char datatoc_gp_brush_clone_png[];
+
+extern int datatoc_gp_brush_weight_png_size;
+extern char datatoc_gp_brush_weight_png[];
+
+extern int datatoc_gp_brush_pencil_png_size;
+extern char datatoc_gp_brush_pencil_png[];
+
+extern int datatoc_gp_brush_pen_png_size;
+extern char datatoc_gp_brush_pen_png[];
+
+extern int datatoc_gp_brush_ink_png_size;
+extern char datatoc_gp_brush_ink_png[];
+
+extern int datatoc_gp_brush_inknoise_png_size;
+extern char datatoc_gp_brush_inknoise_png[];
+
+extern int datatoc_gp_brush_block_png_size;
+extern char datatoc_gp_brush_block_png[];
+
+extern int datatoc_gp_brush_marker_png_size;
+extern char datatoc_gp_brush_marker_png[];
+
+extern int datatoc_gp_brush_fill_png_size;
+extern char datatoc_gp_brush_fill_png[];
+
+extern int datatoc_gp_brush_erase_soft_png_size;
+extern char datatoc_gp_brush_erase_soft_png[];
+
+extern int datatoc_gp_brush_erase_hard_png_size;
+extern char datatoc_gp_brush_erase_hard_png[];
+extern int datatoc_gp_brush_erase_stroke_png_size;
+extern char datatoc_gp_brush_erase_stroke_png[];
#endif /* __ED_DATAFILES_H__ */
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index 39a58929b7c..41488baa964 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -40,7 +40,11 @@ void ED_gizmotypes_dial_3d(void);
void ED_gizmotypes_grab_3d(void);
void ED_gizmotypes_facemap_3d(void);
void ED_gizmotypes_primitive_3d(void);
+void ED_gizmotypes_blank_3d(void);
+struct bContext;
+struct Object;
+struct Scene;
struct wmGizmo;
struct wmGizmoGroup;
@@ -53,13 +57,13 @@ struct wmGizmoGroup;
/* gizmo_library_presets.c */
void ED_gizmo_draw_preset_box(
- const struct wmGizmo *mpr, float mat[4][4], int select_id);
+ const struct wmGizmo *gz, float mat[4][4], int select_id);
void ED_gizmo_draw_preset_arrow(
- const struct wmGizmo *mpr, float mat[4][4], int axis, int select_id);
+ const struct wmGizmo *gz, float mat[4][4], int axis, int select_id);
void ED_gizmo_draw_preset_circle(
- const struct wmGizmo *mpr, float mat[4][4], int axis, int select_id);
+ const struct wmGizmo *gz, float mat[4][4], int axis, int select_id);
void ED_gizmo_draw_preset_facemap(
- const struct bContext *C, const struct wmGizmo *mpr, struct Scene *scene,
+ const struct bContext *C, const struct wmGizmo *gz, struct Scene *scene,
struct Object *ob, const int facemap, int select_id);
@@ -87,8 +91,8 @@ enum {
ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
};
-void ED_gizmo_arrow3d_set_ui_range(struct wmGizmo *mpr, const float min, const float max);
-void ED_gizmo_arrow3d_set_range_fac(struct wmGizmo *mpr, const float range_fac);
+void ED_gizmo_arrow3d_set_ui_range(struct wmGizmo *gz, const float min, const float max);
+void ED_gizmo_arrow3d_set_range_fac(struct wmGizmo *gz, const float range_fac);
/* -------------------------------------------------------------------- */
/* 2D Arrow Gizmo */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index f1f2ce29e7f..13f8233079b 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -30,64 +30,44 @@
#ifndef __ED_GPENCIL_H__
#define __ED_GPENCIL_H__
-#include "ED_numinput.h"
-
struct ID;
struct ListBase;
-struct bContext;
-struct Depsgraph;
-struct ScrArea;
-struct ARegion;
-struct View3D;
-struct Object;
+struct PointerRNA;
+struct rcti;
+
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct bGPDstroke;
-struct bGPDpalette;
-struct bGPDpalettecolor;
-struct bAnimContext;
-struct KeyframeEditData;
-struct PointerRNA;
+struct bGPDspoint;
+struct Brush;
+
+struct Main;
+struct bContext;
+struct EvaluationContext;
+struct Depsgraph;
+struct ScrArea;
+struct ARegion;
+struct RegionView3D;
struct Scene;
+struct ToolSettings;
struct ViewLayer;
-struct wmWindowManager;
-struct wmKeyConfig;
-
-
-/* ------------- Grease-Pencil Helpers ---------------- */
-typedef struct tGPDinterpolate_layer {
- struct tGPDinterpolate_layer *next, *prev;
-
- struct bGPDlayer *gpl; /* layer */
- struct bGPDframe *prevFrame; /* frame before current frame (interpolate-from) */
- struct bGPDframe *nextFrame; /* frame after current frame (interpolate-to) */
- struct bGPDframe *interFrame; /* interpolated frame */
- float factor; /* interpolate factor */
+struct View3D;
-} tGPDinterpolate_layer;
+struct Object;
+struct Material;
-/* Temporary interpolate operation data */
-typedef struct tGPDinterpolate {
- struct Scene *scene; /* current scene from context */
- struct ScrArea *sa; /* area where painting originated */
- struct ARegion *ar; /* region where painting originated */
- struct bGPdata *gpd; /* current GP datablock */
+struct bAnimContext;
+struct KeyframeEditData;
- int cframe; /* current frame number */
- ListBase ilayers; /* (tGPDinterpolate_layer) layers to be interpolated */
- float shift; /* value for determining the displacement influence */
- float init_factor; /* initial interpolation factor for active layer */
- float low_limit; /* shift low limit (-100%) */
- float high_limit; /* shift upper limit (200%) */
- int flag; /* flag from toolsettings */
+struct wmKeyConfig;
+struct wmOperator;
+struct wmWindow;
+struct wmWindowManager;
- NumInput num; /* numeric input */
- void *draw_handle_3d; /* handle for drawing strokes while operator is running 3d stuff */
- void *draw_handle_screen; /* handle for drawing strokes while operator is running screen stuff */
-} tGPDinterpolate;
+/* ------------- Grease-Pencil Runtime Data ---------------- */
-/* Temporary 'Stroke Point' data
+/* Temporary 'Stroke Point' data (2D / screen-space)
*
* Used as part of the 'stroke cache' used during drawing of new strokes
*/
@@ -96,27 +76,43 @@ typedef struct tGPspoint {
float pressure; /* pressure of tablet at this point */
float strength; /* pressure of tablet at this point for alpha factor */
float time; /* Time relative to stroke start (used when converting to path) */
+ float uv_fac; /* factor of uv along the stroke */
+ float uv_rot; /* uv rotation for dor mode */
} tGPspoint;
-
-/* Check if 'sketching sessions' are enabled */
-#define GPENCIL_SKETCH_SESSIONS_ON(scene) ((scene)->toolsettings->gpencil_flags & GP_TOOL_FLAG_PAINTSESSIONS_ON)
+/* used to sort by zdepth gpencil objects in viewport */
+/* TODO: this could be a system parameter in userprefs screen */
+#define GP_CACHE_BLOCK_SIZE 16
+typedef struct tGPencilSort {
+ struct Base *base;
+ float zdepth;
+} tGPencilSort;
/* ----------- Grease Pencil Tools/Context ------------- */
/* Context-dependent */
-struct bGPdata **ED_gpencil_data_get_pointers(const struct bContext *C, struct PointerRNA *ptr);
+struct bGPdata **ED_gpencil_data_get_pointers(const struct bContext *C, struct PointerRNA *r_ptr);
+
struct bGPdata *ED_gpencil_data_get_active(const struct bContext *C);
+struct bGPdata *ED_gpencil_data_get_active_evaluated(const struct bContext *C);
/* Context independent (i.e. each required part is passed in instead) */
-struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ID *screen_id, struct Scene *scene,
- struct ScrArea *sa, struct Object *ob,
- struct PointerRNA *ptr);
-struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct Scene *scene,
- struct ScrArea *sa, struct Object *ob);
+struct bGPdata **ED_gpencil_data_get_pointers_direct(
+ struct ID *screen_id,
+ struct ScrArea *sa,
+ struct Scene *scene,
+ struct Object *ob,
+ struct PointerRNA *r_ptr);
+struct bGPdata *ED_gpencil_data_get_active_direct(
+ struct ID *screen_id,
+ struct ScrArea *sa,
+ struct Scene *scene,
+ struct Object *ob);
+
+bool ED_gpencil_data_owner_is_annotation(struct PointerRNA *owner_ptr);
/* 3D View */
-struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct ViewLayer *view_layer);
+struct bGPdata *ED_gpencil_data_get_active_v3d(struct ViewLayer *view_layer);
bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra);
@@ -124,13 +120,7 @@ bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfr
bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
-bool ED_gpencil_stroke_color_use(const struct bGPDlayer *gpl, const struct bGPDstroke *gps);
-
-struct bGPDpalettecolor *ED_gpencil_stroke_getcolor(struct bGPdata *gpd, struct bGPDstroke *gps);
-
-bool ED_gpencil_stroke_minmax(
- const struct bGPDstroke *gps, const bool use_select,
- float r_min[3], float r_max[3]);
+bool ED_gpencil_stroke_color_use(struct Object *ob, const struct bGPDlayer *gpl, const struct bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */
@@ -150,16 +140,29 @@ void ED_gpencil_strokes_copybuf_free(void);
void ED_gpencil_draw_2dimage(const struct bContext *C);
void ED_gpencil_draw_view2d(const struct bContext *C, bool onlyv2d);
-void ED_gpencil_draw_view3d(struct wmWindowManager *wm,
- struct Scene *scene,
- struct ViewLayer *view_layer,
- struct Depsgraph *depsgraph,
- struct View3D *v3d,
- struct ARegion *ar,
- bool only3d);
-void ED_gpencil_draw_ex(struct Scene *scene, struct bGPdata *gpd, int winx, int winy,
- const int cfra, const char spacetype);
-void ED_gp_draw_interpolation(struct tGPDinterpolate *tgpi, const int type);
+void ED_gpencil_draw_view3d(
+ struct wmWindowManager *wm,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct Depsgraph *depsgraph,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ bool only3d);
+void ED_gpencil_draw_view3d_annotations(
+ struct Scene *scene, struct Depsgraph *depsgraph,
+ struct View3D *v3d, struct ARegion *ar,
+ bool only3d);
+void ED_gpencil_draw_view3d_object(
+ struct wmWindowManager *wm,
+ struct Scene *scene,
+ struct Depsgraph *depsgraph,
+ struct Object *ob,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ bool only3d);
+void ED_gpencil_draw_ex(
+ struct RegionView3D *rv3d, struct Scene *scene, struct bGPdata *gpd, int winx, int winy,
+ const int cfra, const char spacetype);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
bool ED_gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
@@ -192,10 +195,46 @@ int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
/* ------------ Transformation Utilities ------------ */
-/* get difference matrix using parent */
-void ED_gpencil_parent_location(struct bGPDlayer *gpl, float diff_mat[4][4]);
+/* get difference matrix */
+void ED_gpencil_parent_location(
+ const struct Depsgraph *depsgraph, struct Object *obact, struct bGPdata *gpd,
+ struct bGPDlayer *gpl, float diff_mat[4][4]);
/* reset parent matrix for all layers */
-void ED_gpencil_reset_layers_parent(struct bGPdata *gpd);
+void ED_gpencil_reset_layers_parent(struct Depsgraph *depsgraph, struct Object *obact, struct bGPdata *gpd);
+
+/* cursor utilities */
+void ED_gpencil_brush_draw_eraser(struct Brush *brush, int x, int y);
+
+/* ----------- Add Primitive Utilities -------------- */
+
+void ED_gpencil_create_monkey(struct bContext *C, float mat[4][4]);
+void ED_gpencil_create_stroke(struct bContext *C, float mat[4][4]);
+
+/* ------------ Object Utilities ------------ */
+struct Object *ED_add_gpencil_object(struct bContext *C, struct Scene *scene, const float loc[3]);
+void ED_gpencil_add_defaults(struct bContext *C);
+/* set object modes */
+void ED_gpencil_setup_modes(struct bContext *C, struct bGPdata *gpd, int newmode);
+
+void ED_gp_project_stroke_to_plane(struct Object *ob, struct RegionView3D *rv3d, struct bGPDstroke *gps, const float origin[3], const int axis);
+void ED_gp_project_point_to_plane(struct Object *ob, struct RegionView3D *rv3d, const float origin[3], const int axis, struct bGPDspoint *pt);
+void ED_gp_get_drawing_reference(struct View3D *v3d, struct Scene *scene, struct Object *ob, struct bGPDlayer *gpl, char align_flag, float vec[3]);
+
+/* set sculpt cursor */
+void ED_gpencil_toggle_brush_cursor(struct bContext *C, bool enable, void *customdata);
+
+/* vertex groups */
+void ED_gpencil_vgroup_assign(struct bContext *C, struct Object *ob, float weight);
+void ED_gpencil_vgroup_remove(struct bContext *C, struct Object *ob);
+void ED_gpencil_vgroup_select(struct bContext *C, struct Object *ob);
+void ED_gpencil_vgroup_deselect(struct bContext *C, struct Object *ob);
+
+/* join objects */
+int ED_gpencil_join_objects_exec(struct bContext *C, struct wmOperator *op);
+/* texture coordinate utilities */
+void ED_gpencil_tpoint_to_point(struct ARegion *ar, float origin[3], const struct tGPspoint *tpt, struct bGPDspoint *pt);
+void ED_gpencil_calc_stroke_uv(struct Object *ob, struct bGPDstroke *gps);
+void ED_gpencil_update_color_uv(struct Main *bmain, struct Material *mat);
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 9b0b2c970b2..45a0680e0c1 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -42,6 +42,7 @@ struct bActionGroup;
struct Object;
struct ListBase;
struct bGPDlayer;
+struct Palette;
struct MaskLayer;
struct Scene;
struct View2D;
@@ -109,7 +110,7 @@ typedef enum eKeyframeShapeDrawOpts {
} eKeyframeShapeDrawOpts;
/* draw simple diamond-shape keyframe */
-/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, immBegin(GWN_PRIM_POINTS, n), then call this n times */
+/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, immBegin(GPU_PRIM_POINTS, n), then call this n times */
void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha,
unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id);
@@ -151,9 +152,11 @@ void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tr
/* DopeSheet Summary */
void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* Grease Pencil datablock summary */
-void gpencil_to_keylist(struct bDopeSheet *ads, struct bGPdata *gpd, struct DLRBT_Tree *keys);
+void gpencil_to_keylist(struct bDopeSheet *ads, struct bGPdata *gpd, struct DLRBT_Tree *keys, const bool active);
/* Grease Pencil Layer */
void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys);
+/* Palette */
+void palette_to_keylist(struct bDopeSheet *ads, struct Palette *palette, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* Mask */
void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 38545137740..a39523983ba 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -42,6 +42,7 @@ struct ID;
struct Main;
struct Menu;
struct ModifierData;
+struct ShaderFxData;
struct Object;
struct ReportList;
struct Scene;
@@ -112,6 +113,7 @@ void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap
void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap,
const bool do_connected);
+void ED_keymap_editmesh_elem_mode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode);
void ED_object_base_activate(struct bContext *C, struct Base *base);
@@ -260,6 +262,40 @@ bool ED_object_iter_other(
bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v);
+
+/* object_greasepencil_modifier.c */
+struct GpencilModifierData *ED_object_gpencil_modifier_add(
+ struct ReportList *reports, struct Main *bmain, struct Scene *scene,
+ struct Object *ob, const char *name, int type);
+bool ED_object_gpencil_modifier_remove(
+ struct ReportList *reports, struct Main *bmain,
+ struct Object *ob, struct GpencilModifierData *md);
+void ED_object_gpencil_modifier_clear(
+ struct Main *bmain, struct Object *ob);
+int ED_object_gpencil_modifier_move_down(
+ struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
+int ED_object_gpencil_modifier_move_up(
+ struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
+int ED_object_gpencil_modifier_apply(
+ struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
+ struct Object *ob, struct GpencilModifierData *md, int mode);
+int ED_object_gpencil_modifier_copy(
+ struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md);
+
+/* object_shader_fx.c */
+struct ShaderFxData *ED_object_shaderfx_add(
+ struct ReportList *reports, struct Main *bmain, struct Scene *scene,
+ struct Object *ob, const char *name, int type);
+bool ED_object_shaderfx_remove(
+ struct ReportList *reports, struct Main *bmain,
+ struct Object *ob, struct ShaderFxData *fx);
+void ED_object_shaderfx_clear(
+ struct Main *bmain, struct Object *ob);
+int ED_object_shaderfx_move_down(
+ struct ReportList *reports, struct Object *ob, struct ShaderFxData *fx);
+int ED_object_shaderfx_move_up(
+ struct ReportList *reports, struct Object *ob, struct ShaderFxData *fx);
+
/* object_select.c */
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 914641c1add..2445cbdb16c 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -286,6 +286,7 @@ bool ED_operator_object_active_editable_font(struct bContext *C);
bool ED_operator_editmesh(struct bContext *C);
bool ED_operator_editmesh_view3d(struct bContext *C);
bool ED_operator_editmesh_region_view3d(struct bContext *C);
+bool ED_operator_editmesh_auto_smooth(struct bContext *C);
bool ED_operator_editarmature(struct bContext *C);
bool ED_operator_editcurve(struct bContext *C);
bool ED_operator_editcurve_3d(struct bContext *C);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 80dea103f8c..a8e8b347da2 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -89,6 +89,7 @@ enum TfmMode {
TFM_VERT_SLIDE,
TFM_SEQ_SLIDE,
TFM_BONE_ENVELOPE_DIST,
+ TFM_NORMAL_ROTATION,
};
/* TRANSFORM CONTEXTS */
@@ -154,18 +155,19 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_CENTER (1 << 12)
#define P_GPENCIL_EDIT (1 << 13)
#define P_CURSOR_EDIT (1 << 14)
+#define P_CLNOR_INVALIDATE (1 << 15)
void Transform_Properties(struct wmOperatorType *ot, int flags);
/* transform gizmos */
-void TRANSFORM_WGT_gizmo(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_xform_cage(struct wmGizmoGroupType *wgt);
+void TRANSFORM_GGT_gizmo(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_xform_cage(struct wmGizmoGroupType *gzgt);
-bool ED_widgetgroup_gizmo2d_poll(const struct bContext *C, struct wmGizmoGroupType *wgt);
-void ED_widgetgroup_gizmo2d_setup(const struct bContext *C, struct wmGizmoGroup *mgroup);
-void ED_widgetgroup_gizmo2d_refresh(const struct bContext *C, struct wmGizmoGroup *mgroup);
-void ED_widgetgroup_gizmo2d_draw_prepare(const struct bContext *C, struct wmGizmoGroup *mgroup);
+bool ED_widgetgroup_gizmo2d_poll(const struct bContext *C, struct wmGizmoGroupType *gzgt);
+void ED_widgetgroup_gizmo2d_setup(const struct bContext *C, struct wmGizmoGroup *gzgroup);
+void ED_widgetgroup_gizmo2d_refresh(const struct bContext *C, struct wmGizmoGroup *gzgroup);
+void ED_widgetgroup_gizmo2d_draw_prepare(const struct bContext *C, struct wmGizmoGroup *gzgroup);
/* Snapping */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index efcf5978968..6b0c59fb557 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -119,7 +119,7 @@ void ED_view3d_cursor3d_position_rotation(
float cursor_co[3], float cursor_quat[4]);
void ED_view3d_cursor3d_update(
struct bContext *C, const int mval[2],
- bool use_depth, enum eV3DCursorOrient orientation);
+ const bool use_depth, enum eV3DCursorOrient orientation);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -523,7 +523,7 @@ void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *a
void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
#define V3D_IS_ZBUF(v3d) \
- (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE))
+ (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->shading.type > OB_WIRE))
void ED_view3d_id_remap(struct View3D *v3d, const struct ID *old_id, struct ID *new_id);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index ec4c7dddd4c..dec02faf85c 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -1001,6 +1001,30 @@ DEF_ICON(MATCAP_22)
DEF_ICON(MATCAP_23)
DEF_ICON(MATCAP_24)
+/* grease pencil sculpt */
+DEF_ICON(GPBRUSH_SMOOTH)
+DEF_ICON(GPBRUSH_THICKNESS)
+DEF_ICON(GPBRUSH_STRENGTH)
+DEF_ICON(GPBRUSH_GRAB)
+DEF_ICON(GPBRUSH_PUSH)
+DEF_ICON(GPBRUSH_TWIST)
+DEF_ICON(GPBRUSH_PINCH)
+DEF_ICON(GPBRUSH_RANDOMIZE)
+DEF_ICON(GPBRUSH_CLONE)
+DEF_ICON(GPBRUSH_WEIGHT)
+
+DEF_ICON(GPBRUSH_PENCIL)
+DEF_ICON(GPBRUSH_PEN)
+DEF_ICON(GPBRUSH_INK)
+DEF_ICON(GPBRUSH_INKNOISE)
+DEF_ICON(GPBRUSH_BLOCK)
+DEF_ICON(GPBRUSH_MARKER)
+DEF_ICON(GPBRUSH_CUSTOM)
+DEF_ICON(GPBRUSH_FILL)
+DEF_ICON(GPBRUSH_ERASE_SOFT)
+DEF_ICON(GPBRUSH_ERASE_HARD)
+DEF_ICON(GPBRUSH_ERASE_STROKE)
+
/* vector icons, VICO_ prefix added */
DEF_VICO(SMALL_TRI_RIGHT_VEC)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 723dde640e4..824920bce73 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -772,7 +772,7 @@ typedef enum {
uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2);
eAutoPropButsReturn uiDefAutoButsRNA(
uiLayout *layout, struct PointerRNA *ptr,
- bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
+ bool (*check_prop)(struct PointerRNA *ptr, struct PropertyRNA *prop, void *user_data), void *user_data,
eButLabelAlign label_align, const bool compact);
/* use inside searchfunc to add items */
@@ -935,6 +935,7 @@ enum {
UI_TEMPLATE_OP_PROPS_SHOW_TITLE = (1 << 0),
UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = (1 << 1),
UI_TEMPLATE_OP_PROPS_COMPACT = (1 << 2),
+ UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = (1 << 3),
};
/* used for transp checkers */
@@ -1021,7 +1022,8 @@ uiLayout *uiLayoutRadial(uiLayout *layout);
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
void uiTemplateID(
uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
- const char *newop, const char *openop, const char *unlinkop, int filter);
+ const char *newop, const char *openop, const char *unlinkop,
+ int filter, const bool live_icon);
void uiTemplateIDBrowse(
uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop, int filter);
@@ -1051,6 +1053,12 @@ void uiTemplatePathBuilder(
uiLayout *layout, struct PointerRNA *ptr, const char *propname,
struct PointerRNA *root_ptr, const char *text);
uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
+uiLayout *uiTemplateGpencilModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
+void uiTemplateGpencilColorPreview(
+ uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
+ int rows, int cols, float scale, int filter);
+
+uiLayout *uiTemplateShaderFx(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplateOperatorRedoProperties(uiLayout *layout, const struct bContext *C);
@@ -1069,6 +1077,7 @@ void uiTemplateCurveMapping(
bool levels, bool brush, bool neg_slope);
void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool value_slider, bool lock, bool lock_luminosity, bool cubic);
void uiTemplatePalette(uiLayout *layout, struct PointerRNA *ptr, const char *propname, bool color);
+void uiTemplateCryptoPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateLayers(
uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
@@ -1084,7 +1093,6 @@ void UI_but_func_operator_search(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
eAutoPropButsReturn uiTemplateOperatorPropertyButs(
const struct bContext *C, uiLayout *layout, struct wmOperator *op,
- bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const eButLabelAlign label_align, const short flag);
void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C);
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
@@ -1193,7 +1201,7 @@ void ED_operatortypes_ui(void);
void ED_keymap_ui(struct wmKeyConfig *keyconf);
void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
-bool UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
+bool UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event, const char **tooltip);
bool UI_context_copy_to_selected_list(
struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
@@ -1265,7 +1273,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* ui_interface_region_tooltip.c */
struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but);
-struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *mpr);
+struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz);
void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar);
/* How long before a tool-tip shows. */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 651081c46bb..a34c4938b86 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -59,7 +59,7 @@ typedef struct IconFile {
/*
* Resizable Icons for Blender
*/
-void UI_icons_init(int first_dyn_id);
+void UI_icons_init(void);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 3e01c5f356f..37c56d454bb 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -280,7 +280,7 @@ static void ui_update_window_matrix(const wmWindow *window, const ARegion *regio
/* window matrix and aspect */
if (region && region->visible) {
/* Get projection matrix which includes View2D translation and zoom. */
- gpuGetProjectionMatrix(block->winmat);
+ GPU_matrix_projection_get(block->winmat);
block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]);
}
else {
@@ -1448,9 +1448,9 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_but_to_pixelrect(&rect, ar, block, NULL);
/* pixel space for AA widgets */
- gpuPushProjectionMatrix();
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
wmOrtho2_region_pixelspace(ar);
@@ -1485,8 +1485,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
BLF_batch_draw_end();
/* restore matrix */
- gpuPopProjectionMatrix();
- gpuPopMatrix();
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
}
static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block)
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 240649c8ab0..d00ab70562c 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -715,7 +715,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
/* Show header tools for header buttons. */
- if (ui_block_is_menu(but->block) == false) {
+ if (ui_block_is_popup_any(but->block) == false) {
ARegion *ar = CTX_wm_region(C);
if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 51f2c7e8ece..6a304a8150e 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -130,19 +130,19 @@ void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float
/* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
* If it has been scaled, then it's no longer valid. */
- Gwn_Batch *batch = ui_batch_roundbox_get(filled, true);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GWN_batch_draw(batch);
+ GPUBatch *batch = ui_batch_roundbox_get(filled, true);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
}
else {
/* plain antialiased unfilled box */
GPU_line_smooth(true);
- Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GWN_batch_draw(batch);
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
GPU_line_smooth(false);
}
@@ -159,8 +159,8 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
};
int a;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* mult */
for (a = 0; a < 7; a++) {
@@ -176,7 +176,7 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
- immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_len);
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
immVertex2f(pos, maxx - rad, miny);
@@ -244,10 +244,10 @@ void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float
.alpha_discard = 1.0f,
};
- Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GWN_batch_draw(batch);
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
}
#if 0
@@ -280,9 +280,9 @@ void UI_draw_roundbox_shade_x(
int vert_count = 0;
int a;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
@@ -304,7 +304,7 @@ void UI_draw_roundbox_shade_x(
vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
- immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
@@ -404,10 +404,10 @@ void UI_draw_roundbox_shade_x(
.alpha_discard = 1.0f,
};
- Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
- GWN_batch_draw(batch);
+ GPUBatch *batch = ui_batch_roundbox_get(filled, false);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GPU_batch_draw(batch);
}
#if 0 /* unused */
@@ -432,9 +432,9 @@ void UI_draw_roundbox_shade_y(
mul_v2_fl(vec[a], rad);
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
@@ -452,7 +452,7 @@ void UI_draw_roundbox_shade_y(
vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
- immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
@@ -535,8 +535,8 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo
{
int ofs_y = 4 * U.pixelsize;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
@@ -550,9 +550,9 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo
/* 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])
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
/* 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;
@@ -571,7 +571,7 @@ void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highligh
}
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBeginAtMost(GWN_PRIM_LINE_STRIP, 25);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, 25);
immAttrib3ubv(col, highlight);
@@ -685,8 +685,8 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
*
* \Note This functionn is to be used with the 2D dashed shader enabled.
*
- * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
- * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
+ * \param pos is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attrib
+ * \param line_origin is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attrib
*
* The next 4 parameters are the offsets for the view, not the zones.
*/
@@ -749,7 +749,7 @@ static void histogram_draw_one(
/* curve outline */
GPU_line_width(1.5);
- immBegin(GWN_PRIM_LINE_STRIP, res);
+ immBegin(GPU_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
immVertex2f(pos_attrib, x2, y + (data[i] * h));
@@ -758,7 +758,7 @@ static void histogram_draw_one(
}
else {
/* under the curve */
- immBegin(GWN_PRIM_TRI_STRIP, res * 2);
+ immBegin(GPU_PRIM_TRI_STRIP, res * 2);
immVertex2f(pos_attrib, x, y);
immVertex2f(pos_attrib, x, y + (data[0] * h));
for (int i = 1; i < res; i++) {
@@ -772,7 +772,7 @@ static void histogram_draw_one(
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immBegin(GWN_PRIM_LINE_STRIP, res);
+ immBegin(GPU_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
immVertex2f(pos_attrib, x2, y + (data[i] * h));
@@ -818,8 +818,8 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -833,7 +833,7 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
@@ -869,21 +869,21 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUS
static void waveform_draw_one(float *waveform, int nbr, const float col[3])
{
- Gwn_VertFormat format = {0};
- uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat format = {0};
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, nbr);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, nbr);
- GWN_vertbuf_attr_fill(vbo, pos_id, waveform);
+ GPU_vertbuf_attr_fill(vbo, pos_id, waveform);
- /* TODO store the Gwn_Batch inside the scope */
- Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
- GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
- GWN_batch_draw(batch);
+ /* TODO store the GPUBatch inside the scope */
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ GPU_batch_draw(batch);
- GWN_batch_discard(batch);
+ GPU_batch_discard(batch);
}
void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
@@ -957,15 +957,15 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid lines here */
- immBegin(GWN_PRIM_LINES, 12);
+ immBegin(GPU_PRIM_LINES, 12);
for (int i = 0; i < 6; i++) {
immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
@@ -976,7 +976,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
/* 3 vertical separation */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
for (int i = 1; i < 3; i++) {
immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
@@ -987,7 +987,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
}
/* separate min max zone on the right */
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, rect.xmin + w, rect.ymin);
immVertex2f(pos, rect.xmin + w, rect.ymax);
immEnd();
@@ -995,7 +995,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
/* 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)) {
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
@@ -1013,7 +1013,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
}
/* 7.5 IRE black point level for NTSC */
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
immEnd();
@@ -1027,13 +1027,13 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
float col[3] = {alpha, alpha, alpha};
- gpuPushMatrix();
- gpuTranslate2f(rect.xmin, yofs);
- gpuScale2f(w, h);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(w, h);
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
- gpuPopMatrix();
+ GPU_matrix_pop();
/* min max */
immUniformColor3f(0.5f, 0.5f, 0.5f);
@@ -1042,22 +1042,22 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_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();
- gpuTranslate2f(rect.xmin, yofs);
- gpuScale2f(w, h);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(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]);
waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* PARADE / YCC (3 channels) */
else if (ELEM(scopes->wavefrm_mode,
@@ -1069,19 +1069,19 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
{
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
- gpuPushMatrix();
- gpuTranslate2f(rect.xmin, yofs);
- gpuScale2f(w3, h);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(rect.xmin, yofs);
+ GPU_matrix_scale_2f(w3, h);
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- gpuTranslate2f(1.0f, 0.0f);
+ GPU_matrix_translate_2f(1.0f, 0.0f);
waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- gpuTranslate2f(1.0f, 0.0f);
+ GPU_matrix_translate_2f(1.0f, 0.0f);
waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* min max */
@@ -1096,7 +1096,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSE
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
immEnd();
@@ -1140,7 +1140,7 @@ static void vectorscope_draw_target(unsigned int pos, float centerx, float cente
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
dangle = DEG2RADF(2.5f);
dampli = 2.5f / 200.0f;
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
@@ -1152,22 +1152,22 @@ static void vectorscope_draw_target(unsigned int pos, float centerx, float cente
dampli = 0.2f * tampli;
dangle2 = DEG2RADF(5.0f);
dampli2 = 0.5f * dampli;
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
immEnd();
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
immEnd();
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
immEnd();
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
@@ -1215,15 +1215,15 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid elements */
/* cross */
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
@@ -1236,7 +1236,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
/* circles */
for (int j = 0; j < 5; j++) {
const int increment = 15;
- immBegin(GWN_PRIM_LINE_LOOP, (int)(360 / increment));
+ immBegin(GPU_PRIM_LINE_LOOP, (int)(360 / increment));
for (int i = 0; i <= 360 - increment; i += increment) {
const float a = DEG2RADF((float)i);
const float r = (j + 1) * 0.1f;
@@ -1247,7 +1247,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
/* skin tone line */
immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_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();
@@ -1263,13 +1263,13 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UN
glBlendFunc(GL_ONE, GL_ONE);
GPU_point_size(1.0);
- gpuPushMatrix();
- gpuTranslate2f(centerx, centery);
- gpuScaleUniform(diam);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(centerx, centery);
+ GPU_matrix_scale_1f(diam);
waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
immUnbindProgram();
@@ -1284,7 +1284,7 @@ static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, floa
{
GPU_line_smooth(true);
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2f(pos, x1 + halfwidth, y1);
immVertex2f(pos, x1, y1 + height);
immVertex2f(pos, x1 - halfwidth, y1);
@@ -1297,7 +1297,7 @@ static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, f
{
glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
- immBegin(fill ? GWN_PRIM_TRIS : GWN_PRIM_LINE_LOOP, 3);
+ immBegin(fill ? GPU_PRIM_TRIS : GPU_PRIM_LINE_LOOP, 3);
immVertex2f(pos, x1 + halfwidth, y1);
immVertex2f(pos, x1, y1 + height);
immVertex2f(pos, x1 - halfwidth, y1);
@@ -1308,7 +1308,7 @@ static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, f
static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill)
{
- immBegin(fill ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
+ immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x1, y2);
immVertex2f(pos, x2, y2);
@@ -1348,7 +1348,7 @@ static void ui_draw_colorband_handle(
immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
immUniform1f("dash_width", active ? 4.0f : 2.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(shdr_pos, x, y1);
immVertex2f(shdr_pos, x, y2);
immEnd();
@@ -1419,8 +1419,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
float sizey_solid = sizey * 0.25f;
float y1 = rect->ymin;
- Gwn_VertFormat *format = immVertexFormat();
- pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
/* Drawing the checkerboard. */
@@ -1432,8 +1432,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
/* New format */
format = immVertexFormat();
- pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- col_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* layer: color ramp */
@@ -1447,7 +1447,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
- immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
+ immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1466,7 +1466,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1;
v2[1] = y1 + sizey_solid;
- immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
+ immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1487,7 +1487,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
/* New format */
format = immVertexFormat();
- pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* layer: box outline */
@@ -1498,14 +1498,14 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
GPU_blend(true);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos_id, x1, y1);
immVertex2f(pos_id, x1 + sizex, y1);
immEnd();
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos_id, x1, y1 - 1);
immVertex2f(pos_id, x1 + sizex, y1 - 1);
immEnd();
@@ -1548,28 +1548,28 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
ui_but_v3_get(but, light);
/* transform to button */
- gpuPushMatrix();
+ GPU_matrix_push();
if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
size = 0.5f * BLI_rcti_size_x(rect);
else
size = 0.5f * BLI_rcti_size_y(rect);
- gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
- gpuScaleUniform(size);
+ GPU_matrix_translate_2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
+ GPU_matrix_scale_1f(size);
- Gwn_Batch *sphere = GPU_batch_preset_sphere(2);
- GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
- GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
- GWN_batch_uniform_3fv(sphere, "light", light);
- GWN_batch_draw(sphere);
+ GPUBatch *sphere = GPU_batch_preset_sphere(2);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ GPU_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
+ GPU_batch_uniform_3fv(sphere, "light", light);
+ GPU_batch_draw(sphere);
/* restore */
glDisable(GL_CULL_FACE);
/* AA circle */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv((unsigned char *)wcol->inner);
@@ -1580,7 +1580,7 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
GPU_line_smooth(false);
/* matrix after circle */
- gpuPopMatrix();
+ GPU_matrix_pop();
immUnbindProgram();
}
@@ -1599,7 +1599,7 @@ static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoo
floorf((rect->xmax - fx) / dx) + 1.0f +
floorf((rect->ymax - fy) / dy) + 1.0f);
- immBegin(GWN_PRIM_LINES, (int)line_count * 2);
+ immBegin(GPU_PRIM_LINES, (int)line_count * 2);
while (fx < rect->xmax) {
immVertex2f(pos, fx, rect->ymin);
immVertex2f(pos, fx, rect->ymax);
@@ -1675,8 +1675,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
GPU_line_width(1.0f);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* backdrop */
@@ -1712,7 +1712,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
/* axes */
gl_shaded_color((unsigned char *)wcol->inner, -50);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
@@ -1725,7 +1725,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
#if 0
if (cumap->flag & CUMA_DRAW_CFRA) {
immUniformColor3ub(0x60, 0xc0, 0x40);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
immEnd();
@@ -1734,7 +1734,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* sample option */
if (cumap->flag & CUMA_DRAW_SAMPLE) {
- immBegin(GWN_PRIM_LINES, 2); /* will draw one of the following 3 lines */
+ immBegin(GPU_PRIM_LINES, 2); /* will draw one of the following 3 lines */
if (but->a1 == UI_GRAD_H) {
float tsample[3];
float hsv[3];
@@ -1770,7 +1770,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
immUniformColor3ubv((unsigned char *)wcol->item);
GPU_line_smooth(true);
GPU_blend(true);
- immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
+ immBegin(GPU_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
if (cuma->table == NULL)
curvemapping_changed(cumap, false);
@@ -1807,13 +1807,13 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* the points, use aspect to make them visible on edges */
format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
cmp = cuma->curve;
GPU_point_size(3.0f);
- immBegin(GWN_PRIM_POINTS, cuma->totpoint);
+ immBegin(GPU_PRIM_POINTS, cuma->totpoint);
for (int a = 0; a < cuma->totpoint; a++) {
float color[4];
if (cmp[a].flag & CUMA_SELECT)
@@ -1833,7 +1833,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* outline */
format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv((unsigned char *)wcol->outline);
@@ -1900,7 +1900,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
}
if (!ok && scopes->track_preview) {
- gpuPushMatrix();
+ GPU_matrix_push();
/* draw content of pattern area */
GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
@@ -1919,23 +1919,23 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
immDrawPixelsTex(&state, 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 */
- gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
+ GPU_matrix_translate_2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
GPU_scissor(
rect.xmin,
rect.ymin,
BLI_rctf_size_x(&rect),
BLI_rctf_size_y(&rect));
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
/* Do stipple cross with geometry */
- immBegin(GWN_PRIM_LINES, 7 * 2 * 2);
+ immBegin(GPU_PRIM_LINES, 7 * 2 * 2);
float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
for (int axe = 0; axe < 2; ++axe) {
for (int i = 0; i < 7; ++i) {
@@ -1958,7 +1958,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *U
immUnbindProgram();
}
- gpuPopMatrix();
+ GPU_matrix_pop();
ok = true;
}
@@ -2018,13 +2018,13 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
float x = 0.5f * (recti->xmin + recti->xmax);
float y = 0.5f * (recti->ymin + recti->ymax);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(but->col);
GPU_blend(true);
- immBegin(GWN_PRIM_TRI_FAN, 16);
+ immBegin(GPU_PRIM_TRI_FAN, 16);
for (int a = 0; a < 16; a++)
immVertex2f(pos, x + size * si[a], y + size * co[a]);
immEnd();
@@ -2032,7 +2032,7 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
immUniformColor4ub(0, 0, 0, 150);
GPU_line_width(1);
GPU_line_smooth(true);
- immBegin(GWN_PRIM_LINE_LOOP, 16);
+ immBegin(GPU_PRIM_LINE_LOOP, 16);
for (int a = 0; a < 16; a++)
immVertex2f(pos, x + size * si[a], y + size * co[a]);
immEnd();
@@ -2115,13 +2115,13 @@ void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx,
{
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(GWN_PRIM_TRIS, 54);
+ immBegin(GPU_PRIM_TRIS, 54);
/* accumulated outline boxes to make shade not linear, is more pleasant */
ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
@@ -2186,11 +2186,11 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
.alpha_discard = 1.0f,
};
- Gwn_Batch *batch = ui_batch_roundbox_shadow_get();
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
- GWN_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
- GWN_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
- GWN_batch_draw(batch);
+ GPUBatch *batch = ui_batch_roundbox_shadow_get();
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
+ GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
+ GPU_batch_draw(batch);
/* outline emphasis */
GPU_line_smooth(true);
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index eb8fff471e2..424019995ad 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -82,6 +82,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
/* assign to operators */
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorband");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_color");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_color_crypto");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver");
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 73efc59feb7..bcce70d9d8a 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -36,6 +36,7 @@
#include "DNA_screen_types.h"
#include "BLI_math_vector.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -72,6 +73,8 @@ typedef struct Eyedropper {
bool accum_start; /* has mouse been pressed */
float accum_col[3];
int accum_tot;
+
+ bool accumulate; /* Color picking for cryptomatte, without accumulation. */
} Eyedropper;
static bool eyedropper_init(bContext *C, wmOperator *op)
@@ -80,6 +83,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
Eyedropper *eye;
op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
+ eye->accumulate = !STREQ(op->type->idname, "UI_OT_eyedropper_color_crypto");
UI_context_active_but_prop_get(C, &eye->ptr, &eye->prop, &eye->index);
@@ -207,29 +211,30 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3
RNA_property_update(C, &eye->ptr, eye->prop);
}
-/* set sample from accumulated values */
-static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
-{
- float col[3];
- mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot);
- eyedropper_color_set(C, eye, col);
-}
-
-/* single point sample & set */
static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
{
+ /* Accumulate color. */
float col[3];
eyedropper_color_sample_fl(C, mx, my, col);
- eyedropper_color_set(C, eye, col);
-}
-static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
-{
- float col[3];
- eyedropper_color_sample_fl(C, mx, my, col);
- /* delay linear conversion */
- add_v3_v3(eye->accum_col, col);
- eye->accum_tot++;
+ if (eye->accumulate) {
+ add_v3_v3(eye->accum_col, col);
+ eye->accum_tot++;
+ }
+ else {
+ copy_v3_v3(eye->accum_col, col);
+ eye->accum_tot = 1;
+ }
+
+ /* Apply to property. */
+ float accum_col[3];
+ if (eye->accum_tot > 1) {
+ mul_v3_v3fl(accum_col, eye->accum_col, 1.0f / (float)eye->accum_tot);
+ }
+ else {
+ copy_v3_v3(accum_col, eye->accum_col);
+ }
+ eyedropper_color_set(C, eye, accum_col);
}
static void eyedropper_cancel(bContext *C, wmOperator *op)
@@ -254,29 +259,24 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (eye->accum_tot == 0) {
eyedropper_color_sample(C, eye, event->x, event->y);
}
- else {
- eyedropper_color_set_accum(C, eye);
- }
eyedropper_exit(C, op);
return OPERATOR_FINISHED;
case EYE_MODAL_SAMPLE_BEGIN:
/* enable accum and make first sample */
eye->accum_start = true;
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ eyedropper_color_sample(C, eye, event->x, event->y);
break;
case EYE_MODAL_SAMPLE_RESET:
eye->accum_tot = 0;
zero_v3(eye->accum_col);
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
+ eyedropper_color_sample(C, eye, event->x, event->y);
break;
}
}
- else if (event->type == MOUSEMOVE) {
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
if (eye->accum_start) {
/* button is pressed so keep sampling */
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
+ eyedropper_color_sample(C, eye, event->x, event->y);
}
}
@@ -297,7 +297,7 @@ static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
}
else {
eyedropper_exit(C, op);
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
}
@@ -315,26 +315,15 @@ static int eyedropper_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
else {
- return OPERATOR_CANCELLED;
+ return OPERATOR_PASS_THROUGH;
}
}
static bool eyedropper_poll(bContext *C)
{
- PointerRNA ptr;
- PropertyRNA *prop;
- int index_dummy;
- uiBut *but;
-
- /* Only color buttons */
- if ((CTX_wm_window(C) != NULL) &&
- (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
- (but->type == UI_BTYPE_COLOR))
- {
- return 1;
- }
-
- return 0;
+ /* Actual test for active button happens later, since we don't
+ * know which one is active until mouse over. */
+ return (CTX_wm_window(C) != NULL);
}
void UI_OT_eyedropper_color(wmOperatorType *ot)
@@ -353,6 +342,22 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
+}
+
+void UI_OT_eyedropper_color_crypto(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Cryptomatte Eyedropper";
+ ot->idname = "UI_OT_eyedropper_color_crypto";
+ ot->description = "Pick a color from Cryptomatte node Pick output image";
- /* properties */
+ /* api callbacks */
+ ot->invoke = eyedropper_invoke;
+ ot->modal = eyedropper_modal;
+ ot->cancel = eyedropper_cancel;
+ ot->exec = eyedropper_exec;
+ ot->poll = eyedropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 62413e2434c..4f77b797ec0 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -47,6 +47,7 @@
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_dynamicpaint_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -109,6 +110,7 @@ typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
#define ICON_TYPE_VECTOR 4
#define ICON_TYPE_GEOM 5
#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */
+#define ICON_TYPE_GPLAYER 7
typedef struct DrawInfo {
int type;
@@ -250,11 +252,11 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float
viconutil_set_point(pts[1], cx - d2, cy - d);
viconutil_set_point(pts[2], cx + d2, cy);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.2f, 0.2f, 0.2f, alpha);
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
immVertex2iv(pos, pts[0]);
immVertex2iv(pos, pts[1]);
immVertex2iv(pos, pts[2]);
@@ -280,15 +282,15 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
int xco = x + w / 2;
int yco = y + h / 2;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
/* draw keyframe
* - size: 0.6 * h (found out experimentally... dunno why!)
@@ -343,7 +345,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU
const int b = x + w / 3 * 2;
const int c = x + w;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* XXX: Include alpha into this... */
@@ -391,6 +393,28 @@ DEF_VICON_COLORSET_DRAW_NTH(20, 19)
#undef DEF_VICON_COLORSET_DRAW_NTH
+/* Dynamically render icon instead of rendering a plain color to a texture/buffer
+ * This is mot strictly a "vicon", as it needs access to icon->obj to get the color info,
+ * but it works in a very similar way.
+ */
+static void vicon_gplayer_color_draw(Icon *icon, int x, int y, int w, int h)
+{
+ bGPDlayer *gpl = (bGPDlayer *)icon->obj;
+
+ /* Just draw a colored rect - Like for vicon_colorset_draw() */
+ /* TODO: Make this have rounded corners, and maybe be a bit smaller.
+ * However, UI_draw_roundbox_aa() draws the colors too dark, so can't be used.
+ */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3fv(gpl->color);
+ immRecti(pos, x, y, x + w - 1, y + h - 1);
+
+ immUnbindProgram();
+}
+
+
#ifndef WITH_HEADLESS
static void init_brush_icons(void)
@@ -443,6 +467,30 @@ static void init_brush_icons(void)
INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
+ /* grease pencil sculpt */
+ INIT_BRUSH_ICON(ICON_GPBRUSH_SMOOTH, gp_brush_smooth);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_THICKNESS, gp_brush_thickness);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_STRENGTH, gp_brush_strength);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_GRAB, gp_brush_grab);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PUSH, gp_brush_push);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_TWIST, gp_brush_twist);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PINCH, gp_brush_pinch);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_RANDOMIZE, gp_brush_randomize);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_CLONE, gp_brush_clone);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_WEIGHT, gp_brush_weight);
+
+ /* grease pencil drawing brushes */
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PENCIL, gp_brush_pencil);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_PEN, gp_brush_pen);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_INK, gp_brush_ink);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_INKNOISE, gp_brush_inknoise);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_BLOCK, gp_brush_block);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_MARKER, gp_brush_marker);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_FILL, gp_brush_fill);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_SOFT, gp_brush_erase_soft);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_HARD, gp_brush_erase_hard);
+ INIT_BRUSH_ICON(ICON_GPBRUSH_ERASE_STROKE, gp_brush_erase_stroke);
+
#undef INIT_BRUSH_ICON
}
@@ -877,6 +925,9 @@ static DrawInfo *icon_create_drawinfo(Icon *icon)
else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
di->type = ICON_TYPE_BUFFER;
}
+ else if (icon_data_type == ICON_DATA_GPLAYER) {
+ di->type = ICON_TYPE_GPLAYER;
+ }
else {
BLI_assert(0);
}
@@ -934,9 +985,8 @@ int UI_icon_get_height(int icon_id)
return 0;
}
-void UI_icons_init(int first_dyn_id)
+void UI_icons_init()
{
- BKE_icons_init(first_dyn_id);
#ifndef WITH_HEADLESS
init_iconfile_list(&iconfilelist);
init_internal_icons();
@@ -1262,7 +1312,7 @@ static void icon_draw_cache_flush_ex(void)
glUniform1i(img_loc, 0);
glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
- GWN_draw_primitive(GWN_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+ GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -1292,7 +1342,7 @@ static void icon_draw_texture_cached(
{
float mvp[4][4];
- gpuGetModelViewProjectionMatrix(mvp);
+ GPU_matrix_model_view_projection_get(mvp);
IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
g_icon_draw_cache.calls++;
@@ -1342,14 +1392,14 @@ static void icon_draw_texture(
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
GPU_shader_bind(shader);
- if (rgb) glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
- else glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
+ if (rgb) glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
+ else glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h);
- GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
+ GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -1485,6 +1535,15 @@ static void icon_draw_size(
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
}
+ else if (di->type == ICON_TYPE_GPLAYER) {
+ BLI_assert(icon->obj != NULL);
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ /* Just draw a colored rect - Like for vicon_colorset_draw() */
+ vicon_gplayer_color_draw(icon, (int)x, (int)y, w, h);
+ }
}
static void ui_id_preview_image_render_size(
@@ -1577,7 +1636,45 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
}
/* reset the icon */
- if (mode == OB_MODE_SCULPT) {
+ if (ob->mode & OB_MODE_GPENCIL_PAINT) {
+ switch (br->gpencil_settings->icon_id) {
+ case GP_BRUSH_ICON_PENCIL:
+ br->id.icon_id = ICON_GPBRUSH_PENCIL;
+ break;
+ case GP_BRUSH_ICON_PEN:
+ br->id.icon_id = ICON_GPBRUSH_PEN;
+ break;
+ case GP_BRUSH_ICON_INK:
+ br->id.icon_id = ICON_GPBRUSH_INK;
+ break;
+ case GP_BRUSH_ICON_INKNOISE:
+ br->id.icon_id = ICON_GPBRUSH_INKNOISE;
+ break;
+ case GP_BRUSH_ICON_BLOCK:
+ br->id.icon_id = ICON_GPBRUSH_BLOCK;
+ break;
+ case GP_BRUSH_ICON_MARKER:
+ br->id.icon_id = ICON_GPBRUSH_MARKER;
+ break;
+ case GP_BRUSH_ICON_FILL:
+ br->id.icon_id = ICON_GPBRUSH_FILL;
+ break;
+ case GP_BRUSH_ICON_ERASE_SOFT:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_SOFT;
+ break;
+ case GP_BRUSH_ICON_ERASE_HARD:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_HARD;
+ break;
+ case GP_BRUSH_ICON_ERASE_STROKE:
+ br->id.icon_id = ICON_GPBRUSH_ERASE_STROKE;
+ break;
+ default:
+ br->id.icon_id = ICON_GPBRUSH_PEN;
+ break;
+ }
+ return id->icon_id;
+ }
+ else if (mode == OB_MODE_SCULPT) {
items = rna_enum_brush_sculpt_tool_items;
tool = br->sculpt_tool;
}
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index dc444b98b2c..fabf5f9bf48 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -136,8 +136,8 @@ static void icon_draw_rect_input_line_prim(
{
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- BLI_assert(ELEM(prim, GWN_PRIM_LINE_LOOP, GWN_PRIM_LINE_STRIP));
- const uint pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ BLI_assert(ELEM(prim, GPU_PRIM_LINE_LOOP, GPU_PRIM_LINE_STRIP));
+ const uint pos_id = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
immBegin(prim, lines_len);
@@ -289,7 +289,7 @@ void icon_draw_rect_input(
else if (event_type == SPACEKEY) {
const uchar lines[] = {60, 118, 60, 60, 195, 60, 195, 118};
icon_draw_rect_input_line_prim(
- &rect, color, GWN_PRIM_LINE_STRIP,
+ &rect, color, GPU_PRIM_LINE_STRIP,
(const void *)lines, ARRAY_SIZE(lines) / 2);
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index ffc389c6dfd..f7507223f31 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -752,9 +752,9 @@ enum {
ROUNDBOX_TRIA_MAX, /* don't use */
};
-struct Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased);
-struct Gwn_Batch *ui_batch_roundbox_widget_get(int tria);
-struct Gwn_Batch *ui_batch_roundbox_shadow_get(void);
+struct GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased);
+struct GPUBatch *ui_batch_roundbox_widget_get(int tria);
+struct GPUBatch *ui_batch_roundbox_shadow_get(void);
void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4]);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
@@ -780,7 +780,7 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na
#define UI_POPUP_MENU_TOP (int)(8 * UI_DPI_FAC)
#define UI_PIXEL_AA_JITTER 8
-const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2];
+extern const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2];
/* interface_style.c */
void uiStyleInit(void);
@@ -831,7 +831,9 @@ bool ui_but_is_toggle(const uiBut *but);
bool ui_but_is_popover_once_compat(const uiBut *but);
extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
/* interface_context_menu.c */
bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
@@ -843,6 +845,7 @@ struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf);
/* interface_eyedropper_color.c */
void UI_OT_eyedropper_color(struct wmOperatorType *ot);
+void UI_OT_eyedropper_color_crypto(struct wmOperatorType *ot);
/* interface_eyedropper_colorband.c */
void UI_OT_eyedropper_colorband(struct wmOperatorType *ot);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 82ed4c5acba..f143d418fe3 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1244,7 +1244,15 @@ void uiItemsFullEnumO(
bool free;
if (ui_layout_is_radial(layout)) {
+ /* XXX: While "_all()" guarantees spatial stability, it's bad when an enum has > 8 items total,
+ * but only a small subset will ever be shown at once (e.g. Mode Switch menu, after the
+ * introduction of GP editing modes)
+ */
+#if 0
RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
+#else
+ RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
+#endif
}
else {
RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, &totitem, &free);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 96128aa29f0..ae0fe912f95 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1243,7 +1243,7 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
ot->exec = reloadtranslation_exec;
}
-bool UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
+bool UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
/* should only return true for regions that include buttons, for now
* return true always */
@@ -1359,6 +1359,7 @@ void ED_operatortypes_ui(void)
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
+ WM_operatortype_append(UI_OT_eyedropper_color_crypto);
WM_operatortype_append(UI_OT_eyedropper_colorband);
WM_operatortype_append(UI_OT_eyedropper_colorband_point);
WM_operatortype_append(UI_OT_eyedropper_id);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 79d92eedfa3..aa67d58fd57 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -454,9 +454,9 @@ static void ui_offset_panel_block(uiBlock *block)
/* triangle 'icon' for panel header */
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;
+ float f3 = 0.05 * U.widget_unit;
+ float f5 = 0.15 * U.widget_unit;
+ float f7 = 0.25 * U.widget_unit;
if (dir == 'h') {
UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
@@ -478,7 +478,7 @@ static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y2);
@@ -519,7 +519,7 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
GPU_blend(true);
immUniformColor4ub(255, 255, 255, 50);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, xmin, ymin);
immVertex2f(pos, xmax, ymax);
@@ -531,7 +531,7 @@ static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
immUniformColor4ub(0, 0, 0, 50);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, xmin, ymin + 1);
immVertex2f(pos, xmax, ymax + 1);
@@ -584,7 +584,7 @@ static void ui_draw_panel_dragwidget(unsigned int pos, unsigned int col, const r
UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
/* draw multiple boxes */
- immBegin(GWN_PRIM_TRIS, 4 * 2 * (6 * 2));
+ immBegin(GPU_PRIM_TRIS, 4 * 2 * (6 * 2));
for (i_x = 0; i_x < 4; i_x++) {
for (i_y = 0; i_y < 2; i_y++) {
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
@@ -677,7 +677,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
titlerect.xmin += 5.0f / block->aspect;
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (!is_subpanel) {
@@ -691,7 +691,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
immUniformThemeColor(TH_PANEL_HEADER);
immRectf(pos, minx, headrect.ymin, maxx, y);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, minx, y);
immVertex2f(pos, maxx, y);
@@ -729,9 +729,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (show_drag) {
uint col;
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
/* itemrect smaller */
itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
@@ -745,7 +745,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
immUnbindProgram();
/* Restore format for the following draws. */
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
}
@@ -758,7 +758,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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
/* an open panel */
else {
@@ -1700,9 +1700,9 @@ static void ui_panel_category_draw_tab(
{0.98, 0.805}};
int a;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
/* mult */
for (a = 0; a < 4; a++) {
@@ -1724,7 +1724,7 @@ static void ui_panel_category_draw_tab(
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_len);
+ immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_STRIP, vert_len);
/* start with corner right-top */
if (use_highlight) {
@@ -1929,7 +1929,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* begin drawing */
GPU_line_smooth(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* draw the background */
@@ -1991,7 +1991,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* tab blackline */
if (!is_active) {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv(theme_col_tab_divider);
@@ -2022,7 +2022,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
GPU_blend(false);
/* tab blackline remaining (last tab) */
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (pc_dyn->prev == NULL) {
immUniformColor3ubv(theme_col_tab_divider);
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index 66f63fef82d..d0f7e1341de 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -109,11 +109,25 @@ bool ui_block_is_menu(const uiBlock *block)
((block->flag & UI_BLOCK_KEEP_OPEN) == 0));
}
+bool ui_block_is_popover(const uiBlock *block)
+{
+ return (block->flag & UI_BLOCK_POPOVER) != 0;
+}
+
bool ui_block_is_pie_menu(const uiBlock *block)
{
return ((block->flag & UI_BLOCK_RADIAL) != 0);
}
+bool ui_block_is_popup_any(const uiBlock *block)
+{
+ return (
+ ui_block_is_menu(block) ||
+ ui_block_is_popover(block) ||
+ ui_block_is_pie_menu(block)
+ );
+}
+
bool UI_block_is_empty(const uiBlock *block)
{
for (const uiBut *but = block->buttons.first; but; but = but->next) {
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index fae547d460c..97f501b7448 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -615,7 +615,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
-static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *mpr)
+static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
{
uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
@@ -623,23 +623,23 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *mpr)
/* Operator Actions */
{
- bool use_drag = mpr->drag_part != -1 && mpr->highlight_part != mpr->drag_part;
+ bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
const struct {
int part;
const char *prefix;
} mpop_actions[] = {
{
- .part = mpr->highlight_part,
+ .part = gz->highlight_part,
.prefix = use_drag ? TIP_("Click") : NULL,
}, {
- .part = use_drag ? mpr->drag_part : -1,
+ .part = use_drag ? gz->drag_part : -1,
.prefix = use_drag ? TIP_("Drag") : NULL,
},
};
for (int i = 0; i < ARRAY_SIZE(mpop_actions); i++) {
- wmGizmoOpElem *mpop = (mpop_actions[i].part != -1) ? WM_gizmo_operator_get(mpr, mpop_actions[i].part) : NULL;
+ wmGizmoOpElem *mpop = (mpop_actions[i].part != -1) ? WM_gizmo_operator_get(gz, mpop_actions[i].part) : NULL;
if (mpop != NULL) {
/* Description */
const char *info = RNA_struct_ui_description(mpop->type->srna);
@@ -691,13 +691,13 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *mpr)
}
/* Property Actions */
- if (mpr->type->target_property_defs_len) {
- wmGizmoProperty *mpr_prop_array = WM_gizmo_target_property_array(mpr);
- for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ if (gz->type->target_property_defs_len) {
+ wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
/* TODO(campbell): function callback descriptions. */
- wmGizmoProperty *mpr_prop = &mpr_prop_array[i];
- if (mpr_prop->prop != NULL) {
- const char *info = RNA_property_ui_description(mpr_prop->prop);
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (gz_prop->prop != NULL) {
+ const char *info = RNA_property_ui_description(gz_prop->prop);
if (info && info[0]) {
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
@@ -934,13 +934,13 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
return ui_tooltip_create_with_data(C, data, init_position, aspect);
}
-ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *mpr)
+ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
{
wmWindow *win = CTX_wm_window(C);
const float aspect = 1.0f;
float init_position[2];
- uiTooltipData *data = ui_tooltip_data_from_gizmo(C, mpr);
+ uiTooltipData *data = ui_tooltip_data_from_gizmo(C, gz);
if (data == NULL) {
return NULL;
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 36ad516bf7f..ed4c766c596 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -522,6 +522,35 @@ void uiStyleInit(void)
BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
+ /* Set default flags based on UI preferences (not render fonts) */
+ {
+ int flag_enable = 0, flag_disable = 0;
+ if ((U.text_render & USER_TEXT_DISABLE_HINTING) == 0) {
+ flag_enable |= BLF_HINTING;
+ }
+ else {
+ flag_disable |= BLF_HINTING;
+ }
+
+ if (U.text_render & USER_TEXT_DISABLE_AA) {
+ flag_enable |= BLF_MONOCHROME;
+ }
+ else {
+ flag_disable |= BLF_MONOCHROME;
+ }
+
+ for (font = U.uifonts.first; font; font = font->next) {
+ if (font->blf_id != -1) {
+ BLF_enable(font->blf_id, flag_enable);
+ BLF_disable(font->blf_id, flag_disable);
+ }
+ }
+ if (blf_mono_font != -1) {
+ BLF_enable(blf_mono_font, flag_enable);
+ BLF_disable(blf_mono_font, flag_disable);
+ }
+ }
+
/**
* Second for rendering else we get threading problems,
*
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 6110d5f3466..e81ad1428d1 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -39,6 +39,8 @@
#include "DNA_object_force_types.h"
#include "DNA_brush_types.h"
#include "DNA_texture_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_shader_fx_types.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
@@ -57,6 +59,7 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
@@ -71,6 +74,7 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "BKE_shader_fx.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -110,7 +114,7 @@ static void template_add_button_search_menu(
const bContext *C, uiLayout *layout, uiBlock *block,
PointerRNA *ptr, PropertyRNA *prop,
uiBlockCreateFunc block_func, void *block_argN, const char * const tip,
- const bool use_previews, const bool editable)
+ const bool use_previews, const bool editable, const bool live_icon)
{
PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL;
@@ -146,7 +150,14 @@ static void template_add_button_search_menu(
}
else {
but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip);
- ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+
+ if (live_icon) {
+ int icon = id ? ui_id_icon_get(C, id, false) : 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);
+ }
if (id) {
/* default dragging of icon for id browse buttons */
UI_but_drag_set_id(but, id);
@@ -162,7 +173,8 @@ static uiBlock *template_common_search_menu(
const bContext *C, ARegion *region,
uiButSearchFunc search_func, void *search_arg,
uiButHandleFunc handle_func, void *active_item,
- const int preview_rows, const int preview_cols)
+ const int preview_rows, const int preview_cols,
+ float scale)
{
static char search[256];
wmWindow *win = CTX_wm_window(C);
@@ -177,8 +189,8 @@ static uiBlock *template_common_search_menu(
/* preview thumbnails */
if (preview_rows > 0 && preview_cols > 0) {
- const int w = 4 * U.widget_unit * preview_cols;
- const int h = 5 * U.widget_unit * preview_rows;
+ const int w = 4 * U.widget_unit * preview_cols * scale;
+ const int h = 5 * U.widget_unit * preview_rows * scale;
/* fake button, it holds space for search items */
uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
@@ -237,6 +249,7 @@ typedef struct TemplateID {
short filter;
int prv_rows, prv_cols;
bool preview;
+ float scale;
} TemplateID;
/* Search browse menu, assign */
@@ -382,7 +395,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
return template_common_search_menu(
C, ar, id_search_cb_p, &template_ui, template_ID_set_property_cb, active_item_ptr.data,
- template_ui.prv_rows, template_ui.prv_cols);
+ template_ui.prv_rows, template_ui.prv_cols, template_ui.scale);
}
/************************ ID Template ***************************/
@@ -630,7 +643,8 @@ static uiBut *template_id_def_new_but(
static void template_ID(
bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag,
- const char *newop, const char *openop, const char *unlinkop)
+ const char *newop, const char *openop, const char *unlinkop,
+ const bool live_icon)
{
uiBut *but;
uiBlock *block;
@@ -655,7 +669,7 @@ static void template_ID(
template_add_button_search_menu(
C, layout, block, &template_ui->ptr, template_ui->prop,
id_search_menu, MEM_dupallocN(template_ui), TIP_(template_id_browse_tip(type)),
- use_previews, editable);
+ use_previews, editable, live_icon);
}
/* text button with name */
@@ -860,7 +874,8 @@ static void ui_template_id(
uiLayout *layout, bContext *C,
PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop,
- int flag, int prv_rows, int prv_cols, int filter, bool use_tabs)
+ int flag, int prv_rows, int prv_cols, int filter, bool use_tabs,
+ float scale, bool live_icon)
{
TemplateID *template_ui;
PropertyRNA *prop;
@@ -879,6 +894,7 @@ static void ui_template_id(
template_ui->prop = prop;
template_ui->prv_rows = prv_rows;
template_ui->prv_cols = prv_cols;
+ template_ui->scale = scale;
if ((flag & UI_ID_PIN) == 0) {
template_ui->filter = filter;
@@ -907,7 +923,7 @@ static void ui_template_id(
}
else {
uiLayoutRow(layout, true);
- template_ID(C, layout, template_ui, type, flag, newop, openop, unlinkop);
+ template_ID(C, layout, template_ui, type, flag, newop, openop, unlinkop, live_icon);
}
}
@@ -916,13 +932,14 @@ static void ui_template_id(
void uiTemplateID(
uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int filter)
+ const char *openop, const char *unlinkop,
+ int filter, const bool live_icon)
{
ui_template_id(
layout, C, ptr, propname,
newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
- 0, 0, filter, false);
+ 0, 0, filter, false, 1.0f, live_icon);
}
void uiTemplateIDBrowse(
@@ -933,7 +950,7 @@ void uiTemplateIDBrowse(
layout, C, ptr, propname,
newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME,
- 0, 0, filter, false);
+ 0, 0, filter, false, 1.0f, false);
}
void uiTemplateIDPreview(
@@ -944,7 +961,18 @@ void uiTemplateIDPreview(
layout, C, ptr, propname,
newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
- rows, cols, filter, false);
+ rows, cols, filter, false, 1.0f, false);
+}
+
+void uiTemplateGpencilColorPreview(
+ uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname,
+ int rows, int cols, float scale, int filter)
+{
+ ui_template_id(
+ layout, C, ptr, propname,
+ NULL, NULL, NULL,
+ UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
+ rows, cols, filter, false, scale < 0.5f ? 0.5f : scale, false);
}
/**
@@ -960,7 +988,7 @@ void uiTemplateIDTabs(
layout, C, ptr, propname,
newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
- 0, 0, filter, true);
+ 0, 0, filter, true, 1.0f, false);
}
/************************ ID Chooser Template ***************************/
@@ -1057,12 +1085,12 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem
return template_common_search_menu(
C, region, ui_rna_collection_search_cb, &template_search,
template_search_handle_cb, active_ptr.data,
- template_search.preview_rows, template_search.preview_cols);
+ template_search.preview_rows, template_search.preview_cols, 1.0f);
}
static void template_search_add_button_searchmenu(
const bContext *C, uiLayout *layout, uiBlock *block,
- TemplateSearch *template_search, const bool editable)
+ TemplateSearch *template_search, const bool editable, const bool live_icon)
{
const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop);
@@ -1070,7 +1098,7 @@ static void template_search_add_button_searchmenu(
C, layout, block,
&template_search->search_data.target_ptr, template_search->search_data.target_prop,
template_search_menu, MEM_dupallocN(template_search), ui_description,
- template_search->use_previews, editable);
+ template_search->use_previews, editable, live_icon);
}
static void template_search_add_button_name(
@@ -1116,7 +1144,7 @@ static void template_search_buttons(
uiLayoutRow(layout, true);
UI_block_align_begin(block);
- template_search_add_button_searchmenu(C, layout, block, template_search, editable);
+ template_search_add_button_searchmenu(C, layout, block, template_search, editable, false);
template_search_add_button_name(block, &active_ptr, type);
template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable);
template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
@@ -1539,14 +1567,250 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
return NULL;
}
+/************************ Grease Pencil Modifier Template *************************/
-/************************ Redo Buttons Template *************************/
+static uiLayout *gpencil_draw_modifier(
+ uiLayout *layout, Object *ob,
+ GpencilModifierData *md)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ PointerRNA ptr;
+ uiBlock *block;
+ uiLayout *box, *column, *row, *sub;
+ uiLayout *result = NULL;
+
+ /* create RNA pointer */
+ RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
+
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(column, "modifier", &ptr);
+
+ /* rounded header ------------------------------------------------------------------- */
+ box = uiLayoutBox(column);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* Open/Close ................................. */
+ uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+
+ /* modifier-type icon */
+ uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* modifier name */
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
+
+ /* mode enabling buttons */
+ UI_block_align_begin(block);
+ uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
-static bool template_operator_redo_property_buts_poll(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+ if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, false);
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
+
+ UI_block_align_end(block);
+
+ /* Up/Down + Delete ........................... */
+ UI_block_align_begin(block);
+ uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_gpencil_modifier_move_up");
+ uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_gpencil_modifier_move_down");
+ UI_block_align_end(block);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemO(row, "", ICON_X, "OBJECT_OT_gpencil_modifier_remove");
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* modifier settings (under the header) --------------------------------------------------- */
+ if (md->mode & eGpencilModifierMode_Expanded) {
+ /* apply/convert/copy */
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+
+ /* only here obdata, the rest of modifiers is ob level */
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+ uiItemEnumO(row, "OBJECT_OT_gpencil_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0, "apply_as", MODIFIER_APPLY_DATA);
+
+ uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
+ "OBJECT_OT_gpencil_modifier_copy");
+
+ /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
+ result = uiLayoutColumn(box, false);
+ block = uiLayoutAbsoluteBlock(box);
+ }
+
+ /* error messages */
+ if (md->error) {
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, md->error, ICON_ERROR);
+ }
+
+ return result;
+}
+
+uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- return (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED) == 0;
+ Object *ob;
+ GpencilModifierData *md, *vmd;
+ int i;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ md = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected modifier on object");
+ return NULL;
+ }
+
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
+
+ /* find modifier and draw it */
+ vmd = ob->greasepencil_modifiers.first;
+ for (i = 0; vmd; i++, vmd = vmd->next) {
+ if (md == vmd)
+ return gpencil_draw_modifier(layout, ob, md);
+ }
+
+ return NULL;
}
+/************************ Shader FX Template *************************/
+
+static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob,
+ ShaderFxData *md)
+{
+ const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type);
+ PointerRNA ptr;
+ uiBlock *block;
+ uiLayout *box, *column, *row, *sub;
+ uiLayout *result = NULL;
+
+ /* create RNA pointer */
+ RNA_pointer_create(&ob->id, &RNA_ShaderFx, md, &ptr);
+
+ column = uiLayoutColumn(layout, true);
+ uiLayoutSetContextPointer(column, "shaderfx", &ptr);
+
+ /* rounded header ------------------------------------------------------------------- */
+ box = uiLayoutBox(column);
+
+ row = uiLayoutRow(box, false);
+ block = uiLayoutGetBlock(row);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ /* Open/Close ................................. */
+ uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+
+ /* shader-type icon */
+ uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* effect name */
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ uiLayoutSetRedAlert(row, true);
+ }
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiLayoutSetRedAlert(row, false);
+
+ /* mode enabling buttons */
+ UI_block_align_begin(block);
+ uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
+
+ if (mti->flags & eShaderFxTypeFlag_SupportsEditmode) {
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, false);
+ uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE);
+ }
+
+ UI_block_align_end(block);
+
+ /* Up/Down + Delete ........................... */
+ UI_block_align_begin(block);
+ uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_shaderfx_move_up");
+ uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_shaderfx_move_down");
+ UI_block_align_end(block);
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiItemO(row, "", ICON_X, "OBJECT_OT_shaderfx_remove");
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* effect settings (under the header) --------------------------------------------------- */
+ if (md->mode & eShaderFxMode_Expanded) {
+ /* apply/convert/copy */
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+
+ /* only here obdata, the rest of effect is ob level */
+ UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+
+ /* result is the layout block inside the box, that we return so that effect settings can be drawn */
+ result = uiLayoutColumn(box, false);
+ block = uiLayoutAbsoluteBlock(box);
+ }
+
+ /* error messages */
+ if (md->error) {
+ box = uiLayoutBox(column);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, md->error, ICON_ERROR);
+ }
+
+ return result;
+}
+
+uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ Object *ob;
+ ShaderFxData *fx, *vfx;
+ int i;
+
+ /* verify we have valid data */
+ if (!RNA_struct_is_a(ptr->type, &RNA_ShaderFx)) {
+ RNA_warning("Expected shader fx on object");
+ return NULL;
+ }
+
+ ob = ptr->id.data;
+ fx = ptr->data;
+
+ if (!ob || !(GS(ob->id.name) == ID_OB)) {
+ RNA_warning("Expected shader fx on object");
+ return NULL;
+ }
+
+ UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
+
+ /* find modifier and draw it */
+ vfx = ob->shader_fx.first;
+ for (i = 0; vfx; i++, vfx = vfx->next) {
+ if (fx == vfx)
+ return gpencil_draw_shaderfx(layout, ob, fx);
+ }
+
+ return NULL;
+}
+
+/************************ Redo Buttons Template *************************/
+
static void template_operator_redo_property_buts_draw(
const bContext *C, wmOperator *op,
uiLayout *layout, int layout_flags,
@@ -1560,8 +1824,9 @@ static void template_operator_redo_property_buts_draw(
else {
/* Might want to make label_align adjustable somehow. */
eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
- C, layout, op, r_has_advanced ? template_operator_redo_property_buts_poll : NULL,
- UI_BUT_LABEL_ALIGN_NONE, layout_flags);
+ C, layout, op,
+ UI_BUT_LABEL_ALIGN_NONE,
+ layout_flags);
if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
if (r_has_advanced) {
*r_has_advanced = true;
@@ -3043,6 +3308,24 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname,
}
}
+void uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, const char *propname)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ uiBlock *block;
+ uiBut *but;
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ block = uiLayoutGetBlock(layout);
+
+ but = uiDefIconTextButO(block, UI_BTYPE_BUT, "UI_OT_eyedropper_color_crypto", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, RNA_property_ui_name(prop), 0, 0, UI_UNIT_X, UI_UNIT_Y, RNA_property_ui_description(prop));
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+ but->rnaindex = -1;
+}
/********************* Layer Buttons Template ************************/
@@ -3930,13 +4213,30 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt,
}
#endif
+struct uiTemplateOperatorPropertyPollParam {
+ const bContext *C;
+ wmOperator *op;
+ short flag;
+};
+
+static bool ui_layout_operator_buts_poll_property(
+ struct PointerRNA *UNUSED(ptr), struct PropertyRNA *prop, void *user_data)
+{
+ struct uiTemplateOperatorPropertyPollParam *params = user_data;
+ if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) &&
+ (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED))
+ {
+ return false;
+ }
+ return params->op->type->poll_property(params->C, params->op, prop);
+}
+
/**
* Draw Operator property buttons for redoing execution with different settings.
* This function does not initialize the layout, functions can be called on the layout before and after.
*/
eAutoPropButsReturn uiTemplateOperatorPropertyButs(
const bContext *C, uiLayout *layout, wmOperator *op,
- bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const eButLabelAlign label_align, const short flag)
{
uiBlock *block = uiLayoutGetBlock(layout);
@@ -3995,13 +4295,18 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs(
else {
wmWindowManager *wm = CTX_wm_manager(C);
PointerRNA ptr;
+ struct uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = flag};
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
uiLayoutSetPropSep(layout, true);
/* main draw call */
- return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
+ return_info = uiDefAutoButsRNA(
+ layout, &ptr,
+ op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL,
+ op->type->poll_property ? &user_data : NULL,
+ label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
@@ -4588,7 +4893,7 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
- uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!file) {
return;
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index d080397c488..60aa79e1093 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -159,7 +159,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
*/
eAutoPropButsReturn uiDefAutoButsRNA(
uiLayout *layout, PointerRNA *ptr,
- bool (*check_prop)(PointerRNA *, PropertyRNA *),
+ bool (*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data,
const eButLabelAlign label_align, const bool compact)
{
eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
@@ -174,7 +174,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(
if (flag & PROP_HIDDEN) {
continue;
}
- if (check_prop && check_prop(ptr, prop) == 0) {
+ if (check_prop && check_prop(ptr, prop, user_data) == 0) {
return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
continue;
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index fea88388be7..019aabdb466 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -247,22 +247,22 @@ static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {
};
static struct {
- Gwn_Batch *roundbox_widget[ROUNDBOX_TRIA_MAX];
+ GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX];
- Gwn_Batch *roundbox_simple;
- Gwn_Batch *roundbox_simple_aa;
- Gwn_Batch *roundbox_simple_outline;
- Gwn_Batch *roundbox_shadow;
+ GPUBatch *roundbox_simple;
+ GPUBatch *roundbox_simple_aa;
+ GPUBatch *roundbox_simple_outline;
+ GPUBatch *roundbox_shadow;
- Gwn_VertFormat format;
+ GPUVertFormat format;
uint vflag_id;
} g_ui_batch_cache = {{0}};
-static Gwn_VertFormat *vflag_format(void)
+static GPUVertFormat *vflag_format(void)
{
if (g_ui_batch_cache.format.attr_len == 0) {
- Gwn_VertFormat *format = &g_ui_batch_cache.format;
- g_ui_batch_cache.vflag_id = GWN_vertformat_attr_add(format, "vflag", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat *format = &g_ui_batch_cache.format;
+ g_ui_batch_cache.vflag_id = GPU_vertformat_attr_add(format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT);
}
return &g_ui_batch_cache.format;
}
@@ -273,17 +273,17 @@ static Gwn_VertFormat *vflag_format(void)
#define NO_AA WIDGET_AA_JITTER
static void set_roundbox_vertex_data(
- Gwn_VertBufRaw *vflag_step, uint32_t d)
+ GPUVertBufRaw *vflag_step, uint32_t d)
{
- uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
*data = d;
}
static uint32_t set_roundbox_vertex(
- Gwn_VertBufRaw *vflag_step,
+ GPUVertBufRaw *vflag_step,
int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
{
- uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
*data = corner_id;
*data |= corner_v << 2;
*data |= jit_v << 6;
@@ -294,10 +294,10 @@ static uint32_t set_roundbox_vertex(
}
static uint32_t set_tria_vertex(
- Gwn_VertBufRaw *vflag_step,
+ GPUVertBufRaw *vflag_step,
int tria_type, int tria_v, int tria_id, int jit_v)
{
- uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
}
@@ -308,7 +308,7 @@ static uint32_t set_tria_vertex(
return *data;
}
-static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data)
+static void roundbox_batch_add_tria(GPUVertBufRaw *vflag_step, int tria, uint32_t last_data)
{
const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
/* for each tria */
@@ -324,12 +324,12 @@ static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32
}
}
-Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
+GPUBatch *ui_batch_roundbox_widget_get(int tria)
{
if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
uint32_t last_data;
- Gwn_VertBufRaw vflag_step;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
int vcount = WIDGET_SIZE_MAX; /* inner */
vcount += 2; /* restart */
vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
@@ -341,8 +341,8 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
}
}
- GWN_vertbuf_data_alloc(vbo, vcount);
- GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
/* Inner */
for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
@@ -383,15 +383,15 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
if (tria) {
roundbox_batch_add_tria(&vflag_step, tria, last_data);
}
- g_ui_batch_cache.roundbox_widget[tria] = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
}
return g_ui_batch_cache.roundbox_widget[tria];
}
-Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
+GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased)
{
- Gwn_Batch **batch = NULL;
+ GPUBatch **batch = NULL;
if (filled) {
if (antialiased)
@@ -408,13 +408,13 @@ Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
if (*batch == NULL) {
uint32_t last_data;
- Gwn_VertBufRaw vflag_step;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
int vcount = WIDGET_SIZE_MAX;
vcount += (filled) ? 2 : 0;
vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
- GWN_vertbuf_data_alloc(vbo, vcount);
- GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
if (filled) {
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
@@ -435,7 +435,7 @@ Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
break;
}
}
- *batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
else {
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
@@ -451,7 +451,7 @@ Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
break;
}
}
- *batch = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
gpu_batch_presets_register(*batch);
@@ -459,15 +459,15 @@ Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
return *batch;
}
-Gwn_Batch *ui_batch_roundbox_shadow_get(void)
+GPUBatch *ui_batch_roundbox_shadow_get(void)
{
if (g_ui_batch_cache.roundbox_shadow == NULL) {
uint32_t last_data;
- Gwn_VertBufRaw vflag_step;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ GPUVertBufRaw vflag_step;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
- GWN_vertbuf_data_alloc(vbo, vcount);
- GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ GPU_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
for (int c = 0; c < 4; c++) {
for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
@@ -488,7 +488,7 @@ Gwn_Batch *ui_batch_roundbox_shadow_get(void)
set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
}
}
- g_ui_batch_cache.roundbox_shadow = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ g_ui_batch_cache.roundbox_shadow = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow);
}
return g_ui_batch_cache.roundbox_shadow;
@@ -513,11 +513,11 @@ void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(draw_color);
- immBegin(GWN_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
+ immBegin(GPU_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
/* for each AA step */
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
@@ -556,14 +556,14 @@ void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float col
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(draw_color);
/* for each AA step */
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- immBegin(GWN_PRIM_TRI_FAN, length);
+ immBegin(GPU_PRIM_TRI_FAN, length);
immVertex2f(pos, tri_array[0][0], tri_array[0][1]);
immVertex2f(pos, tri_array[1][0], tri_array[1][1]);
@@ -1083,8 +1083,8 @@ static void widgetbase_set_uniform_colors_ubv(
#define MAX_WIDGET_BASE_BATCH 6
#define MAX_WIDGET_PARAMETERS 11
-struct {
- Gwn_Batch *batch; /* Batch type */
+static struct {
+ GPUBatch *batch; /* Batch type */
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
int count;
bool enabled;
@@ -1097,22 +1097,22 @@ void UI_widgetbase_draw_cache_flush(void)
if (g_widget_base_batch.count == 0)
return;
- Gwn_Batch *batch = g_widget_base_batch.batch;
+ GPUBatch *batch = g_widget_base_batch.batch;
if (g_widget_base_batch.count == 1) {
/* draw single */
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)g_widget_base_batch.params);
- GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)g_widget_base_batch.params);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_batch_draw(batch);
}
else {
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
- GWN_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
+ GPU_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
(float *)g_widget_base_batch.params);
- GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- gpuBindMatrices(batch->interface);
- GWN_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
- GWN_batch_program_use_end(batch);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_matrix_bind(batch->interface);
+ GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
+ GPU_batch_program_use_end(batch);
}
g_widget_base_batch.count = 0;
}
@@ -1135,7 +1135,7 @@ void UI_widgetbase_draw_cache_end(void)
GPU_blend(false);
}
-static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
+static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb)
{
wtb->uniform_params.tria1_size = wtb->tria1.size;
wtb->uniform_params.tria2_size = wtb->tria2.size;
@@ -1171,10 +1171,10 @@ static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
else {
float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
/* draw single */
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&wtb->uniform_params);
- GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&wtb->uniform_params);
+ GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GPU_batch_draw(batch);
}
}
@@ -1228,7 +1228,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || alpha_check) {
widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, alpha_check);
- Gwn_Batch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
+ GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
draw_widgetbase_batch(roundbox_batch, wtb);
}
@@ -1494,7 +1494,7 @@ float UI_text_clip_middle_ex(
rpart = rpart_buf;
}
- l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
+ l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
/* If we really have no place, or we would clip a very small piece of string in the middle,
* only show start of string.
@@ -1504,7 +1504,7 @@ float UI_text_clip_middle_ex(
else {
size_t r_offset, r_len;
- r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
+ r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, NULL);
r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
if (l_end + sep_len + r_len + rpart_len > max_len) {
@@ -1525,6 +1525,7 @@ float UI_text_clip_middle_ex(
if (rpart) {
/* Add back preserved right part to our shorten str. */
memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
+ okwidth += rpart_width;
}
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
@@ -1836,7 +1837,7 @@ 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);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)wcol->item);
@@ -1872,7 +1873,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
UI_widgetbase_draw_cache_flush();
GPU_blend(false);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(0.2f, 0.6f, 0.9f);
@@ -2423,7 +2424,7 @@ 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;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2475,7 +2476,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
static void ui_hsv_cursor(float x, float y)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2571,13 +2572,13 @@ 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);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(GWN_PRIM_TRI_FAN, tot + 2);
+ immBegin(GPU_PRIM_TRI_FAN, tot + 2);
immAttrib3fv(color, colcent);
immVertex2f(pos, centx, centy);
@@ -2598,7 +2599,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
/* fully rounded outline */
format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2682,12 +2683,12 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
}
/* old below */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- immBegin(GWN_PRIM_TRIS, steps * 3 * 6);
+ immBegin(GPU_PRIM_TRIS, 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;
@@ -2843,7 +2844,7 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
/* outline */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ub(0, 0, 0);
imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
@@ -2940,14 +2941,14 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
30
};
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_blend(true);
immUniformColor4ubv(col);
GPU_line_width(1.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, rect->xmin, y);
immVertex2f(pos, rect->xmax, y);
immEnd();
@@ -3402,11 +3403,11 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
UI_widgetbase_draw_cache_flush();
GPU_blend(false);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(bw, bw, bw);
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 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);
@@ -3783,7 +3784,7 @@ 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);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* make mask to draw over image */
@@ -4420,11 +4421,11 @@ static void ui_draw_popover_back_impl(
/* Draw popover arrow (top/bottom) */
if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)wcol->inner);
GPU_blend(true);
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
if (direction == UI_DIR_DOWN) {
const float y = rect->ymax;
immVertex2f(pos, cent_x - unit_half, y);
@@ -4476,10 +4477,10 @@ static void draw_disk_shaded(
unsigned char r_col[4];
unsigned int pos, col;
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (shaded) {
- col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
}
else {
@@ -4487,7 +4488,7 @@ static void draw_disk_shaded(
immUniformColor4ubv((unsigned char *)col1);
}
- immBegin(GWN_PRIM_TRI_STRIP, subd * 2);
+ immBegin(GPU_PRIM_TRI_STRIP, subd * 2);
for (i = 0; i < subd; i++) {
float a;
@@ -4532,8 +4533,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;
- gpuPushMatrix();
- gpuTranslate2f(cx, cy);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(cx, cy);
GPU_blend(true);
if (btheme->tui.wcol_pie_menu.shaded) {
@@ -4556,8 +4557,8 @@ void ui_draw_pie_center(uiBlock *block)
}
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline);
@@ -4579,7 +4580,7 @@ void ui_draw_pie_center(uiBlock *block)
}
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 47d664eaeb2..72023ebf2ae 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -83,7 +83,7 @@ static struct bThemeState g_theme_state = {
void ui_resources_init(void)
{
- UI_icons_init(BIFICONID_LAST);
+ UI_icons_init();
}
void ui_resources_free(void)
@@ -1536,15 +1536,6 @@ void init_userdef_do_versions(Main *bmain)
#undef USER_VERSION_ATLEAST
#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST((&(U)), ver, subver)
-
- if (!USER_VERSION_ATLEAST(269, 9)) {
- /* grease pencil - new layer color */
- if (U.gpencil_new_layer_col[3] < 0.1f) {
- /* defaults to black, but must at least be visible! */
- U.gpencil_new_layer_col[3] = 0.9f;
- }
- }
-
if (!USER_VERSION_ATLEAST(271, 5)) {
U.pie_menu_radius = 100;
U.pie_menu_threshold = 12;
@@ -1582,6 +1573,17 @@ void init_userdef_do_versions(Main *bmain)
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
}
+
+ /* Annotations - new layer color
+ * Replace anything that used to be set if it looks like was left
+ * on the old default (i.e. black), which most users used
+ */
+ if ((U.gpencil_new_layer_col[3] < 0.1f) || (U.gpencil_new_layer_col[0] < 0.1f)) {
+ /* - New color matches the annotation pencil icon
+ * - Non-full alpha looks better!
+ */
+ ARRAY_SET_ITEMS(U.gpencil_new_layer_col, 0.38f, 0.61f, 0.78f, 0.9f);
+ }
}
/**
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 1b449877abe..3a527712367 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1151,7 +1151,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);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
// ED_region_pixelspace(CTX_wm_region(C));
}
@@ -1338,12 +1338,12 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
if (vertex_count == 0)
return;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, vertex_count);
+ immBegin(GPU_PRIM_LINES, vertex_count);
/* vertical lines */
if (flag & V2D_VERTICAL_LINES) {
@@ -1480,15 +1480,15 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step)
count_y = (v2d->cur.ymax - start_y) / step + 1;
if (count_x > 0 || count_y > 0) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
float theme_color[3];
UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
+ immBegin(GPU_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
immAttrib3fv(color, theme_color);
for (int i = 0; i < count_x ; start_x += step, i++) {
@@ -1531,14 +1531,14 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_line_width(1.0f);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBeginAtMost(GWN_PRIM_LINES, vertex_count);
+ immBeginAtMost(GPU_PRIM_LINES, vertex_count);
for (int level = 0; level < totlevels; ++level) {
UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color);
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index dfc401c1635..1c56dabb396 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -354,7 +354,7 @@ static int view_scrollright_exec(bContext *C, wmOperator *op)
}
/* set RNA-Props - only movement in positive x-direction */
- RNA_int_set(op->ptr, "deltax", 20);
+ RNA_int_set(op->ptr, "deltax", 40);
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
@@ -398,7 +398,7 @@ static int view_scrollleft_exec(bContext *C, wmOperator *op)
}
/* set RNA-Props - only movement in negative x-direction */
- RNA_int_set(op->ptr, "deltax", -20);
+ RNA_int_set(op->ptr, "deltax", -40);
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 4717ef309f3..506dec2aa3e 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -124,8 +124,8 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
return;
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -134,7 +134,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
/* this could be split into its own loop */
if (draw_type == MASK_DT_OUTLINE) {
GPU_line_width(3.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
immEnd();
@@ -154,7 +154,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
}
GPU_line_width(1.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
immEnd();
@@ -178,7 +178,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
immUniform4fv("outlineColor", point_color);
immUniformColor3fvAlpha(point_color, 0.25f);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, handle_pos);
immEnd();
@@ -212,8 +212,8 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", 0.7f * handle_size);
@@ -251,7 +251,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
immUniformThemeColor(TH_HANDLE_VERTEX);
}
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, feather_point);
immEnd();
@@ -320,7 +320,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
else
immUniformThemeColor(TH_HANDLE_VERTEX);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, vert);
immEnd();
@@ -350,7 +350,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
immUniform1f("size", 12.0f);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(pos, x, y);
immEnd();
@@ -371,7 +371,7 @@ static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char r
}
}
-static void mask_draw_array(unsigned int pos, Gwn_PrimType prim_type, const float (*points)[2], unsigned int vertex_len)
+static void mask_draw_array(unsigned int pos, GPUPrimType prim_type, const float (*points)[2], unsigned int vertex_len)
{
immBegin(prim_type, vertex_len);
for (unsigned int i = 0; i < vertex_len; ++i) {
@@ -384,7 +384,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
const bool is_feather, const bool is_active,
const unsigned char rgb_spline[4], const char draw_type)
{
- const Gwn_PrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GWN_PRIM_LINE_LOOP : GWN_PRIM_LINE_STRIP;
+ const GPUPrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GPU_PRIM_LINE_LOOP : GPU_PRIM_LINE_STRIP;
const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
unsigned char rgb_tmp[4];
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -402,8 +402,8 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
}
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
switch (draw_type) {
@@ -695,17 +695,17 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
GPU_blend_set_func(GPU_DST_COLOR, GPU_ZERO);
}
- gpuPushMatrix();
- gpuTranslate2f(x, y);
- gpuScale2f(zoomx, zoomy);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
if (stabmat) {
- gpuMultMatrix(stabmat);
+ GPU_matrix_mul(stabmat);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
- gpuPopMatrix();
+ GPU_matrix_pop();
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
GPU_blend(false);
@@ -715,13 +715,13 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
- gpuPushMatrix();
- gpuTranslate2f(x + xofs, y + yofs);
- gpuScale2f(zoomx, zoomy);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x + xofs, y + yofs);
+ GPU_matrix_scale_2f(zoomx, zoomy);
if (stabmat) {
- gpuMultMatrix(stabmat);
+ GPU_matrix_mul(stabmat);
}
- gpuScale2f(maxdim, maxdim);
+ GPU_matrix_scale_2f(maxdim, maxdim);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
@@ -734,7 +734,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
@@ -747,12 +747,12 @@ void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra
unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
if (num_lines > 0) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(255, 175, 0, 255);
- immBegin(GWN_PRIM_LINES, 2 * num_lines);
+ immBegin(GPU_PRIM_LINES, 2 * num_lines);
for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first;
masklay_shape;
diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index be5c01e08df..6fa0eb33b89 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -160,14 +160,14 @@ static void gizmo_mesh_placement_update_from_op(GizmoPlacementGroup *man)
/* translate callbacks */
static void gizmo_placement_prop_matrix_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoPlacementGroup *man = mpr->parent_mgroup->customdata;
+ GizmoPlacementGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 16);
+ UNUSED_VARS_NDEBUG(gz_prop);
if (value_p != man->cage->matrix_offset) {
mul_m4_m4m4(value_p, man->cage->matrix_basis, man->cage->matrix_offset);
@@ -176,14 +176,14 @@ static void gizmo_placement_prop_matrix_get(
}
static void gizmo_placement_prop_matrix_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value)
{
- GizmoPlacementGroup *man = mpr->parent_mgroup->customdata;
+ GizmoPlacementGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
- BLI_assert(mpr_prop->type->array_length == 16);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 16);
+ UNUSED_VARS_NDEBUG(gz_prop);
float mat[4][4];
mul_m4_m4m4(mat, man->cage->matrix_basis, value);
@@ -197,38 +197,38 @@ static void gizmo_placement_prop_matrix_set(
gizmo_placement_exec(man);
}
-static bool gizmo_mesh_placement_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool gizmo_mesh_placement_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
wmOperator *op = WM_operator_last_redo(C);
if (op == NULL || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
static void gizmo_mesh_placement_modal_from_setup(
- const bContext *C, wmGizmoGroup *mgroup)
+ const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoPlacementGroup *man = mgroup->customdata;
+ GizmoPlacementGroup *man = gzgroup->customdata;
/* Initial size. */
{
- wmGizmo *mpr = man->cage;
- zero_m4(mpr->matrix_offset);
-
- /* TODO: support zero scaled matrix in 'GIZMO_WT_cage_3d'. */
- mpr->matrix_offset[0][0] = 0.01;
- mpr->matrix_offset[1][1] = 0.01;
- mpr->matrix_offset[2][2] = 0.01;
- mpr->matrix_offset[3][3] = 1.0f;
+ wmGizmo *gz = man->cage;
+ zero_m4(gz->matrix_offset);
+
+ /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
+ gz->matrix_offset[0][0] = 0.01;
+ gz->matrix_offset[1][1] = 0.01;
+ gz->matrix_offset[2][2] = 0.01;
+ gz->matrix_offset[3][3] = 1.0f;
}
/* Start off dragging. */
{
wmWindow *win = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
- wmGizmo *mpr = man->cage;
+ wmGizmo *gz = man->cage;
{
float mat3[3][3];
@@ -239,19 +239,19 @@ static void gizmo_mesh_placement_modal_from_setup(
win->eventstate->y - ar->winrct.ymin,
},
location, mat3);
- copy_m4_m3(mpr->matrix_basis, mat3);
- copy_v3_v3(mpr->matrix_basis[3], location);
+ copy_m4_m3(gz->matrix_basis, mat3);
+ copy_v3_v3(gz->matrix_basis[3], location);
}
if (1) {
- wmGizmoMap *mmap = mgroup->parent_mmap;
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
WM_gizmo_modal_set_from_setup(
- mmap, (bContext *)C, man->cage, ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z, win->eventstate);
+ gzmap, (bContext *)C, man->cage, ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z, win->eventstate);
}
}
}
-static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -260,11 +260,11 @@ static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *mgroup)
}
struct GizmoPlacementGroup *man = MEM_callocN(sizeof(GizmoPlacementGroup), __func__);
- mgroup->customdata = man;
+ gzgroup->customdata = man;
- const wmGizmoType *wt_cage = WM_gizmotype_find("GIZMO_WT_cage_3d", true);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
- man->cage = WM_gizmo_new_ptr(wt_cage, mgroup, NULL);
+ man->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, man->cage->color);
@@ -293,32 +293,32 @@ static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *mgroup)
});
}
- gizmo_mesh_placement_modal_from_setup(C, mgroup);
+ gizmo_mesh_placement_modal_from_setup(C, gzgroup);
}
static void gizmo_mesh_placement_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+ const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoPlacementGroup *man = mgroup->customdata;
+ GizmoPlacementGroup *man = gzgroup->customdata;
if (man->data.op->next) {
man->data.op = WM_operator_last_redo((bContext *)man->data.context);
}
gizmo_mesh_placement_update_from_op(man);
}
-static void MESH_WGT_add_bounds(struct wmGizmoGroupType *wgt)
+static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
{
- wgt->name = "Mesh Add Bounds";
- wgt->idname = "MESH_WGT_add_bounds";
+ gzgt->name = "Mesh Add Bounds";
+ gzgt->idname = "MESH_GGT_add_bounds";
- wgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = gizmo_mesh_placement_poll;
- wgt->setup = gizmo_mesh_placement_setup;
- wgt->draw_prepare = gizmo_mesh_placement_draw_prepare;
+ gzgt->poll = gizmo_mesh_placement_poll;
+ gzgt->setup = gizmo_mesh_placement_setup;
+ gzgt->draw_prepare = gizmo_mesh_placement_draw_prepare;
}
/** \} */
@@ -379,18 +379,18 @@ static int add_primitive_cube_gizmo_invoke(bContext *C, wmOperator *op, const wm
int ret = add_primitive_cube_gizmo_exec(C, op);
if (ret & OPERATOR_FINISHED) {
/* Setup gizmos */
- if (v3d && ((v3d->mpr_flag & V3D_GIZMO_HIDE) == 0)) {
+ if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *mmap = ar->gizmo_map;
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find("MESH_WGT_add_bounds", false);
- wmGizmoGroup *mgroup = WM_gizmomap_group_find_ptr(mmap, wgt);
- if (mgroup != NULL) {
- GizmoPlacementGroup *man = mgroup->customdata;
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
+ wmGizmoGroup *gzgroup = WM_gizmomap_group_find_ptr(gzmap, gzgt);
+ if (gzgroup != NULL) {
+ GizmoPlacementGroup *man = gzgroup->customdata;
man->data.op = op;
- gizmo_mesh_placement_modal_from_setup(C, mgroup);
+ gizmo_mesh_placement_modal_from_setup(C, gzgroup);
}
else {
- WM_gizmo_group_type_ensure_ptr(wgt);
+ WM_gizmo_group_type_ensure_ptr(gzgt);
}
}
}
@@ -420,7 +420,7 @@ void MESH_OT_primitive_cube_add_gizmo(wmOperatorType *ot)
PropertyRNA *prop = RNA_def_float_matrix(ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- WM_gizmogrouptype_append(MESH_WGT_add_bounds);
+ WM_gizmogrouptype_append(MESH_GGT_add_bounds);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index b73ce410626..e87abc6adf7 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -30,6 +30,7 @@
#include "BLI_string.h"
#include "BLI_math.h"
+#include "BLI_linklist_stack.h"
#include "BLT_translation.h"
@@ -38,6 +39,7 @@
#include "BKE_editmesh.h"
#include "BKE_unit.h"
#include "BKE_layer.h"
+#include "BKE_mesh.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -95,7 +97,7 @@ typedef struct {
/* modal only */
float mcenter[2];
void *draw_handle_pixel;
- short mpr_flag;
+ short gizmo_flag;
short value_mode; /* Which value does mouse movement and numeric input affect? */
float segments; /* Segments as float so smooth mouse pan works in small increments */
} BevelData;
@@ -134,6 +136,98 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
}
}
+static void bevel_harden_normals(BMEditMesh *em, BMOperator *bmop, float face_strength)
+{
+ BKE_editmesh_lnorspace_update(em);
+ BM_normals_loops_edges_tag(em->bm, true);
+ const int cd_clnors_offset = CustomData_get_offset(&em->bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_cur, *l_first;
+ BMIter fiter;
+
+ BMOpSlot *nslot = BMO_slot_get(bmop->slots_out, "normals.out"); /* Per vertex normals depending on hn_mode */
+
+ /* Similar functionality to bm_mesh_loops_calc_normals... Edges that can be smoothed are tagged */
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_cur = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if ((BM_elem_flag_test(l_cur->v, BM_ELEM_SELECT)) &&
+ ((!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG)) ||
+ (!BM_elem_flag_test(l_cur, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_cur))))
+ {
+ /* Both adjacent loops are sharp, set clnor to face normal */
+ if (!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_cur->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_cur);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_cur, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ /* Find next corresponding sharp edge in this smooth fan */
+ BMVert *v_pivot = l_cur->v;
+ float *calc_n = BLI_ghash_lookup(nslot->data.ghash, v_pivot);
+
+ BMEdge *e_next;
+ const BMEdge *e_org = l_cur->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_cur;
+ e_next = lfan_pivot->e;
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float cn_wght[3] = { 0.0f, 0.0f, 0.0f }, cn_unwght[3] = { 0.0f, 0.0f, 0.0f };
+
+ /* Fan through current vert and accumulate normals and loops */
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
+ float cur[3];
+ mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
+ add_v3_v3(cn_wght, cur);
+
+ if (BM_elem_flag_test(lfan_pivot->f, BM_ELEM_SELECT))
+ add_v3_v3(cn_unwght, cur);
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+
+ normalize_v3(cn_wght);
+ normalize_v3(cn_unwght);
+ if (calc_n) {
+ mul_v3_fl(cn_wght, face_strength);
+ mul_v3_fl(calc_n, 1.0f - face_strength);
+ add_v3_v3(calc_n, cn_wght);
+ normalize_v3(calc_n);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ if (calc_n) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], calc_n, clnors);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], cn_unwght, clnors);
+ }
+ }
+ BLI_ghash_remove(nslot->data.ghash, v_pivot, NULL, MEM_freeN);
+ }
+ }
+ } while ((l_cur = l_cur->next) != l_first);
+ }
+}
+
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
Scene *scene = CTX_data_scene(C);
@@ -201,8 +295,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
- opdata->mpr_flag = v3d->mpr_flag;
- v3d->mpr_flag = V3D_GIZMO_HIDE;
+ opdata->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
}
}
@@ -224,6 +318,10 @@ static bool edbm_bevel_calc(wmOperator *op)
const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
int material = RNA_int_get(op->ptr, "material");
const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
+ const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ const float hn_strength = RNA_float_get(op->ptr, "strength");
+ const int hnmode = RNA_enum_get(op->ptr, "hnmode");
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
@@ -238,11 +336,12 @@ static bool edbm_bevel_calc(wmOperator *op)
material = CLAMPIS(material, -1, em->ob->totcol - 1);
}
- EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
- "material=%i loop_slide=%b",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
- clamp_overlap, material, loop_slide);
+ EDBM_op_init(
+ em, &bmop, op,
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
+ "material=%i loop_slide=%b mark_seam=%b mark_sharp=%b strength=%f hnmode=%i",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide, mark_seam, mark_sharp, hn_strength, hnmode);
BMO_op_exec(em->bm, &bmop);
@@ -253,6 +352,10 @@ static bool edbm_bevel_calc(wmOperator *op)
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
+ if (hnmode != BEVEL_HN_NONE) {
+ bevel_harden_normals(em, &bmop, hn_strength);
+ }
+
/* no need to de-select existing geometry */
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
@@ -284,7 +387,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
}
ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
if (v3d) {
- v3d->mpr_flag = opdata->mpr_flag;
+ v3d->gizmo_flag = opdata->gizmo_flag;
}
G.moving = 0;
}
@@ -603,6 +706,26 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
edbm_bevel_update_header(C, op);
handled = true;
break;
+ case UKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ else {
+ bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
+ edbm_bevel_calc(op);
+ handled = true;
+ break;
+ }
+ case KKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ else {
+ bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
+ edbm_bevel_calc(op);
+ handled = true;
+ break;
+ }
}
@@ -641,6 +764,13 @@ void MESH_OT_bevel(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
+ static EnumPropertyItem harden_normals_items[] = {
+ { BEVEL_HN_NONE, "HN_NONE", 0, "Off", "Do not use Harden Normals" },
+ { BEVEL_HN_FACE, "HN_FACE", 0, "Face Area", "Use faces as weight" },
+ { BEVEL_HN_ADJ, "HN_ADJ", 0, "Vertex average", "Use adjacent vertices as weight" },
+ { 0, NULL, 0, NULL, NULL },
+ };
+
/* identifiers */
ot->name = "Bevel";
ot->description = "Edge Bevel";
@@ -666,6 +796,12 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
"Do not allow beveled edges/vertices to overlap each other");
RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
+ RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
+ RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material",
"Material for bevel faces (-1 means use adjacent faces)", -1, 100);
+ RNA_def_float(ot->srna, "strength", 0.5f, 0.0f, 1.0f, "Normal Strength",
+ "Strength of calculated normal", 0.0f, 1.0f);
+ RNA_def_enum(ot->srna, "hnmode", harden_normals_items, BEVEL_HN_NONE, "Normal Mode",
+ "Weighting mode for Harden Normals");
}
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index a9e11b7b411..9416d889a3b 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -70,7 +70,7 @@ typedef struct {
/* modal only */
BMBackup mesh_backup;
bool is_first;
- short mpr_flag;
+ short gizmo_flag;
} BisectData;
static bool mesh_bisect_interactive_calc(
@@ -156,8 +156,8 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* misc other vars */
G.moving = G_TRANSFORM_EDIT;
- opdata->mpr_flag = v3d->mpr_flag;
- v3d->mpr_flag = V3D_GIZMO_HIDE;
+ opdata->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
/* initialize modal callout */
ED_workspace_status_text(C, IFACE_("LMB: Click and drag to draw cut line"));
@@ -169,7 +169,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata)
{
View3D *v3d = CTX_wm_view3d(C);
EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
- v3d->mpr_flag = opdata->mpr_flag;
+ v3d->gizmo_flag = opdata->gizmo_flag;
G.moving = 0;
}
@@ -199,8 +199,8 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Setup gizmos */
{
View3D *v3d = CTX_wm_view3d(C);
- if (v3d && (v3d->mpr_flag & V3D_GIZMO_HIDE) == 0) {
- WM_gizmo_group_type_ensure("MESH_WGT_bisect");
+ if (v3d && (v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
+ WM_gizmo_group_type_ensure("MESH_GGT_bisect");
}
}
#endif
@@ -334,7 +334,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
}
#ifdef USE_GIZMO
-static void MESH_WGT_bisect(struct wmGizmoGroupType *wgt);
+static void MESH_GGT_bisect(struct wmGizmoGroupType *gzgt);
#endif
void MESH_OT_bisect(struct wmOperatorType *ot)
@@ -374,7 +374,7 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
#ifdef USE_GIZMO
- WM_gizmogrouptype_append(MESH_WGT_bisect);
+ WM_gizmogrouptype_append(MESH_GGT_bisect);
#endif
}
@@ -459,40 +459,40 @@ static void gizmo_mesh_bisect_update_from_op(GizmoGroup *man)
/* depth callbacks */
static void gizmo_bisect_prop_depth_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_co[3], plane_no[3];
RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co);
RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
- value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]);
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
}
static void gizmo_bisect_prop_depth_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
const float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_co[3], plane[4];
RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co);
RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane);
normalize_v3(plane);
- plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]);
+ plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
/* Keep our location, may be offset simply to be inside the viewport. */
closest_to_plane_normalized_v3(plane_co, plane, plane_co);
@@ -504,27 +504,27 @@ static void gizmo_bisect_prop_depth_set(
/* translate callbacks */
static void gizmo_bisect_prop_translate_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
- BLI_assert(mpr_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, value_p);
}
static void gizmo_bisect_prop_translate_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
- BLI_assert(mpr_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, value_p);
@@ -533,15 +533,15 @@ static void gizmo_bisect_prop_translate_set(
/* angle callbacks */
static void gizmo_bisect_prop_angle_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_no[4];
RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
@@ -560,15 +560,15 @@ static void gizmo_bisect_prop_angle_get(
}
static void gizmo_bisect_prop_angle_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoGroup *man = mpr->parent_mgroup->customdata;
+ GizmoGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
const float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_no[4];
RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
@@ -593,17 +593,17 @@ static void gizmo_bisect_prop_angle_set(
}
}
-static bool gizmo_mesh_bisect_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool gizmo_mesh_bisect_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
wmOperator *op = WM_operator_last_redo(C);
if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) {
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
-static void gizmo_mesh_bisect_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void gizmo_mesh_bisect_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -612,15 +612,15 @@ static void gizmo_mesh_bisect_setup(const bContext *C, wmGizmoGroup *mgroup)
}
struct GizmoGroup *man = MEM_callocN(sizeof(GizmoGroup), __func__);
- mgroup->customdata = man;
+ gzgroup->customdata = man;
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true);
- const wmGizmoType *wt_grab = WM_gizmotype_find("GIZMO_WT_grab_3d", true);
- const wmGizmoType *wt_dial = WM_gizmotype_find("GIZMO_WT_dial_3d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_grab = WM_gizmotype_find("GIZMO_GT_grab_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
- man->translate_z = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- man->translate_c = WM_gizmo_new_ptr(wt_grab, mgroup, NULL);
- man->rotate_c = WM_gizmo_new_ptr(wt_dial, mgroup, NULL);
+ man->translate_z = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ man->translate_c = WM_gizmo_new_ptr(gzt_grab, gzgroup, NULL);
+ man->rotate_c = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, man->translate_z->color);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, man->translate_c->color);
@@ -673,28 +673,28 @@ static void gizmo_mesh_bisect_setup(const bContext *C, wmGizmoGroup *mgroup)
}
static void gizmo_mesh_bisect_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+ const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoGroup *man = mgroup->customdata;
+ GizmoGroup *man = gzgroup->customdata;
if (man->data.op->next) {
man->data.op = WM_operator_last_redo((bContext *)man->data.context);
}
gizmo_mesh_bisect_update_from_op(man);
}
-static void MESH_WGT_bisect(struct wmGizmoGroupType *wgt)
+static void MESH_GGT_bisect(struct wmGizmoGroupType *gzgt)
{
- wgt->name = "Mesh Bisect";
- wgt->idname = "MESH_WGT_bisect";
+ gzgt->name = "Mesh Bisect";
+ gzgt->idname = "MESH_GGT_bisect";
- wgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = gizmo_mesh_bisect_poll;
- wgt->setup = gizmo_mesh_bisect_setup;
- wgt->draw_prepare = gizmo_mesh_bisect_draw_prepare;
+ gzgt->poll = gizmo_mesh_bisect_poll;
+ gzgt->setup = gizmo_mesh_bisect_setup;
+ gzgt->draw_prepare = gizmo_mesh_bisect_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index dd167c1fc15..c5ef2a06059 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -365,11 +365,11 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
#ifdef USE_GIZMO
-const float extrude_button_scale = 0.15f;
-const float extrude_button_offset_scale = 1.5f;
-const float extrude_arrow_scale = 1.0f;
-const float extrude_arrow_xyz_axis_scale = 1.0f;
-const float extrude_arrow_normal_axis_scale = 1.75f;
+static const float extrude_button_scale = 0.15f;
+static const float extrude_button_offset_scale = 1.5f;
+static const float extrude_arrow_scale = 1.0f;
+static const float extrude_arrow_xyz_axis_scale = 1.0f;
+static const float extrude_arrow_normal_axis_scale = 1.75f;
static const uchar shape_plus[] = {
0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11,
@@ -417,31 +417,31 @@ static void gizmo_mesh_extrude_orientation_matrix_set(
}
}
-static bool gizmo_mesh_extrude_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool gizmo_mesh_extrude_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
ScrArea *sa = CTX_wm_area(C);
bToolRef_Runtime *tref_rt = sa->runtime.tool ? sa->runtime.tool->runtime : NULL;
if ((tref_rt == NULL) ||
- !STREQ(wgt->idname, tref_rt->gizmo_group) ||
+ !STREQ(gzgt->idname, tref_rt->gizmo_group) ||
!ED_operator_editmesh_view3d((bContext *)C))
{
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
-static void gizmo_mesh_extrude_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void gizmo_mesh_extrude_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct GizmoExtrudeGroup *man = MEM_callocN(sizeof(GizmoExtrudeGroup), __func__);
- mgroup->customdata = man;
+ gzgroup->customdata = man;
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true);
- const wmGizmoType *wt_grab = WM_gizmotype_find("GIZMO_WT_button_2d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_grab = WM_gizmotype_find("GIZMO_GT_button_2d", true);
for (int i = 0; i < 4; i++) {
- man->adjust_xyz_no[i] = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- man->invoke_xyz_no[i] = WM_gizmo_new_ptr(wt_grab, mgroup, NULL);
+ man->adjust_xyz_no[i] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ man->invoke_xyz_no[i] = WM_gizmo_new_ptr(gzt_grab, gzgroup, NULL);
man->invoke_xyz_no[i]->flag |= WM_GIZMO_DRAW_OFFSET_SCALE;
}
@@ -503,9 +503,9 @@ static void gizmo_mesh_extrude_setup(const bContext *UNUSED(C), wmGizmoGroup *mg
}
}
-static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *man = mgroup->customdata;
+ GizmoExtrudeGroup *man = gzgroup->customdata;
for (int i = 0; i < 4; i++) {
WM_gizmo_set_flag(man->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
@@ -623,9 +623,9 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *mgroup)
}
}
-static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *man = mgroup->customdata;
+ GizmoExtrudeGroup *man = gzgroup->customdata;
switch (man->data.orientation_type) {
case V3D_MANIP_VIEW:
{
@@ -640,38 +640,38 @@ static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *mgr
}
static void gizmo_mesh_extrude_message_subscribe(
- const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus)
+ const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
{
ARegion *ar = CTX_wm_region(C);
/* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
.owner = ar,
- .user_data = mgroup->parent_mmap,
+ .user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
{
- WM_msg_subscribe_rna_anon_prop(mbus, Scene, transform_orientation, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, Scene, transform_orientation, &msg_sub_value_gz_tag_refresh);
}
}
-static void MESH_WGT_extrude(struct wmGizmoGroupType *wgt)
+static void MESH_GGT_extrude(struct wmGizmoGroupType *gzgt)
{
- wgt->name = "Mesh Extrude";
- wgt->idname = "MESH_WGT_extrude";
+ gzgt->name = "Mesh Extrude";
+ gzgt->idname = "MESH_GGT_extrude";
- wgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = gizmo_mesh_extrude_poll;
- wgt->setup = gizmo_mesh_extrude_setup;
- wgt->refresh = gizmo_mesh_extrude_refresh;
- wgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
- wgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
+ gzgt->poll = gizmo_mesh_extrude_poll;
+ gzgt->setup = gizmo_mesh_extrude_setup;
+ gzgt->refresh = gizmo_mesh_extrude_refresh;
+ gzgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
+ gzgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
}
#endif /* USE_GIZMO */
@@ -826,7 +826,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot)
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
#ifdef USE_GIZMO
- WM_gizmogrouptype_append(MESH_WGT_extrude);
+ WM_gizmogrouptype_append(MESH_GGT_extrude);
#endif
}
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c
index 3864bd63036..adb7ee71ee0 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin.c
@@ -143,40 +143,40 @@ static void gizmo_mesh_spin_update_from_op(GizmoSpinGroup *man)
/* depth callbacks */
static void gizmo_spin_prop_depth_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_co[3], plane_no[3];
RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co);
RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
- value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]);
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, gz->matrix_basis[3]);
}
static void gizmo_spin_prop_depth_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
const float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_co[3], plane[4];
RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co);
RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane);
normalize_v3(plane);
- plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]);
+ plane[3] = -value[0] - dot_v3v3(plane, gz->matrix_basis[3]);
/* Keep our location, may be offset simply to be inside the viewport. */
closest_to_plane_normalized_v3(plane_co, plane, plane_co);
@@ -188,28 +188,28 @@ static void gizmo_spin_prop_depth_set(
/* translate callbacks */
static void gizmo_spin_prop_translate_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, value);
}
static void gizmo_spin_prop_translate_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
- BLI_assert(mpr_prop->type->array_length == 3);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(gz_prop);
RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, value);
@@ -218,15 +218,15 @@ static void gizmo_spin_prop_translate_set(
/* angle callbacks */
static void gizmo_spin_prop_axis_angle_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_no[4];
RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
@@ -245,15 +245,15 @@ static void gizmo_spin_prop_axis_angle_get(
}
static void gizmo_spin_prop_axis_angle_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
const float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
float plane_no[4];
RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
@@ -280,43 +280,43 @@ static void gizmo_spin_prop_axis_angle_set(
/* angle callbacks */
static void gizmo_spin_prop_angle_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
value[0] = RNA_property_float_get(op->ptr, man->data.prop_angle);
}
static void gizmo_spin_prop_angle_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
- GizmoSpinGroup *man = mpr->parent_mgroup->customdata;
+ GizmoSpinGroup *man = gz->parent_gzgroup->customdata;
wmOperator *op = man->data.op;
- BLI_assert(mpr_prop->type->array_length == 1);
- UNUSED_VARS_NDEBUG(mpr_prop);
+ BLI_assert(gz_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(gz_prop);
const float *value = value_p;
RNA_property_float_set(op->ptr, man->data.prop_angle, value[0]);
gizmo_spin_exec(man);
}
-static bool gizmo_mesh_spin_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool gizmo_mesh_spin_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
wmOperator *op = WM_operator_last_redo(C);
if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) {
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
-static void gizmo_mesh_spin_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void gizmo_mesh_spin_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -325,16 +325,16 @@ static void gizmo_mesh_spin_setup(const bContext *C, wmGizmoGroup *mgroup)
}
struct GizmoSpinGroup *man = MEM_callocN(sizeof(GizmoSpinGroup), __func__);
- mgroup->customdata = man;
+ gzgroup->customdata = man;
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true);
- const wmGizmoType *wt_grab = WM_gizmotype_find("GIZMO_WT_grab_3d", true);
- const wmGizmoType *wt_dial = WM_gizmotype_find("GIZMO_WT_dial_3d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_grab = WM_gizmotype_find("GIZMO_GT_grab_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
- man->translate_z = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- man->translate_c = WM_gizmo_new_ptr(wt_grab, mgroup, NULL);
- man->rotate_c = WM_gizmo_new_ptr(wt_dial, mgroup, NULL);
- man->angle_z = WM_gizmo_new_ptr(wt_dial, mgroup, NULL);
+ man->translate_z = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ man->translate_c = WM_gizmo_new_ptr(gzt_grab, gzgroup, NULL);
+ man->rotate_c = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ man->angle_z = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, man->translate_z->color);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, man->translate_c->color);
@@ -403,28 +403,28 @@ static void gizmo_mesh_spin_setup(const bContext *C, wmGizmoGroup *mgroup)
}
static void gizmo_mesh_spin_draw_prepare(
- const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+ const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- GizmoSpinGroup *man = mgroup->customdata;
+ GizmoSpinGroup *man = gzgroup->customdata;
if (man->data.op->next) {
man->data.op = WM_operator_last_redo((bContext *)man->data.context);
}
gizmo_mesh_spin_update_from_op(man);
}
-static void MESH_WGT_spin(struct wmGizmoGroupType *wgt)
+static void MESH_GGT_spin(struct wmGizmoGroupType *gzgt)
{
- wgt->name = "Mesh Spin";
- wgt->idname = "MESH_WGT_spin";
+ gzgt->name = "Mesh Spin";
+ gzgt->idname = "MESH_GGT_spin";
- wgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = gizmo_mesh_spin_poll;
- wgt->setup = gizmo_mesh_spin_setup;
- wgt->draw_prepare = gizmo_mesh_spin_draw_prepare;
+ gzgt->poll = gizmo_mesh_spin_poll;
+ gzgt->setup = gizmo_mesh_spin_setup;
+ gzgt->draw_prepare = gizmo_mesh_spin_draw_prepare;
}
/** \} */
@@ -511,8 +511,8 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
#ifdef USE_GIZMO
if (ret & OPERATOR_FINISHED) {
/* Setup gizmos */
- if (v3d && ((v3d->mpr_flag & V3D_GIZMO_HIDE) == 0)) {
- WM_gizmo_group_type_ensure("MESH_WGT_spin");
+ if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
+ WM_gizmo_group_type_ensure("MESH_GGT_spin");
}
}
#endif
@@ -549,6 +549,6 @@ void MESH_OT_spin(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
#ifdef USE_GIZMO
- WM_gizmogrouptype_append(MESH_WGT_spin);
+ WM_gizmogrouptype_append(MESH_GGT_spin);
#endif
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 1be180b852c..486203462a0 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -78,7 +78,7 @@ typedef struct {
/* modal only */
float mcenter[2];
void *draw_handle_pixel;
- short mpr_flag;
+ short gizmo_flag;
} InsetData;
@@ -173,8 +173,8 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
- opdata->mpr_flag = v3d->mpr_flag;
- v3d->mpr_flag = V3D_GIZMO_HIDE;
+ opdata->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
}
}
@@ -196,7 +196,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op)
}
ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
if (v3d) {
- v3d->mpr_flag = opdata->mpr_flag;
+ v3d->gizmo_flag = opdata->gizmo_flag;
}
G.moving = 0;
}
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 8a9a5eadbdd..c98aef74ae7 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1007,13 +1007,13 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
copy_v3_v3(v2, ray_hit_best[1]);
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor(TH_TRANSFORM);
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(pos, v1);
immVertex3fv(pos, v2);
immEnd();
@@ -1040,26 +1040,27 @@ static void knife_init_colors(KnifeColors *colors)
static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
const KnifeTool_OpData *kcd = arg;
-
GPU_depth_test(false);
glPolygonOffset(1.0f, 1.0f);
- gpuPushMatrix();
- gpuMultMatrix(kcd->ob->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(kcd->ob->obmat);
+
+ if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
+ knifetool_draw_angle_snapping(kcd);
+ }
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (kcd->mode == MODE_DRAGGING) {
- if (kcd->is_angle_snapping)
- knifetool_draw_angle_snapping(kcd);
-
immUniformColor3ubv(kcd->colors.line);
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(pos, kcd->prev.cage);
immVertex3fv(pos, kcd->curr.cage);
immEnd();
@@ -1069,7 +1070,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.point);
GPU_point_size(11);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->prev.cage);
immEnd();
}
@@ -1078,7 +1079,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.curpoint);
GPU_point_size(9);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->prev.cage);
immEnd();
}
@@ -1087,7 +1088,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.edge);
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(pos, kcd->curr.edge->v1->cageco);
immVertex3fv(pos, kcd->curr.edge->v2->cageco);
immEnd();
@@ -1096,7 +1097,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.point);
GPU_point_size(11);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->curr.cage);
immEnd();
}
@@ -1105,47 +1106,50 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.curpoint);
GPU_point_size(9);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(pos, kcd->curr.cage);
immEnd();
}
if (kcd->totlinehit > 0) {
KnifeLineHit *lh;
- int i;
+ int i, v, vs;
+ float fcol[4];
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- /* draw any snapped verts first */
- immUniformColor4ubv(kcd->colors.point_a);
- GPU_point_size(11);
-
- immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit);
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
lh = kcd->linehits;
- for (i = 0; i < kcd->totlinehit; i++, lh++) {
+ for (i = 0, v = 0, vs = kcd->totlinehit - 1; i < kcd->totlinehit; i++, lh++) {
if (lh->v) {
- immVertex3fv(pos, lh->cagehit);
+ GPU_vertbuf_attr_set(vert, pos, v++, lh->cagehit);
+ }
+ else {
+ GPU_vertbuf_attr_set(vert, pos, vs--, lh->cagehit);
}
}
- immEnd();
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* draw any snapped verts first */
+ rgba_uchar_to_float(fcol, kcd->colors.point_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
+ GPU_matrix_bind(batch->interface);
+ GPU_point_size(11);
+ GPU_batch_draw_range_ex(batch, 0, v - 1, false);
/* now draw the rest */
- immUniformColor4ubv(kcd->colors.curpoint_a);
+ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
GPU_point_size(7);
+ GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false);
- immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit);
-
- lh = kcd->linehits;
- for (i = 0; i < kcd->totlinehit; i++, lh++) {
- if (!lh->v) {
- immVertex3fv(pos, lh->cagehit);
- }
- }
-
- immEnd();
+ GPU_batch_program_use_end(batch);
+ GPU_batch_discard(batch);
GPU_blend(false);
}
@@ -1157,7 +1161,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.line);
GPU_line_width(1.0);
- immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
@@ -1169,6 +1173,9 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
}
immEnd();
+
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
}
if (kcd->totkvert > 0) {
@@ -1178,7 +1185,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
immUniformColor3ubv(kcd->colors.point);
GPU_point_size(5.0);
- immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
BLI_mempool_iternew(kcd->kverts, &iter);
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
@@ -1189,11 +1196,14 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
}
immEnd();
+
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
}
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
/* Reset default */
GPU_depth_test(true);
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 87c006095ed..95c94c146e4 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -113,16 +113,16 @@ static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *a
if ((lcd->totedge > 0) || (lcd->totpoint > 0)) {
GPU_depth_test(false);
- gpuPushMatrix();
- gpuMultMatrix(lcd->ob->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(lcd->ob->obmat);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3ub(255, 0, 255);
if (lcd->totedge > 0) {
- immBegin(GWN_PRIM_LINES, lcd->totedge * 2);
+ immBegin(GPU_PRIM_LINES, lcd->totedge * 2);
for (int i = 0; i < lcd->totedge; i++) {
immVertex3fv(pos, lcd->edges[i][0]);
@@ -135,7 +135,7 @@ static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *a
if (lcd->totpoint > 0) {
GPU_point_size(3.0f);
- immBegin(GWN_PRIM_POINTS, lcd->totpoint);
+ immBegin(GPU_PRIM_POINTS, lcd->totpoint);
for (int i = 0; i < lcd->totpoint; i++) {
immVertex3fv(pos, lcd->points[i]);
@@ -146,7 +146,7 @@ static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *a
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
/* Reset default */
GPU_depth_test(true);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 2e7cf1fc76f..cdb8981801a 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1462,6 +1462,18 @@ static int edbm_select_mode_exec(bContext *C, wmOperator *op)
static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
+ if (CTX_wm_space_image(C)) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ /* Bypass when no action is needed. */
+ if (!RNA_struct_property_is_set(op->ptr, "type")) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
/* detecting these options based on shift/ctrl here is weak, but it's done
* to make this work when clicking buttons or menus */
if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index d7617a14ff3..76ba2e5c67e 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -41,11 +41,16 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_bitmap.h"
+#include "BLI_heap.h"
#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "BLI_linklist_stack.h"
#include "BLI_noise.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_sort_utils.h"
+#include "BLI_string.h"
#include "BKE_layer.h"
#include "BKE_material.h"
@@ -54,6 +59,7 @@
#include "BKE_report.h"
#include "BKE_texture.h"
#include "BKE_main.h"
+#include "BKE_mesh.h"
#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
@@ -6001,10 +6007,10 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static bool edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool edbm_sort_elements_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- const int action = RNA_enum_get(ptr, "type");
+ const int action = RNA_enum_get(op->ptr, "type");
/* Only show seed for randomize action! */
if (STREQ(prop_id, "seed")) {
@@ -6025,18 +6031,6 @@ static bool edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *pro
return true;
}
-static void edbm_sort_elements_ui(bContext *C, wmOperator *op)
-{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* Main auto-draw call. */
- uiDefAutoButsRNA(layout, &ptr, edbm_sort_elements_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
-}
-
void MESH_OT_sort_elements(wmOperatorType *ot)
{
static const EnumPropertyItem type_items[] = {
@@ -6072,7 +6066,7 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
ot->invoke = WM_menu_invoke;
ot->exec = edbm_sort_elements_exec;
ot->poll = ED_operator_editmesh;
- ot->ui = edbm_sort_elements_ui;
+ ot->poll_property = edbm_sort_elements_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -6924,3 +6918,1339 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
/** \} */
#endif /* WITH_FREESTYLE */
+
+/********************** Loop normals editing tools modal map. **********************/
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+/* NOTE: We could add more here, like e.g. a switch between local or global coordinates of target,
+ * use numinput to type in explicit vector values... */
+enum {
+ /* Generic commands. */
+ EDBM_CLNOR_MODAL_CANCEL = 1,
+ EDBM_CLNOR_MODAL_CONFIRM = 2,
+
+ /* Point To operator. */
+ EDBM_CLNOR_MODAL_POINTTO_RESET = 101,
+ EDBM_CLNOR_MODAL_POINTTO_INVERT = 102,
+ EDBM_CLNOR_MODAL_POINTTO_SPHERIZE = 103,
+ EDBM_CLNOR_MODAL_POINTTO_ALIGN = 104,
+
+ EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE = 110,
+ EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT = 111,
+ EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT = 112,
+ EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR = 113,
+ EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED = 114,
+};
+
+/* called in transform_ops.c, on each regeneration of keymaps */
+wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {EDBM_CLNOR_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {EDBM_CLNOR_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ /* Point To operator. */
+ {EDBM_CLNOR_MODAL_POINTTO_RESET, "RESET", 0, "Reset", "Reset normals to initial ones"},
+ {EDBM_CLNOR_MODAL_POINTTO_INVERT, "INVERT", 0, "Invert", "Toggle inversion of affected normals"},
+ {EDBM_CLNOR_MODAL_POINTTO_SPHERIZE, "SPHERIZE", 0, "Spherize", "Interpolate between new and original normals"},
+ {EDBM_CLNOR_MODAL_POINTTO_ALIGN, "ALIGN", 0, "Align", "Make all affected normals parallel"},
+
+ {EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE, "USE_MOUSE", 0, "Use Mouse", "Follow mouse cursor position"},
+ {EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT, "USE_PIVOT", 0, "Use Pivot",
+ "Use current rotation/scaling pivot point coordinates"},
+ {EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT, "USE_OBJECT", 0, "Use Object", "Use current edited object's location"},
+ {EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR, "SET_USE_3DCURSOR", 0, "Set and Use 3D Cursor",
+ "Set new 3D cursor position and use it"},
+ {EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED, "SET_USE_SELECTED", 0, "Select and Use Mesh Item",
+ "Select new active mesh element and use its location"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static const char *keymap_name = "Custom Normals Modal Map";
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, keymap_name);
+
+ /* We only need to add map once */
+ if (keymap && keymap->modal_items)
+ return NULL;
+
+ keymap = WM_modalkeymap_add(keyconf, keymap_name, modal_items);
+
+ /* Generic items for modal map. */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, EDBM_CLNOR_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, EDBM_CLNOR_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, EDBM_CLNOR_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_CONFIRM);
+
+ /* Point To items for modal map */
+ WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_RESET);
+ WM_modalkeymap_add_item(keymap, IKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_INVERT);
+ WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_SPHERIZE);
+ WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_ALIGN);
+
+ WM_modalkeymap_add_item(keymap, MKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE);
+ WM_modalkeymap_add_item(keymap, LKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT);
+ WM_modalkeymap_add_item(keymap, OKEY, KM_PRESS, KM_NOTHING, 0, EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT);
+
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_CLICK, KM_CTRL, 0, EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_CLICK, KM_CTRL, 0, EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED);
+
+ WM_modalkeymap_assign(keymap, "MESH_OT_point_normals");
+
+ return keymap;
+}
+
+#define CLNORS_VALID_VEC_LEN (1e-4f)
+
+/********************** 'Point to' Loop Normals **********************/
+
+enum {
+ EDBM_CLNOR_POINTTO_MODE_COORDINATES = 1,
+ EDBM_CLNOR_POINTTO_MODE_MOUSE = 2,
+};
+
+static EnumPropertyItem clnors_pointto_mode_items[] = {
+ {EDBM_CLNOR_POINTTO_MODE_COORDINATES, "COORDINATES", 0, "Coordinates",
+ "Use static coordinates (defined by various means)"},
+ {EDBM_CLNOR_POINTTO_MODE_MOUSE, "MOUSE", 0, "Mouse", "Follow mouse cursor"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* Initialize loop normal data */
+static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+
+ op->customdata = lnors_ed_arr;
+
+ return lnors_ed_arr->totloop;
+}
+
+static void point_normals_free(bContext *C, wmOperator *op)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ op->customdata = NULL;
+ ED_area_status_text(CTX_wm_area(C), NULL);
+}
+
+static void point_normals_update_header(bContext *C, wmOperator *op)
+{
+ char header[UI_MAX_DRAW_STR];
+ char buf[UI_MAX_DRAW_STR];
+
+ char *p = buf;
+ int available_len = sizeof(buf);
+
+#define WM_MODALKEY(_id) \
+ WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
+
+ BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, "
+ "%s: point to mouse (%s), %s: point to Pivot, "
+ "%s: point to object origin, %s: reset normals, "
+ "%s: set & point to 3D cursor, %s: select & point to mesh item, "
+ "%s: invert normals (%s), %s: spherize (%s), %s: align (%s)"),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_CONFIRM), WM_MODALKEY(EDBM_CLNOR_MODAL_CANCEL),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE),
+ WM_bool_as_string(RNA_enum_get(op->ptr, "mode") == EDBM_CLNOR_POINTTO_MODE_MOUSE),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT), WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_RESET), WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_INVERT), WM_bool_as_string(RNA_boolean_get(op->ptr, "invert")),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_SPHERIZE),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "spherize")),
+ WM_MODALKEY(EDBM_CLNOR_MODAL_POINTTO_ALIGN), WM_bool_as_string(RNA_boolean_get(op->ptr, "align")));
+
+#undef WM_MODALKEY
+
+ ED_area_status_text(CTX_wm_area(C), header);
+}
+
+/* TODO move that to generic function in BMesh? */
+static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center)
+{
+ BMVert *v;
+ BMIter viter;
+ int i = 0;
+
+ zero_v3(r_center);
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ add_v3_v3(r_center, v->co);
+ i++;
+ }
+ }
+ mul_v3_fl(r_center, 1.0f / (float)i);
+}
+
+static void point_normals_apply(bContext *C, wmOperator *op, float target[3], const bool do_reset)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMesh *bm = BKE_editmesh_from_object(obedit)->bm;
+ BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
+
+ const bool do_invert = RNA_boolean_get(op->ptr, "invert");
+ const bool do_spherize = RNA_boolean_get(op->ptr, "spherize");
+ const bool do_align = RNA_boolean_get(op->ptr, "align");
+ float center[3];
+
+ if (do_align && !do_reset) {
+ bmesh_selected_verts_center_calc(bm, center);
+ }
+
+ sub_v3_v3(target, obedit->loc); /* Move target to local coordinates. */
+
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (do_reset) {
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ else if (do_spherize) {
+ /* Note that this is *not* real spherical interpolation. Probably good enough in this case though? */
+ const float strength = RNA_float_get(op->ptr, "spherize_strength");
+ float spherized_normal[3];
+
+ sub_v3_v3v3(spherized_normal, target, lnor_ed->loc);
+ normalize_v3(spherized_normal); /* otherwise, multiplication by strength is meaningless... */
+ mul_v3_fl(spherized_normal, strength);
+ mul_v3_v3fl(lnor_ed->nloc, lnor_ed->niloc, 1.0f - strength);
+ add_v3_v3(lnor_ed->nloc, spherized_normal);
+ }
+ else if (do_align) {
+ sub_v3_v3v3(lnor_ed->nloc, target, center);
+ }
+ else {
+ sub_v3_v3v3(lnor_ed->nloc, target, lnor_ed->loc);
+ }
+
+ if (do_invert && !do_reset) {
+ negate_v3(lnor_ed->nloc);
+ }
+ if (normalize_v3(lnor_ed->nloc) >= CLNORS_VALID_VEC_LEN) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ }
+}
+
+static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ float target[3];
+
+ int ret = OPERATOR_PASS_THROUGH;
+ int mode = RNA_enum_get(op->ptr, "mode");
+ int new_mode = mode;
+ bool force_mousemove = false;
+ bool do_reset = false;
+
+ PropertyRNA *prop_target = RNA_struct_find_property(op->ptr, "target_location");
+
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case EDBM_CLNOR_MODAL_CONFIRM:
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case EDBM_CLNOR_MODAL_CANCEL:
+ do_reset = true;
+ ret = OPERATOR_CANCELLED;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_RESET:
+ do_reset = true;
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_INVERT:
+ {
+ PropertyRNA *prop_invert = RNA_struct_find_property(op->ptr, "invert");
+ RNA_property_boolean_set(op->ptr, prop_invert, !RNA_property_boolean_get(op->ptr, prop_invert));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_SPHERIZE:
+ {
+ PropertyRNA *prop_spherize = RNA_struct_find_property(op->ptr, "spherize");
+ RNA_property_boolean_set(op->ptr, prop_spherize, !RNA_property_boolean_get(op->ptr, prop_spherize));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_ALIGN:
+ {
+ PropertyRNA *prop_align = RNA_struct_find_property(op->ptr, "align");
+ RNA_property_boolean_set(op->ptr, prop_align, !RNA_property_boolean_get(op->ptr, prop_align));
+ RNA_property_float_get_array(op->ptr, prop_target, target);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ }
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_MOUSE:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_MOUSE;
+ force_mousemove = true; /* We want to immediately update to mouse cursor position... */
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_OBJECT:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ copy_v3_v3(target, obedit->loc);
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_SET_USE_3DCURSOR:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ ED_view3d_cursor3d_update(C, event->mval, false, V3D_CURSOR_ORIENT_NONE);
+ copy_v3_v3(target, ED_view3d_cursor3d_get(scene, v3d)->location);
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_SET_USE_SELECTED:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ view3d_operator_needs_opengl(C);
+ if (EDBM_select_pick(C, event->mval, false, false, false)) {
+ ED_object_editmode_calc_active_center(obedit, false, target); /* Point to newly selected active. */
+ add_v3_v3(target, obedit->loc);
+ ret = OPERATOR_RUNNING_MODAL;
+ }
+ break;
+
+ case EDBM_CLNOR_MODAL_POINTTO_USE_PIVOT:
+ new_mode = EDBM_CLNOR_POINTTO_MODE_COORDINATES;
+ switch (scene->toolsettings->transform_pivot_point) {
+ case V3D_AROUND_CENTER_BOUNDS: /* calculateCenterBound */
+ {
+ BMVert *v;
+ BMIter viter;
+ float min[3], max[3];
+ int i = 0;
+
+ BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ if (i) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
+ else {
+ copy_v3_v3(min, v->co);
+ copy_v3_v3(max, v->co);
+ }
+ i++;
+ }
+ }
+ mid_v3_v3v3(target, min, max);
+ add_v3_v3(target, obedit->loc);
+ break;
+ }
+
+ case V3D_AROUND_CENTER_MEAN:
+ {
+ bmesh_selected_verts_center_calc(bm, target);
+ add_v3_v3(target, obedit->loc);
+ break;
+ }
+
+ case V3D_AROUND_CURSOR:
+ copy_v3_v3(target, ED_view3d_cursor3d_get(scene, v3d)->location);
+ break;
+
+ case V3D_AROUND_ACTIVE:
+ if (!ED_object_editmode_calc_active_center(obedit, false, target)) {
+ zero_v3(target);
+ }
+ add_v3_v3(target, obedit->loc);
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Does not support Individual Origin as pivot");
+ copy_v3_v3(target, obedit->loc);
+ }
+ ret = OPERATOR_RUNNING_MODAL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (new_mode != mode) {
+ mode = new_mode;
+ RNA_enum_set(op->ptr, "mode", mode);
+ }
+
+ /* Only handle mousemove event in case we are in mouse mode. */
+ if (event->type == MOUSEMOVE || force_mousemove) {
+ if (mode == EDBM_CLNOR_POINTTO_MODE_MOUSE) {
+ ARegion *ar = CTX_wm_region(C);
+ float center[3];
+
+ bmesh_selected_verts_center_calc(bm, center);
+
+ ED_view3d_win_to_3d_int(v3d, ar, center, event->mval, target);
+
+ ret = OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ if (ret != OPERATOR_PASS_THROUGH) {
+ if (!ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
+ RNA_property_float_set_array(op->ptr, prop_target, target);
+ }
+ point_normals_apply(C, op, target, do_reset);
+ EDBM_update_generic(em, true, false); /* Recheck bools. */
+
+ point_normals_update_header(C, op);
+ }
+
+ if (ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
+ point_normals_free(C, op);
+ }
+
+ return ret;
+}
+
+static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!point_normals_init(C, op, event)) {
+ point_normals_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_modal_handler(C, op);
+
+ point_normals_update_header(C, op);
+
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR;
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int edbm_point_normals_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!point_normals_init(C, op, NULL)) {
+ point_normals_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Note that 'mode' is ignored in exec case, we directly use vector stored in target_location, whatever that is. */
+
+ float target[3];
+ RNA_float_get_array(op->ptr, "target_location", target);
+
+ point_normals_apply(C, op, target, false);
+
+ EDBM_update_generic(em, true, false);
+ point_normals_free(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool point_normals_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Only show strength option if spherize is enabled. */
+ if (STREQ(prop_id, "spherize_strength")) {
+ return (bool)RNA_boolean_get(ptr, "spherize");
+ }
+
+ /* Else, show it! */
+ return true;
+}
+
+static void edbm_point_normals_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, point_normals_draw_check_prop, NULL, '\0', false);
+}
+
+void MESH_OT_point_normals(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Point Normals to Target";
+ ot->description = "Point selected custom normals to specified Target";
+ ot->idname = "MESH_OT_point_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_point_normals_exec;
+ ot->invoke = edbm_point_normals_invoke;
+ ot->modal = edbm_point_normals_modal;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_point_normals_ui;
+ ot->cancel = point_normals_free;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", clnors_pointto_mode_items, EDBM_CLNOR_POINTTO_MODE_COORDINATES,
+ "Mode", "How to define coordinates to point custom normals to");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ RNA_def_boolean(ot->srna, "invert", false, "Invert", "Invert affected normals");
+
+ RNA_def_boolean(ot->srna, "align", false, "Align", "Make all affected normals parallel");
+
+ RNA_def_float_vector(ot->srna, "target_location", 3, (float[3]){0.0f, 0.0f, 0.0f}, -FLT_MAX, FLT_MAX,
+ "Target", "Target location to which normals will point", -1000.0f, 1000.0f);
+
+ RNA_def_boolean(ot->srna, "spherize", false,
+ "Spherize", "Interpolate between original and new normals");
+
+ RNA_def_float(ot->srna, "spherize_strength", 0.1, 0.0f, 1.0f,
+ "Spherize Strength", "Ratio of spherized normal to original normal", 0.0f, 1.0f);
+}
+
+/********************** Split/Merge Loop Normals **********************/
+
+static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
+{
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ BLI_SMALLSTACK_DECLARE(clnors, short *);
+
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+
+ BM_normals_loops_edges_tag(bm, false);
+
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ MLoopNorSpace *lnor_space = bm->lnor_spacearr->lspacearr[lnor_ed->loop_index];
+
+ if ((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
+ LinkNode *loops = lnor_space->loops;
+ float avg_normal[3] = {0.0f, 0.0f, 0.0f};
+ short *clnors_data;
+
+ for (; loops; loops = loops->next) {
+ BMLoop *l = loops->link;
+ const int loop_index = BM_elem_index_get(l);
+
+ BMLoopNorEditData *lnor_ed_tmp = lnors_ed_arr->lidx_to_lnor_editdata[loop_index];
+ BLI_assert(lnor_ed_tmp->loop_index == loop_index && lnor_ed_tmp->loop == l);
+ add_v3_v3(avg_normal, lnor_ed_tmp->nloc);
+ BLI_SMALLSTACK_PUSH(clnors, lnor_ed_tmp->clnors_data);
+ BM_elem_flag_enable(l, BM_ELEM_TAG);
+ }
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((clnors_data = BLI_SMALLSTACK_POP(clnors))) {
+ BKE_lnor_space_custom_normal_to_data(lnor_space, avg_normal, clnors_data);
+ }
+ }
+ }
+}
+
+static void normals_split(BMesh *bm)
+{
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
+
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+
+ BM_normals_loops_edges_tag(bm, true);
+
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) && (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr))))
+ {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float avg_normal[3] = { 0.0f };
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
+ add_v3_v3(avg_normal, lfan_pivot->f->no);
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
+ }
+ }
+ }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+}
+
+static int normals_split_merge(bContext *C, const bool do_merge)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMEdge *e;
+ BMIter eiter;
+
+ BKE_editmesh_lnorspace_update(em);
+
+ BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL;
+
+ mesh_set_smooth_faces(em, do_merge);
+
+ BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ }
+ }
+ if (do_merge == 0) {
+ Mesh *me = obedit->data;
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
+
+ if (do_merge) {
+ normals_merge(bm, lnors_ed_arr);
+ }
+ else {
+ normals_split(bm);
+ }
+
+ if (lnors_ed_arr) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
+
+ EDBM_update_generic(em, true, false);
+
+ return OPERATOR_FINISHED;
+}
+
+static int edbm_merge_normals_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return normals_split_merge(C, true);
+}
+
+void MESH_OT_merge_normals(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Merge Normals";
+ ot->description = "Merge custom normals of selected vertices";
+ ot->idname = "MESH_OT_merge_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_merge_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int edbm_split_normals_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return normals_split_merge(C, false);
+}
+
+void MESH_OT_split_normals(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split Normals";
+ ot->description = "Split custom normals of selected vertices";
+ ot->idname = "MESH_OT_split_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_split_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Average Loop Normals **********************/
+
+enum {
+ EDBM_CLNOR_AVERAGE_LOOP = 1,
+ EDBM_CLNOR_AVERAGE_FACE_AREA = 2,
+ EDBM_CLNOR_AVERAGE_ANGLE = 3,
+};
+
+static EnumPropertyItem average_method_items[] = {
+ {EDBM_CLNOR_AVERAGE_LOOP, "CUSTOM_NORMAL", 0, "Custom Normal", "Take Average of vert Normals"},
+ {EDBM_CLNOR_AVERAGE_FACE_AREA, "FACE_AREA", 0, "Face Area", "Set all vert normals by Face Area"},
+ {EDBM_CLNOR_AVERAGE_ANGLE, "CORNER_ANGLE", 0, "Corner Angle", "Set all vert normals by Corner Angle"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int edbm_average_normals_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
+
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
+
+ const int average_type = RNA_enum_get(op->ptr, "average_type");
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ const float absweight = (float) RNA_int_get(op->ptr, "weight");
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+
+ float weight = absweight / 50.0f;
+ if (absweight == 100.0f) {
+ weight = (float)SHRT_MAX;
+ }
+ else if (absweight == 1.0f) {
+ weight = 1 / (float)SHRT_MAX;
+ }
+ else if ((weight - 1) * 25 > 1) {
+ weight = (weight - 1) * 25;
+ }
+
+ BM_normals_loops_edges_tag(bm, true);
+
+ Heap *loop_weight = BLI_heap_new();
+
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) && (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr))))
+ {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ float val = 1.0f;
+ if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
+ val = 1.0f / BM_face_calc_area(lfan_pivot->f);
+ }
+ else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
+ val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
+ }
+
+ BLI_heap_insert(loop_weight, val, lfan_pivot);
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float wnor[3], avg_normal[3] = { 0.0f }, count = 0;
+ float val = BLI_heap_node_value(BLI_heap_top(loop_weight));
+
+ while (!BLI_heap_is_empty(loop_weight)) {
+ const float cur_val = BLI_heap_node_value(BLI_heap_top(loop_weight));
+ if (!compare_ff(val, cur_val, threshold)) {
+ count++;
+ val = cur_val;
+ }
+ l = BLI_heap_pop_min(loop_weight);
+ BLI_SMALLSTACK_PUSH(loops, l);
+
+ const float n_weight = pow(weight, count);
+
+ if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
+ }
+ else {
+ copy_v3_v3(wnor, l->f->no);
+ }
+ mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
+ add_v3_v3(avg_normal, wnor);
+ }
+
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
+ }
+ }
+ }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+
+ BLI_heap_free(loop_weight, NULL);
+ EDBM_update_generic(em, true, false);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool average_normals_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const int average_type = RNA_enum_get(ptr, "average_type");
+
+ /* Only show weight/threshold options in loop average type. */
+ if (STREQ(prop_id, "weight")) {
+ return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
+ }
+ else if (STREQ(prop_id, "threshold")) {
+ return (average_type == EDBM_CLNOR_AVERAGE_LOOP);
+ }
+
+ /* Else, show it! */
+ return true;
+}
+
+static void edbm_average_normals_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, average_normals_draw_check_prop, NULL, '\0', false);
+}
+
+void MESH_OT_average_normals(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Average Normals";
+ ot->description = "Average custom normals of selected vertices";
+ ot->idname = "MESH_OT_average_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_average_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_average_normals_ui;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "average_type", average_method_items, EDBM_CLNOR_AVERAGE_LOOP,
+ "Type", "Averaging method");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ RNA_def_int(ot->srna, "weight", 50, 1, 100, "Weight", "Weight applied per face", 1, 100);
+
+ RNA_def_float(ot->srna, "threshold", 0.01f, 0, 10, "Threshold",
+ "Threshold value for different weights to be considered equal", 0, 5);
+}
+
+/********************** Custom Normal Interface Tools **********************/
+
+enum {
+ EDBM_CLNOR_TOOLS_COPY = 1,
+ EDBM_CLNOR_TOOLS_PASTE = 2,
+ EDBM_CLNOR_TOOLS_MULTIPLY = 3,
+ EDBM_CLNOR_TOOLS_ADD = 4,
+ EDBM_CLNOR_TOOLS_RESET = 5,
+};
+
+static EnumPropertyItem normal_vector_tool_items[] = {
+ {EDBM_CLNOR_TOOLS_COPY, "COPY", 0, "Copy Normal", "Copy normal to buffer"},
+ {EDBM_CLNOR_TOOLS_PASTE, "PASTE", 0, "Paste Normal", "Paste normal from buffer"},
+ {EDBM_CLNOR_TOOLS_ADD, "ADD", 0, "Add Normal", "Add normal vector with selection"},
+ {EDBM_CLNOR_TOOLS_MULTIPLY, "MULTIPLY", 0, "Multiply Normal", "Multiply normal vector with selection"},
+ {EDBM_CLNOR_TOOLS_RESET, "RESET", 0, "Reset Normal", "Reset buffer and/or normal of selected element"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const bool absolute = RNA_boolean_get(op->ptr, "absolute");
+
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ float *normal_vector = scene->toolsettings->normal_vector;
+
+ switch (mode) {
+ case EDBM_CLNOR_TOOLS_COPY:
+ if (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1) {
+ BKE_report(op->reports, RPT_ERROR, "Can only copy custom normal, vertex normal or face normal");
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ return OPERATOR_CANCELLED;
+ }
+ bool join = true;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
+ join = false;
+ }
+ }
+ if (lnors_ed_arr->totloop == 1) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ else if (bm->totfacesel == 1) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ copy_v3_v3(scene->toolsettings->normal_vector, f->no);
+ }
+ }
+ }
+ else if (join) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_PASTE:
+ if (!absolute) {
+ if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
+ /* If normal is nearly 0, do nothing. */
+ break;
+ }
+ }
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (absolute) {
+ float abs_normal[3];
+ copy_v3_v3(abs_normal, lnor_ed->loc);
+ negate_v3(abs_normal);
+ add_v3_v3(abs_normal, normal_vector);
+
+ if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(abs_normal, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], abs_normal, lnor_ed->clnors_data);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], normal_vector, lnor_ed->clnors_data);
+ }
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_MULTIPLY:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_ADD:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ add_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ break;
+
+ case EDBM_CLNOR_TOOLS_RESET:
+ zero_v3(normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], normal_vector, lnor_ed->clnors_data);
+ }
+ break;
+
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+
+ EDBM_update_generic(em, true, false);
+ return OPERATOR_FINISHED;
+}
+
+static bool normals_tools_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ const int mode = RNA_enum_get(ptr, "mode");
+
+ /* Only show absolute option in paste mode. */
+ if (STREQ(prop_id, "absolute")) {
+ return (mode == EDBM_CLNOR_TOOLS_PASTE);
+ }
+
+ /* Else, show it! */
+ return true;
+}
+
+static void edbm_normals_tools_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, normals_tools_draw_check_prop, NULL, '\0', false);
+}
+
+void MESH_OT_normals_tools(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Normals Vector Tools";
+ ot->description = "Custom normals tools using Normal Vector of UI";
+ ot->idname = "MESH_OT_normals_tools";
+
+ /* api callbacks */
+ ot->exec = edbm_normals_tools_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->ui = edbm_normals_tools_ui;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", normal_vector_tool_items, EDBM_CLNOR_TOOLS_COPY,
+ "Mode", "Mode of tools taking input from Interface");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ RNA_def_boolean(ot->srna, "absolute", false, "Absolute Coordinates", "Copy Absolute coordinates or Normal vector");
+}
+
+static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMIter fiter, viter, eiter, liter;
+
+ const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp");
+
+ BKE_editmesh_lnorspace_update(em);
+
+ float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__);
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM(v, &viter, f, BM_VERTS_OF_FACE) {
+ const int v_index = BM_elem_index_get(v);
+ add_v3_v3(vnors[v_index], f->no);
+ }
+ }
+ }
+ for (int i = 0; i < bm->totvert; i++) {
+ if (!is_zero_v3(vnors[i]) && normalize_v3(vnors[i]) < CLNORS_VALID_VEC_LEN) {
+ zero_v3(vnors[i]);
+ }
+ }
+
+ BLI_bitmap *loop_set = BLI_BITMAP_NEW(bm->totloop, __func__);
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM(e, &eiter, f, BM_EDGES_OF_FACE) {
+ if (!keep_sharp || (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(e, BM_ELEM_SELECT))) {
+ BM_ITER_ELEM(v, &viter, e, BM_VERTS_OF_EDGE) {
+ l = BM_face_vert_share_loop(f, v);
+ const int l_index = BM_elem_index_get(l);
+ const int v_index = BM_elem_index_get(l->v);
+
+ if (!is_zero_v3(vnors[v_index])) {
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], vnors[v_index], clnors);
+
+ if (bm->lnor_spacearr->lspacearr[l_index]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_BITMAP_ENABLE(loop_set, l_index);
+ }
+ else {
+ LinkNode *loops = bm->lnor_spacearr->lspacearr[l_index]->loops;
+ for (; loops; loops = loops->next) {
+ BLI_BITMAP_ENABLE(loop_set, BM_elem_index_get((BMLoop *)loops->link));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int v_index;
+ BM_ITER_MESH_INDEX(v, &viter, bm, BM_VERTS_OF_MESH, v_index) {
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BLI_BITMAP_TEST(loop_set, BM_elem_index_get(l))) {
+ const int loop_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], vnors[v_index], clnors);
+ }
+ }
+ }
+
+ MEM_freeN(loop_set);
+ MEM_freeN(vnors);
+ EDBM_update_generic(em, true, false);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Normals From Faces";
+ ot->description = "Set the custom normals from the selected faces ones";
+ ot->idname = "MESH_OT_set_normals_from_faces";
+
+ /* api callbacks */
+ ot->exec = edbm_set_normals_from_faces_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "keep_sharp", 0, "Keep Sharp Edges", "Do not set sharp edges to face");
+}
+
+static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+
+ float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
+
+ /* This is weird choice of operation, taking all loops of faces of current vertex... Could lead to some rather
+ * far away loops weighting as much as very close ones (topologically speaking), with complex polygons.
+ * Using topological distance here (rather than geometrical one) makes sense imho, but would rather go with
+ * a more consistent and flexible code, we could even add max topological distance to take into account,
+ * and a weighting curve...
+ * Would do that later though, think for now we can live with that choice. --mont29 */
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ l = lnor_ed->loop;
+ float loop_normal[3];
+
+ BM_ITER_ELEM(f, &fiter, l->v, BM_FACES_OF_VERT) {
+ BMLoop *l_other;
+ BM_ITER_ELEM(l_other, &liter, f, BM_LOOPS_OF_FACE) {
+ const int l_index_other = BM_elem_index_get(l_other);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
+ BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
+ add_v3_v3(smooth_normal[i], loop_normal);
+ }
+ }
+ }
+
+ const float factor = RNA_float_get(op->ptr, "factor");
+
+ lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ float current_normal[3];
+
+ if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
+
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
+
+ /* Note: again, this is not true spherical interpolation that normals would need...
+ * But it's probably good enough for now. */
+ mul_v3_fl(current_normal, 1.0f - factor);
+ mul_v3_fl(smooth_normal[i], factor);
+ add_v3_v3(current_normal, smooth_normal[i]);
+
+ if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
+
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ MEM_freeN(smooth_normal);
+
+ EDBM_update_generic(em, true, false);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Smoothen Normals";
+ ot->description = "Smoothen custom normals based on adjacent vertex normals";
+ ot->idname = "MESH_OT_smoothen_normals";
+
+ /* api callbacks */
+ ot->exec = edbm_smoothen_normals_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor",
+ "Specifies weight of smooth vs original normal", 0.0f, 1.0f);
+}
+
+/********************** Weighted Normal Modifier Face Strength **********************/
+
+static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMIter fiter;
+
+ BM_select_history_clear(bm);
+
+ const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ if (cd_prop_int_index == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
+ cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ }
+ cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_index);
+
+ const int face_strength = scene->toolsettings->face_strength;
+ const bool set = RNA_boolean_get(op->ptr, "set");
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ if (set) {
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength = face_strength;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ if (*strength == face_strength) {
+ BM_face_select_set(bm, f, true);
+ BM_select_history_store(bm, f);
+ }
+ else {
+ BM_face_select_set(bm, f, false);
+ }
+ }
+ }
+
+ EDBM_update_generic(em, false, false);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Face Strength";
+ ot->description = "Set/Get strength of face (used in Weighted Normal modifier)";
+ ot->idname = "MESH_OT_mod_weighted_strength";
+
+ /* api callbacks */
+ ot->exec = edbm_mod_weighted_strength_exec;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 11606840b42..26f3c17a97c 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -598,6 +598,8 @@ static void undomesh_to_editmesh(UndoMesh *um, BMEditMesh *em, Mesh *obmesh)
bm->selectmode = um->selectmode;
em->ob = ob;
+ bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL;
+
/* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
* if the active is a basis for any other. */
if (key && (key->type == KEY_RELATIVE)) {
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 2ee3362063b..fd87ba32653 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -565,8 +565,8 @@ UvVertMap *BM_uv_vert_map_create(
}
BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- buf->tfindex = i;
- buf->f = a;
+ buf->loop_of_poly_index = i;
+ buf->poly_index = a;
buf->separate = 0;
buf->next = vmap->vert[BM_elem_index_get(l->v)];
@@ -597,9 +597,9 @@ UvVertMap *BM_uv_vert_map_create(
v->next = newvlist;
newvlist = v;
- efa = BM_face_at_index(bm, v->f);
+ efa = BM_face_at_index(bm, v->poly_index);
- l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
+ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
@@ -608,15 +608,15 @@ UvVertMap *BM_uv_vert_map_create(
while (iterv) {
next = iterv->next;
- efa = BM_face_at_index(bm, iterv->f);
- l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ efa = BM_face_at_index(bm, iterv->poly_index);
+ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
sub_v2_v2v2(uvdiff, uv2, uv);
if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] &&
- (!use_winding || winding[iterv->f] == winding[v->f]))
+ (!use_winding || winding[iterv->poly_index] == winding[v->poly_index]))
{
if (lastv) lastv->next = next;
else vlist = next;
@@ -713,7 +713,7 @@ UvElementMap *BM_uv_element_map_create(
buf->l = l;
buf->separate = 0;
buf->island = INVALID_ISLAND;
- buf->tfindex = i;
+ buf->loop_of_poly_index = i;
buf->next = element_map->vert[BM_elem_index_get(l->v)];
element_map->vert[BM_elem_index_get(l->v)] = buf;
@@ -826,7 +826,7 @@ UvElementMap *BM_uv_element_map_create(
map[element - element_map->buf] = islandbufsize;
islandbuf[islandbufsize].l = element->l;
islandbuf[islandbufsize].separate = element->separate;
- islandbuf[islandbufsize].tfindex = element->tfindex;
+ islandbuf[islandbufsize].loop_of_poly_index = element->loop_of_poly_index;
islandbuf[islandbufsize].island = nislands;
islandbufsize++;
@@ -1348,7 +1348,10 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
/* in debug mode double check we didn't need to recalculate */
BLI_assert(BM_mesh_elem_table_check(em->bm) == true);
}
-
+ if (em->bm->spacearr_dirty & BM_SPACEARR_BMO_SET) {
+ BM_lnorspace_invalidate(em->bm, false);
+ em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET;
+ }
/* don't keep stale derivedMesh data around, see: [#38872] */
BKE_editmesh_free_derivedmesh(em);
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index cc9448e5e06..4a67dea9d4b 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -240,6 +240,16 @@ void MESH_OT_duplicate(struct wmOperatorType *ot);
void MESH_OT_merge(struct wmOperatorType *ot);
void MESH_OT_remove_doubles(struct wmOperatorType *ot);
void MESH_OT_poke(struct wmOperatorType *ot);
+void MESH_OT_point_normals(struct wmOperatorType *ot);
+void MESH_OT_merge_normals(struct wmOperatorType *ot);
+void MESH_OT_split_normals(struct wmOperatorType *ot);
+void MESH_OT_normals_tools(struct wmOperatorType *ot);
+void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot);
+void MESH_OT_average_normals(struct wmOperatorType *ot);
+void MESH_OT_smoothen_normals(struct wmOperatorType *ot);
+void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot);
+
+struct wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf);
#ifdef WITH_FREESTYLE
void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 0fcc5ada854..842a1ecab35 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -200,6 +200,15 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_bisect);
WM_operatortype_append(MESH_OT_symmetrize);
WM_operatortype_append(MESH_OT_symmetry_snap);
+
+ WM_operatortype_append(MESH_OT_point_normals);
+ WM_operatortype_append(MESH_OT_merge_normals);
+ WM_operatortype_append(MESH_OT_split_normals);
+ WM_operatortype_append(MESH_OT_normals_tools);
+ WM_operatortype_append(MESH_OT_set_normals_from_faces);
+ WM_operatortype_append(MESH_OT_average_normals);
+ WM_operatortype_append(MESH_OT_smoothen_normals);
+ WM_operatortype_append(MESH_OT_mod_weighted_strength);
}
#if 0 /* UNUSED, remove? */
@@ -335,22 +344,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "vertex_only", true);
- /* selecting */
- for (int i = 0; i < 4; i++) {
- const bool is_extend = (i & 1);
- const bool is_expand = (i & 2);
- const int key_modifier = (is_extend ? KM_SHIFT : 0) | (is_expand ? KM_CTRL : 0);
- for (int j = 0; j < 3; j++) {
- kmi = WM_keymap_add_item(keymap, "MESH_OT_select_mode", ONEKEY + j, KM_PRESS, key_modifier, 0);
- RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX << j);
- if (is_extend) {
- RNA_boolean_set(kmi->ptr, "use_extend", true);
- }
- if (is_expand) {
- RNA_boolean_set(kmi->ptr, "use_expand", true);
- }
- }
- }
+ /* Selec Vert/Edge/Face. */
+ ED_keymap_editmesh_elem_mode(keyconf, keymap);
/* standard mouse selection goes via space_view3d */
kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
@@ -479,6 +474,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_vert_connect_path", JKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_point_normals", LKEY, KM_PRESS, KM_ALT, 0);
+
/* Vertex Slide */
WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0);
/* use KM_CLICK because same key is used for tweaks */
@@ -528,4 +525,5 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
ED_keymap_proportional_editmode(keyconf, keymap, true);
knifetool_modal_keymap(keyconf);
+ point_normals_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 305e3287029..739975a6278 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -31,6 +31,8 @@ set(INC
../../makesdna
../../makesrna
../../modifiers
+ ../../gpencil_modifiers
+ ../../shader_fx
../../python
../../render/extern/include
../../windowmanager
@@ -53,6 +55,8 @@ set(SRC
object_hook.c
object_modes.c
object_modifier.c
+ object_gpencil_modifier.c
+ object_shader_fx.c
object_ops.c
object_random.c
object_relations.c
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index a8917f4c4aa..f41c4071634 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -71,6 +71,7 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
+#include "BKE_gpencil.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@@ -103,6 +104,7 @@
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_gpencil.h"
#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_node.h"
@@ -985,6 +987,119 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
+/********************* Add Gpencil Operator ********************/
+
+static int object_gpencil_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ float loc[3], rot[3];
+ unsigned int layer;
+ bool newob = false;
+
+ /* Hack: Force view-align to be on by default
+ * since it's not nice for adding shapes in 2D
+ * for them to end up aligned oddly, but only for Monkey
+ */
+ if ((RNA_struct_property_is_set(op->ptr, "view_align") == false) &&
+ (type == GP_MONKEY))
+ {
+ RNA_boolean_set(op->ptr, "view_align", true);
+ }
+
+ /* Note: We use 'Y' here (not 'Z'), as */
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &layer, NULL))
+ return OPERATOR_CANCELLED;
+
+ /* add new object if not currently editing a GP object,
+ * or if "empty" was chosen (i.e. user wants a blank GP canvas)
+ */
+ if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
+ const char *ob_name = (type == GP_MONKEY) ? "Suzanne" : NULL;
+ float radius = RNA_float_get(op->ptr, "radius");
+
+ ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, layer);
+ gpd = ob->data;
+ newob = true;
+
+ BKE_object_obdata_size_init(ob, GP_OBGPENCIL_DEFAULT_SIZE * radius);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
+ }
+
+ /* create relevant geometry */
+ switch (type) {
+ case GP_STROKE:
+ {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_stroke(C, mat);
+ break;
+ }
+ case GP_MONKEY:
+ {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_monkey(C, mat);
+ break;
+ }
+ case GP_EMPTY:
+ /* do nothing */
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not implemented");
+ break;
+ }
+
+ /* if this is a new object, initialise default stuff (colors, etc.) */
+ if (newob) {
+ ED_gpencil_add_defaults(C);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_gpencil_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add GPencil";
+ ot->description = "Add a grease pencil object to the scene";
+ ot->idname = "OBJECT_OT_gpencil_add";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_gpencil_add_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, false);
+
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
+}
+
/********************* Add Light Operator ********************/
static const char *get_light_defname(int type)
@@ -1479,7 +1594,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->parent = NULL;
BKE_constraints_free(&ob_dst->constraints);
- ob_dst->curve_cache = NULL;
+ ob_dst->runtime.curve_cache = NULL;
ob_dst->transflag &= ~OB_DUPLI;
copy_m4_m4(ob_dst->obmat, dob->mat);
@@ -1638,7 +1753,7 @@ static const EnumPropertyItem convert_target_items[] = {
static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- if (ob->curve_cache == NULL) {
+ if (ob->runtime.curve_cache == NULL) {
/* Force creation. This is normally not needed but on operator
* redo we might end up with an object which isn't evaluated yet.
*/
@@ -1781,6 +1896,10 @@ static int convert_exec(bContext *C, wmOperator *op)
if (ob->type == OB_MESH) {
BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
}
+ if (ob->type == OB_GPENCIL) {
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
+ BKE_object_free_shaderfx(ob, 0);
+ }
}
}
else if (ob->type == OB_MESH && target == OB_CURVE) {
@@ -1966,7 +2085,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
convert_ensure_curve_cache(depsgraph, scene, baseob);
- BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
+ BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
if (obact->type == OB_MBALL) {
basact = basen;
@@ -2122,6 +2241,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
ID_NEW_REMAP_US(obn->mat[a])
else {
obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+ /* duplicate grease pencil settings */
+ if (ob->mat[a]->gp_style) {
+ obn->mat[a]->gp_style = MEM_dupallocN(ob->mat[a]->gp_style);
+ }
}
id_us_min(id);
@@ -2222,7 +2345,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
ID_NEW_REMAP_US2(obn->data)
else {
obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
- BKE_pose_rebuild(obn, obn->data);
+ BKE_pose_rebuild(bmain, obn, obn->data, true);
didit = 1;
}
id_us_min(id);
@@ -2258,6 +2381,16 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
id_us_min(id);
}
break;
+ case OB_GPENCIL:
+ if (dupflag != 0) {
+ ID_NEW_REMAP_US2(obn->data)
+ else {
+ obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data));
+ didit = 1;
+ }
+ id_us_min(id);
+ }
+ break;
}
/* check if obdata is copied */
@@ -2482,7 +2615,7 @@ static bool join_poll(bContext *C)
if (!ob || ID_IS_LINKED(ob)) return 0;
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
return ED_operator_screenactive(C);
else
return 0;
@@ -2500,6 +2633,13 @@ static int join_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
return OPERATOR_CANCELLED;
}
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
+ return OPERATOR_CANCELLED;
+ }
+ }
if (ob->type == OB_MESH)
return join_mesh_exec(C, op);
@@ -2507,6 +2647,8 @@ static int join_exec(bContext *C, wmOperator *op)
return join_curve_exec(C, op);
else if (ob->type == OB_ARMATURE)
return join_armature_exec(C, op);
+ else if (ob->type == OB_GPENCIL)
+ return ED_gpencil_join_objects_exec(C, op);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 5210182510f..e8fabdabf17 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -49,6 +49,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -357,17 +358,24 @@ static bool is_noncolor_pass(eScenePassType pass_type)
}
/* if all is good tag image and return true */
-static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
+static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *reports)
{
Image *image;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
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);
+ if (base == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
return false;
}
+ if (!(base->flag & BASE_ENABLED_RENDER)) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", 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;
@@ -497,7 +505,7 @@ static bool bake_pass_filter_check(eScenePassType pass_type, const int pass_filt
}
/* before even getting in the bake function we check for some basic errors */
-static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase *selected_objects,
+static bool bake_objects_check(Main *bmain, ViewLayer *view_layer, Object *ob, ListBase *selected_objects,
ReportList *reports, const bool is_selected_to_active)
{
CollectionPointerLink *link;
@@ -508,7 +516,7 @@ static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase *
if (is_selected_to_active) {
int tot_objects = 0;
- if (!bake_object_check(scene, ob, reports))
+ if (!bake_object_check(view_layer, ob, reports))
return false;
for (link = selected_objects->first; link; link = link->next) {
@@ -536,7 +544,7 @@ static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase *
}
for (link = selected_objects->first; link; link = link->next) {
- if (!bake_object_check(scene, link->ptr.data, reports))
+ if (!bake_object_check(view_layer, link->ptr.data, reports))
return false;
}
}
@@ -1204,7 +1212,7 @@ static int bake_exec(bContext *C, wmOperator *op)
goto finally;
}
- if (!bake_objects_check(bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
+ if (!bake_objects_check(bkr.main, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
goto finally;
}
@@ -1263,7 +1271,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
return;
}
- if (!bake_objects_check(bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
+ if (!bake_objects_check(bkr->main, bkr->view_layer, 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_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index f56fd560946..ad0b091ede9 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -450,8 +450,9 @@ static bool data_transfer_poll(bContext *C)
}
/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
-static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool data_transfer_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
{
+ PointerRNA *ptr = op->ptr;
PropertyRNA *prop_other;
const char *prop_id = RNA_property_identifier(prop);
@@ -512,19 +513,6 @@ static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
return true;
}
-/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
-static void data_transfer_ui(bContext *C, wmOperator *op)
-{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* Main auto-draw call */
- uiDefAutoButsRNA(layout, &ptr, data_transfer_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
-}
-
/* transfers weight from active to selected */
void OBJECT_OT_data_transfer(wmOperatorType *ot)
{
@@ -537,10 +525,10 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
/* API callbacks.*/
ot->poll = data_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
ot->invoke = WM_menu_invoke;
ot->exec = data_transfer_exec;
ot->check = data_transfer_check;
- ot->ui = data_transfer_ui;
/* Flags.*/
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -700,10 +688,10 @@ void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
ot->idname = "OBJECT_OT_datalayout_transfer";
ot->poll = datalayout_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
ot->invoke = datalayout_transfer_invoke;
ot->exec = datalayout_transfer_exec;
ot->check = data_transfer_check;
- ot->ui = data_transfer_ui;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index a6c3c86922d..a6dad906579 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -100,6 +100,7 @@
#include "ED_screen.h"
#include "ED_undo.h"
#include "ED_image.h"
+#include "ED_gpencil.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1377,6 +1378,9 @@ static void object_clear_mpath(Object *ob)
animviz_free_motionpath(ob->mpath);
ob->mpath = NULL;
ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+
+ /* tag object for copy on write - so removed paths don't still show */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
}
@@ -1539,7 +1543,6 @@ static const EnumPropertyItem *object_mode_set_itemsf(
const EnumPropertyItem *input = rna_enum_object_mode_items;
EnumPropertyItem *item = NULL;
Object *ob;
- bGPdata *gpd;
int totitem = 0;
if (!C) /* needed for docs */
@@ -1555,7 +1558,9 @@ static const EnumPropertyItem *object_mode_set_itemsf(
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
(input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
(ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
- OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
+ OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
+ (ELEM(input->value, OB_MODE_GPENCIL_EDIT, OB_MODE_GPENCIL_PAINT,
+ OB_MODE_GPENCIL_SCULPT, OB_MODE_GPENCIL_WEIGHT) && (ob->type == OB_GPENCIL)) ||
(input->value == OB_MODE_OBJECT))
{
RNA_enum_item_add(&item, &totitem, input);
@@ -1568,14 +1573,6 @@ static const EnumPropertyItem *object_mode_set_itemsf(
RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
}
- /* On top of all the rest, GPencil Stroke Edit Mode
- * is available if there's a valid gp datablock...
- */
- gpd = CTX_data_gpencil_data(C);
- if (gpd) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_object_mode_items, OB_MODE_GPENCIL);
- }
-
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1600,7 +1597,6 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
{
bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode");
Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
eObjectMode mode = RNA_enum_get(op->ptr, "mode");
eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
@@ -1620,22 +1616,9 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
}
}
- if (gpd) {
- /* GP Mode is not bound to a specific object. Therefore,
- * we don't want it to be actually saved on any objects,
- * as weirdness can happen if you select other objects,
- * or load old files.
- *
- * Instead, we use the following 2 rules to ensure that
- * the mode selector works as expected:
- * 1) If there's no object, we want to enter editmode.
- * (i.e. with no object, we're in object mode)
- * 2) Otherwise, exit stroke editmode, so that we can
- * enter another mode...
- */
- if (!ob || (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
- WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
- }
+ /* by default the operator assume is a mesh, but if gp object change mode */
+ if ((ob != NULL) && (ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
+ mode = OB_MODE_GPENCIL_EDIT;
}
if (!ob || !ED_object_mode_compat_test(ob, mode))
@@ -1666,6 +1649,14 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
}
}
+ /* if type is OB_GPENCIL, set cursor mode */
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (ob->data) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ ED_gpencil_setup_modes(C, gpd, ob->mode);
+ }
+ }
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
new file mode 100644
index 00000000000..175fb1706fb
--- /dev/null
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -0,0 +1,637 @@
+/*
+ * ***** 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) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2018
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/object/object_gpencil_modifier.c
+ * \ingroup edobj
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_report.h"
+#include "BKE_object.h"
+#include "BKE_gpencil.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "object_intern.h"
+
+/******************************** API ****************************/
+
+GpencilModifierData *ED_object_gpencil_modifier_add(
+ ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+{
+ GpencilModifierData *new_md = NULL;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
+
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
+
+ if (mti->flags & eGpencilModifierTypeFlag_Single) {
+ if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return NULL;
+ }
+ }
+
+ /* get new modifier data to add */
+ new_md = BKE_gpencil_modifier_new(type);
+
+ BLI_addtail(&ob->greasepencil_modifiers, new_md);
+
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
+
+ /* make sure modifier data has unique name */
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
+
+
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+
+ return new_md;
+}
+
+/* Return true if the object has a modifier of type 'type' other than
+ * the modifier pointed to be 'exclude', otherwise returns false. */
+static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(
+ const Object *ob, const GpencilModifierData *exclude,
+ GpencilModifierType type)
+{
+ GpencilModifierData *md;
+
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return true;
+ }
+
+ return false;
+}
+
+static bool gpencil_object_modifier_remove(
+ Main *bmain, Object *ob, GpencilModifierData *md,
+ bool *UNUSED(r_sort_depsgraph))
+{
+ /* It seems on rapid delete it is possible to
+ * get called twice on same modifier, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
+}
+
+bool ED_object_gpencil_modifier_remove(ReportList *reports, Main *bmain, Object *ob, GpencilModifierData *md)
+{
+ bool sort_depsgraph = false;
+ bool ok;
+
+ ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
+ return 0;
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+
+ return 1;
+}
+
+void ED_object_gpencil_modifier_clear(Main *bmain, Object *ob)
+{
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+ bool sort_depsgraph = false;
+
+ if (!md)
+ return;
+
+ while (md) {
+ GpencilModifierData *next_md;
+
+ next_md = md->next;
+
+ gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+
+ md = next_md;
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+}
+
+int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+{
+ if (md->prev) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
+ }
+
+ return 1;
+}
+
+int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+{
+ if (md->next) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
+ }
+
+ return 1;
+}
+
+static int gpencil_modifier_apply_obdata(
+ ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ if (ELEM(NULL, ob, ob->data)) {
+ return 0;
+ }
+ else if (mti->bakeModifier == NULL) {
+ BKE_report(reports, RPT_ERROR, "Not implemented");
+ return 0;
+ }
+ mti->bakeModifier(bmain, depsgraph, md, ob);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+
+ return 1;
+}
+
+int ED_object_gpencil_modifier_apply(
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph,
+ Object *ob, GpencilModifierData *md, int UNUSED(mode))
+{
+
+ if (ob->type == OB_GPENCIL) {
+ if (ob->mode != OB_MODE_OBJECT) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
+ return 0;
+ }
+
+ if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+ }
+ else if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+
+ if (md != ob->greasepencil_modifiers.first)
+ BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
+
+ if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
+ return 0;
+ }
+
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+
+ return 1;
+}
+
+int ED_object_gpencil_modifier_copy(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+{
+ GpencilModifierData *nmd;
+
+ nmd = BKE_gpencil_modifier_new(md->type);
+ BKE_gpencil_modifier_copyData(md, nmd);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
+
+ return 1;
+}
+
+/************************ add modifier operator *********************/
+
+static int gpencil_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static const EnumPropertyItem *gpencil_modifier_add_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *md_item, *group_item = NULL;
+ const GpencilModifierTypeInfo *mti;
+ int totitem = 0, a;
+
+ if (!ob)
+ return rna_enum_object_greasepencil_modifier_type_items;
+
+ for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) {
+ md_item = &rna_enum_object_greasepencil_modifier_type_items[a];
+ if (md_item->identifier[0]) {
+ mti = BKE_gpencil_modifierType_getInfo(md_item->value);
+
+ if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = md_item;
+ md_item = NULL;
+
+ continue;
+ }
+
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
+
+ RNA_enum_item_add(&item, &totitem, md_item);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Grease Pencil Modifier";
+ ot->description = "Add a procedural operation/effect to the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_add";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gpencil_modifier_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eGpencilModifierType_Thick, "Type", "");
+ RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
+ ot->prop = prop;
+}
+
+/************************ generic functions for operators using mod names and data context *********************/
+
+static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
+{
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'modifier'");
+ return 0;
+ }
+
+ if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers comming from static override");
+ return (((GpencilModifierData *)ptr.data)->flag & eGpencilModifierFlag_StaticOverride_Local) != 0;
+ }
+
+ return 1;
+}
+
+static bool gpencil_edit_modifier_poll(bContext *C)
+{
+ return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
+}
+
+static void gpencil_edit_modifier_properties(wmOperatorType *ot)
+{
+ RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
+}
+
+static int gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op)
+{
+ GpencilModifierData *md;
+
+ if (RNA_struct_property_is_set(op->ptr, "modifier")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier);
+ if (ptr.data) {
+ md = ptr.data;
+ RNA_string_set(op->ptr, "modifier", md->name);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op, Object *ob, int type)
+{
+ char modifier_name[MAX_NAME];
+ GpencilModifierData *md;
+ RNA_string_get(op->ptr, "modifier", modifier_name);
+
+ md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
+
+ if (md && type != 0 && md->type != type)
+ md = NULL;
+
+ return md;
+}
+
+/************************ remove modifier operator *********************/
+
+static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+
+ if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot)
+{
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a modifier from the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_remove";
+
+ ot->invoke = gpencil_modifier_remove_invoke;
+ ot->exec = gpencil_modifier_remove_exec;
+ ot->poll = gpencil_edit_modifier_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
+}
+
+/************************ move up modifier operator *********************/
+
+static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+
+ if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_gpencil_modifier_move_up(wmOperatorType *ot)
+{
+ ot->name = "Move Up Modifier";
+ ot->description = "Move modifier up in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
+
+ ot->invoke = gpencil_modifier_move_up_invoke;
+ ot->exec = gpencil_modifier_move_up_exec;
+ ot->poll = gpencil_edit_modifier_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
+}
+
+/************************ move down modifier operator *********************/
+
+static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+
+ if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot)
+{
+ ot->name = "Move Down Modifier";
+ ot->description = "Move modifier down in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
+
+ ot->invoke = gpencil_modifier_move_down_invoke;
+ ot->exec = gpencil_modifier_move_down_exec;
+ ot->poll = gpencil_edit_modifier_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
+}
+
+/************************ apply modifier operator *********************/
+
+static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ int apply_as = RNA_enum_get(op->ptr, "apply_as");
+
+ if (!md || !ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+static const EnumPropertyItem gpencil_modifier_apply_as_items[] = {
+ {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
+ {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
+{
+ ot->name = "Apply Modifier";
+ ot->description = "Apply modifier and remove from the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_apply";
+
+ ot->invoke = gpencil_modifier_apply_invoke;
+ ot->exec = gpencil_modifier_apply_exec;
+ ot->poll = gpencil_edit_modifier_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ RNA_def_enum(ot->srna, "apply_as", gpencil_modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
+ gpencil_edit_modifier_properties(ot);
+}
+
+/************************ copy modifier operator *********************/
+
+static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+
+ if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_copy_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
+{
+ ot->name = "Copy Modifier";
+ ot->description = "Duplicate modifier at the same position in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_copy";
+
+ ot->invoke = gpencil_modifier_copy_invoke;
+ ot->exec = gpencil_modifier_copy_exec;
+ ot->poll = gpencil_edit_modifier_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
+}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 53cabe3759e..72c5fde2955 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -411,6 +411,9 @@ static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
id_fake_user_set(&collection->id);
BKE_collection_object_add(bmain, collection, ob);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -460,6 +463,9 @@ static int collection_link_exec(bContext *C, wmOperator *op)
BKE_collection_object_add(bmain, collection, ob);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -500,6 +506,9 @@ static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
BKE_collection_object_remove(bmain, collection, ob, false);
+ DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -531,6 +540,8 @@ static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
BKE_libblock_delete(bmain, collection);
+ DEG_relations_tag_update(bmain);
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 0e49f8a7790..2cc8671d84b 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -115,6 +115,7 @@ void OBJECT_OT_armature_add(struct wmOperatorType *ot);
void OBJECT_OT_empty_add(struct wmOperatorType *ot);
void OBJECT_OT_lightprobe_add(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_image(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_add(struct wmOperatorType *ot);
void OBJECT_OT_light_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
@@ -176,6 +177,20 @@ void OBJECT_OT_laplaciandeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_surfacedeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_hair_generate_follicles(struct wmOperatorType *ot);
+/* grease pencil modifiers */
+void OBJECT_OT_gpencil_modifier_add(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_modifier_remove(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_modifier_move_up(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_modifier_move_down(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_modifier_apply(struct wmOperatorType *ot);
+void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot);
+
+/* shader fx */
+void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot);
+void OBJECT_OT_shaderfx_remove(struct wmOperatorType *ot);
+void OBJECT_OT_shaderfx_move_up(struct wmOperatorType *ot);
+void OBJECT_OT_shaderfx_move_down(struct wmOperatorType *ot);
+
/* object_constraint.c */
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
void OBJECT_OT_constraint_add_with_targets(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index e9bd6fbce8f..b9bfb44f680 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -27,6 +27,7 @@
* actual mode switching logic is per-object type.
*/
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_workspace_types.h"
@@ -71,8 +72,14 @@ static const char *object_mode_op_string(eObjectMode mode)
return "PARTICLE_OT_particle_edit_toggle";
if (mode == OB_MODE_POSE)
return "OBJECT_OT_posemode_toggle";
- if (mode == OB_MODE_GPENCIL)
+ if (mode == OB_MODE_GPENCIL_EDIT)
return "GPENCIL_OT_editmode_toggle";
+ if (mode == OB_MODE_GPENCIL_PAINT)
+ return "GPENCIL_OT_paintmode_toggle";
+ if (mode == OB_MODE_GPENCIL_SCULPT)
+ return "GPENCIL_OT_sculptmode_toggle";
+ if (mode == OB_MODE_GPENCIL_WEIGHT)
+ return "GPENCIL_OT_weightmode_toggle";
return NULL;
}
@@ -85,8 +92,6 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
if (ob) {
if (mode == OB_MODE_OBJECT)
return true;
- else if (mode == OB_MODE_GPENCIL)
- return true; /* XXX: assume this is the case for now... */
switch (ob->type) {
case OB_MESH:
@@ -111,6 +116,13 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
return true;
break;
+ case OB_GPENCIL:
+ if (mode & (OB_MODE_EDIT | OB_MODE_GPENCIL_EDIT | OB_MODE_GPENCIL_PAINT |
+ OB_MODE_GPENCIL_SCULPT | OB_MODE_GPENCIL_WEIGHT))
+ {
+ return true;
+ }
+ break;
}
}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index f2122f7961a..8384755c679 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1,31 +1,31 @@
/*
- * ***** 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) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation, 2009
- *
- * ***** END GPL LICENSE BLOCK *****
- */
+* ***** 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) 2001-2002 by NaN Holding BV.
+* All rights reserved.
+*
+* Contributor(s): Blender Foundation, 2009
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
/** \file blender/editors/object/object_modifier.c
- * \ingroup edobj
- */
+* \ingroup edobj
+*/
#include <math.h>
@@ -120,8 +120,8 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
if (type == eModifierType_ParticleSystem) {
/* don't need to worry about the new modifier's name, since that is set to the number
- * of particle systems which shouldn't have too many duplicates
- */
+ * of particle systems which shouldn't have too many duplicates
+ */
new_md = object_add_particle_system(bmain, scene, ob, name);
}
else {
@@ -185,9 +185,9 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
}
/* Return true if the object has a modifier of type 'type' other than
- * the modifier pointed to be 'exclude', otherwise returns false. */
+* the modifier pointed to be 'exclude', otherwise returns false. */
static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
- ModifierType type)
+ ModifierType type)
{
ModifierData *md;
@@ -200,16 +200,17 @@ static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
}
/* If the object data of 'orig_ob' has other users, run 'callback' on
- * each of them.
- *
- * If include_orig is true, the callback will run on 'orig_ob' too.
- *
- * If the callback ever returns true, iteration will stop and the
- * function value will be true. Otherwise the function returns false.
- */
-bool ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig,
- bool (*callback)(Object *ob, void *callback_data),
- void *callback_data)
+* each of them.
+*
+* If include_orig is true, the callback will run on 'orig_ob' too.
+*
+* If the callback ever returns true, iteration will stop and the
+* function value will be true. Otherwise the function returns false.
+*/
+bool ED_object_iter_other(
+ Main *bmain, Object *orig_ob, const bool include_orig,
+ bool (*callback)(Object *ob, void *callback_data),
+ void *callback_data)
{
ID *ob_data_id = orig_ob->data;
int users = ob_data_id->us;
@@ -250,8 +251,8 @@ static bool object_has_modifier_cb(Object *ob, void *data)
}
/* Use with ED_object_iter_other(). Sets the total number of levels
- * for any multires modifiers on the object to the int pointed to by
- * callback_data. */
+* for any multires modifiers on the object to the int pointed to by
+* callback_data. */
bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
{
ModifierData *md;
@@ -268,20 +269,20 @@ bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
/* Return true if no modifier of type 'type' other than 'exclude' */
static bool object_modifier_safe_to_delete(Main *bmain, Object *ob,
- ModifierData *exclude,
- ModifierType type)
+ ModifierData *exclude,
+ ModifierType type)
{
return (!object_has_modifier(ob, exclude, type) &&
- !ED_object_iter_other(bmain, ob, false,
- object_has_modifier_cb, &type));
+ !ED_object_iter_other(bmain, ob, false,
+ object_has_modifier_cb, &type));
}
static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
- bool *r_sort_depsgraph)
+ bool *r_sort_depsgraph)
{
/* It seems on rapid delete it is possible to
- * get called twice on same modifier, so make
- * sure it is in list. */
+ * get called twice on same modifier, so make
+ * sure it is in list. */
if (BLI_findindex(&ob->modifiers, md) == -1) {
return 0;
}
@@ -525,7 +526,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
}
static int modifier_apply_shape(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -535,15 +536,15 @@ static int modifier_apply_shape(
}
/*
- * It should be ridiculously easy to extract the original verts that we want
- * and form the shape data. We can probably use the CD KEYINDEX layer (or
- * whatever I ended up calling it, too tired to check now), though this would
- * by necessity have to make some potentially ugly assumptions about the order
- * of the mesh data :-/ you can probably assume in 99% of cases that the first
- * element of a given index is the original, and any subsequent duplicates are
- * copies/interpolates, but that's an assumption that would need to be tested
- * and then predominantly stated in comments in a half dozen headers.
- */
+ * It should be ridiculously easy to extract the original verts that we want
+ * and form the shape data. We can probably use the CD KEYINDEX layer (or
+ * whatever I ended up calling it, too tired to check now), though this would
+ * by necessity have to make some potentially ugly assumptions about the order
+ * of the mesh data :-/ you can probably assume in 99% of cases that the first
+ * element of a given index is the original, and any subsequent duplicates are
+ * copies/interpolates, but that's an assumption that would need to be tested
+ * and then predominantly stated in comments in a half dozen headers.
+ */
if (ob->type == OB_MESH) {
Mesh *mesh_applied;
@@ -566,7 +567,7 @@ static int modifier_apply_shape(
key = me->key = BKE_key_add(bmain, (ID *)me);
key->type = KEY_RELATIVE;
/* if that was the first key block added, then it was the basis.
- * Initialize it with the mesh, and add another for the modifier */
+ * Initialize it with the mesh, and add another for the modifier */
kb = BKE_keyblock_add(key, NULL);
BKE_keyblock_convert_from_mesh(me, key, kb);
}
@@ -670,8 +671,8 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
int ED_object_modifier_apply(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph,
- Scene *scene, Object *ob, ModifierData *md, int mode)
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph,
+ Scene *scene, Object *ob, ModifierData *md, int mode)
{
int prev_mode;
@@ -695,7 +696,7 @@ int ED_object_modifier_apply(
BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
/* Get evaluated modifier, so object links pointer to evaluated data,
- * but still use original object it is applied to the original mesh. */
+ * but still use original object it is applied to the original mesh. */
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md;
@@ -755,7 +756,7 @@ static int modifier_add_exec(bContext *C, wmOperator *op)
}
static const EnumPropertyItem *modifier_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
Object *ob = ED_object_active_context(C);
EnumPropertyItem *item = NULL;
@@ -1168,8 +1169,8 @@ static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
multiresModifier_del_levels(mmd, scene, ob, 1);
ED_object_iter_other(CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1213,8 +1214,8 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
ED_object_iter_other(CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1390,8 +1391,8 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
edit_modifier_properties(ot);
}
@@ -1483,13 +1484,13 @@ static void modifier_skin_customdata_delete(Object *ob)
static bool skin_poll(bContext *C)
{
return (!CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static bool skin_edit_poll(bContext *C)
{
return (CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
@@ -1582,8 +1583,8 @@ static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
+ bm_vert->head.data,
+ CD_MVERT_SKIN);
switch (action) {
@@ -1639,8 +1640,8 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
+ bm_vert->head.data,
+ CD_MVERT_SKIN);
float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
vs->radius[0] = vs->radius[1] = avg;
@@ -1667,12 +1668,12 @@ void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
}
static void skin_armature_bone_create(Object *skin_ob,
- MVert *mvert, MEdge *medge,
- bArmature *arm,
- BLI_bitmap *edges_visited,
- const MeshElemMap *emap,
- EditBone *parent_bone,
- int parent_v)
+ MVert *mvert, MEdge *medge,
+ bArmature *arm,
+ BLI_bitmap *edges_visited,
+ const MeshElemMap *emap,
+ EditBone *parent_bone,
+ int parent_v)
{
int i;
@@ -1707,12 +1708,12 @@ static void skin_armature_bone_create(Object *skin_ob,
}
skin_armature_bone_create(skin_ob,
- mvert, medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
+ mvert, medge,
+ arm,
+ edges_visited,
+ emap,
+ bone,
+ v);
}
}
@@ -1734,10 +1735,10 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
/* add vertex weights to original mesh */
CustomData_add_layer(&me->vdata,
- CD_MDEFORMVERT,
- CD_CALLOC,
- NULL,
- me->totvert);
+ CD_MDEFORMVERT,
+ CD_CALLOC,
+ NULL,
+ me->totvert);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
@@ -1750,19 +1751,19 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
- me->medge, me->totvert, me->totedge);
+ me->medge, me->totvert, me->totedge);
edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
/* note: we use EditBones here, easier to set them up and use
- * edit-armature functions to convert back to regular bones */
+ * edit-armature functions to convert back to regular bones */
for (v = 0; v < me->totvert; v++) {
if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
EditBone *bone = NULL;
/* Unless the skin root has just one adjacent edge, create
- * a fake root bone (have it going off in the Y direction
- * (arbitrary) */
+ * a fake root bone (have it going off in the Y direction
+ * (arbitrary) */
if (emap[v].count > 1) {
bone = ED_armature_ebone_add(arm, "Bone");
@@ -1775,12 +1776,12 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
if (emap[v].count >= 1) {
skin_armature_bone_create(skin_ob,
- mvert, me->medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
+ mvert, me->medge,
+ arm,
+ edges_visited,
+ emap,
+ bone,
+ v);
}
}
}
@@ -2095,7 +2096,7 @@ static int oceanbake_breakjob(void *UNUSED(customdata))
//return *(ob->stop);
/* this is not nice yet, need to make the jobs list template better
- * for identifying/acting upon various different jobs */
+ * for identifying/acting upon various different jobs */
/* but for now we'll reuse the render break... */
return (G.is_break);
}
@@ -2169,8 +2170,8 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
}
och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(bmain, ob),
- omd->bakestart, omd->bakeend, omd->wave_scale,
- omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
+ omd->bakestart, omd->bakeend, omd->wave_scale,
+ omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
@@ -2179,22 +2180,22 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
/* precalculate time variable before baking */
for (f = omd->bakestart; f <= omd->bakeend; f++) {
/* from physics_fluid.c:
- *
- * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
- * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
- * --> BKE_animsys_evaluate_all_animation(bmain, eval_time);
- * This doesn't work with drivers:
- * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
- */
+ *
+ * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
+ * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
+ * --> BKE_animsys_evaluate_all_animation(bmain, eval_time);
+ * This doesn't work with drivers:
+ * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
+ */
/* Modifying the global scene isn't nice, but we can do it in
- * this part of the process before a threaded job is created */
+ * this part of the process before a threaded job is created */
//scene->r.cfra = f;
//ED_update_for_newframe(bmain, scene);
/* ok, this doesn't work with drivers, but is way faster.
- * let's use this for now and hope nobody wants to drive the time value... */
+ * let's use this for now and hope nobody wants to drive the time value... */
BKE_animsys_evaluate_animdata(CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
och->time[i] = omd->time;
@@ -2223,7 +2224,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
/* setup job */
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
- WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
+ WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
oj->owner = ob;
oj->ocean = ocean;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 192df257bba..16ea0791adf 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -40,6 +40,7 @@
#include "BKE_context.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -114,6 +115,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_empty_add);
WM_operatortype_append(OBJECT_OT_lightprobe_add);
WM_operatortype_append(OBJECT_OT_drop_named_image);
+ WM_operatortype_append(OBJECT_OT_gpencil_add);
WM_operatortype_append(OBJECT_OT_light_add);
WM_operatortype_append(OBJECT_OT_camera_add);
WM_operatortype_append(OBJECT_OT_speaker_add);
@@ -146,6 +148,20 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
WM_operatortype_append(OBJECT_OT_skin_armature_create);
+ /* grease pencil modifiers */
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_add);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_remove);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_up);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_down);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
+
+ /* shader fx */
+ WM_operatortype_append(OBJECT_OT_shaderfx_add);
+ WM_operatortype_append(OBJECT_OT_shaderfx_remove);
+ WM_operatortype_append(OBJECT_OT_shaderfx_move_up);
+ WM_operatortype_append(OBJECT_OT_shaderfx_move_down);
+
WM_operatortype_append(OBJECT_OT_correctivesmooth_bind);
WM_operatortype_append(OBJECT_OT_meshdeform_bind);
WM_operatortype_append(OBJECT_OT_explode_refresh);
@@ -491,3 +507,26 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *UNUSED(keyconf), struct
RNA_string_set(kmi->ptr, "value_2", "CONNECTED");
}
}
+
+/**
+ * Map 1..3 to Vert/Edge/Face.
+ */
+void ED_keymap_editmesh_elem_mode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap)
+{
+ for (int i = 0; i < 4; i++) {
+ const bool is_extend = (i & 1);
+ const bool is_expand = (i & 2);
+ const int key_modifier = (is_extend ? KM_SHIFT : 0) | (is_expand ? KM_CTRL : 0);
+ for (int j = 0; j < 3; j++) {
+ wmKeyMapItem *kmi = WM_keymap_add_item(
+ keymap, "MESH_OT_select_mode", ONEKEY + j, KM_PRESS, key_modifier, 0);
+ RNA_enum_set(kmi->ptr, "type", SCE_SELECT_VERTEX << j);
+ if (is_extend) {
+ RNA_boolean_set(kmi->ptr, "use_extend", true);
+ }
+ if (is_expand) {
+ RNA_boolean_set(kmi->ptr, "use_expand", true);
+ }
+ }
+ }
+}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 324b6eca34a..78e44e52299 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -70,6 +70,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lamp.h"
@@ -360,7 +361,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
/* set layers OK */
- BKE_object_make_proxy(newob, ob, gob);
+ BKE_object_make_proxy(bmain, newob, ob, gob);
/* Set back pointer immediately so dependency graph knows that this is
* is a proxy and will act accordingly. Otherwise correctness of graph
@@ -716,7 +717,7 @@ bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene,
if (md) {
((CurveModifierData *)md)->object = par;
}
- if (par->curve_cache && par->curve_cache->path == NULL) {
+ if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
DEG_id_tag_update(&par->id, OB_RECALC_DATA);
}
}
@@ -947,13 +948,13 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
return OPERATOR_INTERFACE;
}
-static bool parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool parent_set_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- const int type = RNA_enum_get(ptr, "type");
/* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
if (STREQ(prop_id, "xmirror")) {
+ const int type = RNA_enum_get(op->ptr, "type");
if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
return true;
else
@@ -963,18 +964,6 @@ static bool parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
return true;
}
-static void parent_set_ui(bContext *C, wmOperator *op)
-{
- uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- /* Main auto-draw call. */
- uiDefAutoButsRNA(layout, &ptr, parent_set_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
-}
-
void OBJECT_OT_parent_set(wmOperatorType *ot)
{
/* identifiers */
@@ -986,7 +975,7 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
ot->invoke = parent_set_invoke;
ot->exec = parent_set_exec;
ot->poll = ED_operator_object_active;
- ot->ui = parent_set_ui;
+ ot->poll_property = parent_set_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1621,21 +1610,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob)
+static Object *single_object_users_object(Main *bmain, Object *ob)
{
/* base gets copy of object */
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- /* remap gpencil parenting */
-
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
- }
- }
id_us_plus(&obn->id);
id_us_min(&ob->id);
@@ -1660,7 +1639,7 @@ static void single_object_users_collection(Main *bmain, Scene *scene, Collection
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
- cob->ob = single_object_users_object(bmain, scene, cob->ob);
+ cob->ob = single_object_users_object(bmain, cob->ob);
}
}
}
@@ -1714,6 +1693,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* collection pointers in scene */
BKE_scene_groups_relink(scene);
+ /* active camera */
ID_NEW_REMAP(scene->camera);
if (v3d) ID_NEW_REMAP(v3d->camera);
@@ -1809,7 +1789,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
case OB_ARMATURE:
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
- BKE_pose_rebuild(ob, ob->data);
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
break;
case OB_SPEAKER:
ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
@@ -1817,6 +1797,9 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
case OB_LIGHTPROBE:
ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
break;
+ case OB_GPENCIL:
+ ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
+ break;
default:
printf("ERROR %s: can't copy %s\n", __func__, id->name);
BLI_assert(!"This should never happen.");
@@ -1892,6 +1875,7 @@ static void single_mat_users_expand(Main *bmain)
Mesh *me;
Curve *cu;
MetaBall *mb;
+ bGPdata *gpd;
for (ob = bmain->object.first; ob; ob = ob->id.next)
if (ob->id.tag & LIB_TAG_NEW)
@@ -1908,6 +1892,10 @@ static void single_mat_users_expand(Main *bmain)
for (mb = bmain->mball.first; mb; mb = mb->id.next)
if (mb->id.tag & LIB_TAG_NEW)
new_id_matar(bmain, mb->mat, mb->totcol);
+
+ for (gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next)
+ if (gpd->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, gpd->mat, gpd->totcol);
}
/* used for copying scenes */
@@ -1952,10 +1940,6 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
}
}
- if (scene->gpd) {
- IDP_RelinkProperty(scene->gpd->id.properties);
- }
-
if (scene->world) {
IDP_RelinkProperty(scene->world->id.properties);
}
@@ -2329,6 +2313,7 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
if (new_ob != NULL && new_ob->id.override_static != NULL) {
if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
+ base = BKE_view_layer_base_find(view_layer, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, DEG_TAG_TRANSFORM | DEG_TAG_BASE_FLAGS_UPDATE);
}
/* parent to 'collection' empty */
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index d5f7a93cc6e..c23a1d64ee8 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -41,6 +41,7 @@
#include "DNA_armature_types.h"
#include "DNA_lamp_types.h"
#include "DNA_workspace_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -88,8 +89,8 @@
* this takes into account the 'restrict selection in 3d view' flag.
* deselect works always, the restriction just prevents selection */
-/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
- * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
+ /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
+ * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
{
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
new file mode 100644
index 00000000000..681851850a5
--- /dev/null
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -0,0 +1,469 @@
+/*
+ * ***** 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) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2018
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/object/object_shader_fx.c
+ * \ingroup edobj
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_shader_fx_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_shader_fx.h"
+#include "BKE_report.h"
+#include "BKE_object.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "object_intern.h"
+
+/******************************** API ****************************/
+
+ShaderFxData *ED_object_shaderfx_add(ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+{
+ ShaderFxData *new_fx = NULL;
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
+
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
+
+ if (fxi->flags & eShaderFxTypeFlag_Single) {
+ if (BKE_shaderfx_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
+ return NULL;
+ }
+ }
+
+ /* get new effect data to add */
+ new_fx = BKE_shaderfx_new(type);
+
+ BLI_addtail(&ob->shader_fx, new_fx);
+
+ if (name) {
+ BLI_strncpy_utf8(new_fx->name, name, sizeof(new_fx->name));
+ }
+
+ /* make sure effect data has unique name */
+ BKE_shaderfx_unique_name(&ob->shader_fx, new_fx);
+
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+
+ return new_fx;
+}
+
+/* Return true if the object has a effect of type 'type' other than
+ * the shaderfx pointed to be 'exclude', otherwise returns false. */
+static bool UNUSED_FUNCTION(object_has_shaderfx)(
+ const Object *ob, const ShaderFxData *exclude,
+ ShaderFxType type)
+{
+ ShaderFxData *fx;
+
+ for (fx = ob->shader_fx.first; fx; fx = fx->next) {
+ if ((fx != exclude) && (fx->type == type))
+ return true;
+ }
+
+ return false;
+}
+
+static bool object_shaderfx_remove(
+ Main *bmain, Object *ob, ShaderFxData *fx,
+ bool *UNUSED(r_sort_depsgraph))
+{
+ /* It seems on rapid delete it is possible to
+ * get called twice on same effect, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->shader_fx, fx) == -1) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ BLI_remlink(&ob->shader_fx, fx);
+ BKE_shaderfx_free(fx);
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
+}
+
+bool ED_object_shaderfx_remove(ReportList *reports, Main *bmain, Object *ob, ShaderFxData *fx)
+{
+ bool sort_depsgraph = false;
+ bool ok;
+
+ ok = object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Effect '%s' not in object '%s'", fx->name, ob->id.name);
+ return 0;
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+
+ return 1;
+}
+
+void ED_object_shaderfx_clear(Main *bmain, Object *ob)
+{
+ ShaderFxData *fx = ob->shader_fx.first;
+ bool sort_depsgraph = false;
+
+ if (!fx)
+ return;
+
+ while (fx) {
+ ShaderFxData *next_fx;
+
+ next_fx = fx->next;
+
+ object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+
+ fx = next_fx;
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+}
+
+int ED_object_shaderfx_move_up(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
+{
+ if (fx->prev) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkbefore(&ob->shader_fx, fx->prev, fx);
+ }
+
+ return 1;
+}
+
+int ED_object_shaderfx_move_down(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
+{
+ if (fx->next) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkafter(&ob->shader_fx, fx->next, fx);
+ }
+
+ return 1;
+}
+
+/************************ add effect operator *********************/
+
+static int shaderfx_add_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!ED_object_shaderfx_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static const EnumPropertyItem *shaderfx_add_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *fx_item, *group_item = NULL;
+ const ShaderFxTypeInfo *mti;
+ int totitem = 0, a;
+
+ if (!ob)
+ return rna_enum_object_shaderfx_type_items;
+
+ for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) {
+ fx_item = &rna_enum_object_shaderfx_type_items[a];
+ if (fx_item->identifier[0]) {
+ mti = BKE_shaderfxType_getInfo(fx_item->value);
+
+ if (mti->flags & eShaderFxTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = fx_item;
+ fx_item = NULL;
+
+ continue;
+ }
+
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
+
+ RNA_enum_item_add(&item, &totitem, fx_item);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+void OBJECT_OT_shaderfx_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Effect";
+ ot->description = "Add a visual effect to the active object";
+ ot->idname = "OBJECT_OT_shaderfx_add";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = shaderfx_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", "");
+ RNA_def_enum_funcs(prop, shaderfx_add_itemf);
+ ot->prop = prop;
+}
+
+/************************ generic functions for operators using names and data context *********************/
+
+static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
+{
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
+ return 0;
+ }
+
+ if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs comming from static override");
+ return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_StaticOverride_Local) != 0;
+ }
+
+ return 1;
+}
+
+static bool edit_shaderfx_poll(bContext *C)
+{
+ return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
+}
+
+static void edit_shaderfx_properties(wmOperatorType *ot)
+{
+ RNA_def_string(ot->srna, "shaderfx", NULL, MAX_NAME, "Shader", "Name of the shaderfx to edit");
+}
+
+static int edit_shaderfx_invoke_properties(bContext *C, wmOperator *op)
+{
+ ShaderFxData *fx;
+
+ if (RNA_struct_property_is_set(op->ptr, "shaderfx")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", &RNA_ShaderFx);
+ if (ptr.data) {
+ fx = ptr.data;
+ RNA_string_set(op->ptr, "shaderfx", fx->name);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int type)
+{
+ char shaderfx_name[MAX_NAME];
+ ShaderFxData *fx;
+ RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
+
+ fx = BKE_shaderfx_findByName(ob, shaderfx_name);
+
+ if (fx && type != 0 && fx->type != type)
+ fx = NULL;
+
+ return fx;
+}
+
+/************************ remove shaderfx operator *********************/
+
+static int shaderfx_remove_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+
+ if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int shaderfx_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_shaderfx_remove(wmOperatorType *ot)
+{
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a shaderfx from the active grease pencil object";
+ ot->idname = "OBJECT_OT_shaderfx_remove";
+
+ ot->invoke = shaderfx_remove_invoke;
+ ot->exec = shaderfx_remove_exec;
+ ot->poll = edit_shaderfx_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
+}
+
+/************************ move up shaderfx operator *********************/
+
+static int shaderfx_move_up_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+
+ if (!fx || !ED_object_shaderfx_move_up(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int shaderfx_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot)
+{
+ ot->name = "Move Up Modifier";
+ ot->description = "Move shaderfx up in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_up";
+
+ ot->invoke = shaderfx_move_up_invoke;
+ ot->exec = shaderfx_move_up_exec;
+ ot->poll = edit_shaderfx_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
+}
+
+/************************ move down shaderfx operator *********************/
+
+static int shaderfx_move_down_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+
+ if (!fx || !ED_object_shaderfx_move_down(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int shaderfx_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot)
+{
+ ot->name = "Move Down Modifier";
+ ot->description = "Move shaderfx down in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_down";
+
+ ot->invoke = shaderfx_move_down_invoke;
+ ot->exec = shaderfx_move_down_exec;
+ ot->poll = edit_shaderfx_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
+}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 5e66dc00fd2..30fb2896670 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -378,8 +378,10 @@ static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
if (!key || !kb)
return OPERATOR_CANCELLED;
- for (kb = key->block.first; kb; kb = kb->next)
- kb->pos = (cfra += 0.1f);
+ for (kb = key->block.first; kb; kb = kb->next) {
+ kb->pos = cfra;
+ cfra += 0.1f;
+ }
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index d2a0879464b..96b540251b4 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -38,6 +38,7 @@
#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
@@ -59,6 +60,7 @@
#include "BKE_armature.h"
#include "BKE_lattice.h"
#include "BKE_tracking.h"
+#include "BKE_gpencil.h"
#include "DEG_depsgraph.h"
@@ -73,6 +75,7 @@
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "ED_gpencil.h"
#include "MEM_guardedalloc.h"
@@ -434,7 +437,7 @@ static int apply_objects_internal(
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
ID *obdata = ob->data;
if (ID_REAL_USERS(obdata) > 1) {
BKE_reportf(reports, RPT_ERROR,
@@ -480,6 +483,37 @@ static int apply_objects_internal(
}
}
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ if (gpd) {
+ if (gpd->layers.first) {
+ /* Unsupported configuration */
+ bool has_unparented_layers = false;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Parented layers aren't supported as we can't easily re-evaluate the scene to sample parent movement */
+ if (gpl->parent == NULL) {
+ has_unparented_layers = true;
+ break;
+ }
+ }
+
+ if (has_unparented_layers == false) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Can't apply to a GP datablock where all layers are parented: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
+ changed = false;
+ }
+ }
+ else {
+ /* No layers/data */
+ BKE_reportf(reports, RPT_ERROR,
+ "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
+ }
+ }
+ }
+
if (ob->type == OB_LAMP) {
Lamp *la = ob->data;
if (la->type == LA_AREA) {
@@ -587,6 +621,10 @@ static int apply_objects_internal(
cu->fsize *= scale;
}
}
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ BKE_gpencil_transform(gpd, mat);
+ }
else if (ob->type == OB_CAMERA) {
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
@@ -1056,6 +1094,69 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
lt->id.tag |= LIB_TAG_DOIT;
do_inverse_offset = true;
}
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ float gpcenter[3];
+ if (gpd) {
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ zero_v3(gpcenter);
+ BKE_gpencil_centroid_3D(gpd, gpcenter);
+ add_v3_v3(gpcenter, ob->obmat[3]);
+ }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(gpcenter, cursor);
+ }
+ if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
+ bGPDspoint *pt;
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+ int i;
+
+ sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
+ copy_m3_m4(bmat, obact->obmat);
+ invert_m3_m3(imat, bmat);
+ mul_m3_v3(imat, offset_global);
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ /* recalculate all strokes (all layers are considered without evaluating lock attributtes) */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
+ }
+ }
+ }
+ }
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+ tot_change++;
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ copy_v3_v3(ob->loc, gpcenter);
+ }
+ ob->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Grease Pencil Object does not support this set origin option");
+ }
+ }
+ }
/* offset other selected objects */
if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 10d9c90aeb3..1b82e60b986 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -2892,7 +2892,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
brush = &pset->brush[pset->brushtype];
if (brush) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(255, 255, 255, 128);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index b5c1ffc64dd..ed7950f3993 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -326,10 +326,10 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT);
wmOrtho2(0, sizex, 0, sizey);
- gpuTranslate2f(sizex / 2, sizey / 2);
+ GPU_matrix_translate_2f(sizex / 2, sizey / 2);
G.f |= G_RENDER_OGL;
- ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
+ ED_gpencil_draw_ex(rv3d, scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
G.f &= ~G_RENDER_OGL;
gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
@@ -355,7 +355,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
if (view_context) {
ibuf_view = ED_view3d_draw_offscreen_imbuf(
- depsgraph, scene, v3d->drawtype,
+ depsgraph, scene, v3d->shading.type,
v3d, ar, sizex, sizey,
IB_rectfloat, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
oglrender->ofs, err_out);
@@ -417,7 +417,7 @@ static void screen_opengl_render_write(OGLRender *oglrender)
else printf("OpenGL Render failed to write '%s'\n", name);
}
-static void addAlphaOverFloat(float dest[4], const float source[4])
+static void UNUSED_FUNCTION(addAlphaOverFloat)(float dest[4], const float source[4])
{
/* d = s + (1-alpha_s)d*/
float mul;
@@ -431,91 +431,6 @@ static void addAlphaOverFloat(float dest[4], const float source[4])
}
-/* add renderlayer and renderpass for each grease pencil layer for using in composition */
-static void add_gpencil_renderpass(const bContext *C, OGLRender *oglrender, RenderResult *rr, RenderView *rv)
-{
- bGPdata *gpd = oglrender->scene->gpd;
- Scene *scene = oglrender->scene;
-
- /* sanity checks */
- if (gpd == NULL) {
- return;
- }
- if (scene == NULL) {
- return;
- }
- if (BLI_listbase_is_empty(&gpd->layers)) {
- return;
- }
- if (oglrender->v3d != NULL && (oglrender->v3d->flag2 & V3D_SHOW_GPENCIL) == 0) {
- return;
- }
-
- /* save old alpha mode */
- short oldalphamode = scene->r.alphamode;
- /* set alpha transparent for gp */
- scene->r.alphamode = R_ALPHAPREMUL;
-
- /* saves layer status */
- short *oldsts = MEM_mallocN(BLI_listbase_count(&gpd->layers) * sizeof(short), "temp_gplayers_flag");
- int i = 0;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- oldsts[i] = gpl->flag;
- ++i;
- }
- /* loop all layers to create separate render */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* dont draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
- continue;
- /* hide all layer except current */
- for (bGPDlayer *gph = gpd->layers.first; gph; gph = gph->next) {
- if (gpl != gph) {
- gph->flag |= GP_LAYER_HIDE;
- }
- }
-
- /* render this gp layer */
- screen_opengl_render_doit(C, oglrender, rr);
-
- /* add RendePass composite */
- RenderPass *rp = RE_create_gp_pass(rr, gpl->info, rv->name);
-
- /* copy image data from rectf */
- // XXX: Needs conversion.
- unsigned char *src = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
- if (src != NULL) {
- float *dest = rp->rect;
-
- int x, y, rectx, recty;
- rectx = rr->rectx;
- recty = rr->recty;
- for (y = 0; y < recty; y++) {
- for (x = 0; x < rectx; x++) {
- unsigned char *pixSrc = src + 4 * (rectx * y + x);
- if (pixSrc[3] > 0) {
- float *pixDest = dest + 4 * (rectx * y + x);
- float float_src[4];
- srgb_to_linearrgb_uchar4(float_src, pixSrc);
- addAlphaOverFloat(pixDest, float_src);
- }
- }
- }
- }
- /* back layer status */
- i = 0;
- for (bGPDlayer *gph = gpd->layers.first; gph; gph = gph->next) {
- gph->flag = oldsts[i];
- ++i;
- }
- }
- /* free memory */
- MEM_freeN(oldsts);
-
- /* back default alpha mode */
- scene->r.alphamode = oldalphamode;
-}
-
static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
{
RenderResult *rr;
@@ -550,11 +465,6 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
BLI_assert(view_id < oglrender->views_len);
RE_SetActiveRenderView(oglrender->re, rv->name);
oglrender->view_id = view_id;
- /* add grease pencil passes. For sequencer, the render does not include renderpasses
- * TODO: The sequencer render of grease pencil should be rethought */
- if (!oglrender->is_sequencer) {
- add_gpencil_renderpass(C, oglrender, rr, rv);
- }
/* render composite */
screen_opengl_render_doit(C, oglrender, rr);
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 04632838cf3..8bb60b19dcf 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -158,7 +158,7 @@ typedef struct ShaderPreview {
Scene *scene;
Depsgraph *depsgraph;
- ID *id;
+ ID *id, *id_copy;
ID *parent;
MTex *slot;
@@ -173,6 +173,7 @@ typedef struct ShaderPreview {
int sizex, sizey;
unsigned int *pr_rect;
int pr_method;
+ bool own_id_copy;
Main *bmain;
Main *pr_main;
@@ -189,7 +190,7 @@ typedef struct IconPreview {
Scene *scene;
Depsgraph *depsgraph;
void *owner;
- ID *id;
+ ID *id, *id_copy;
ListBase sizes;
} IconPreview;
@@ -197,6 +198,7 @@ typedef struct IconPreview {
static Main *G_pr_main = NULL;
static Main *G_pr_main_cycles = NULL;
+static Main *G_pr_main_grease_pencil = NULL;
#ifndef WITH_HEADLESS
static Main *load_main_from_memory(const void *blend, int blend_size)
@@ -226,6 +228,7 @@ void ED_preview_ensure_dbase(void)
if (!base_initialized) {
G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
G_pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size);
+ G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend, datatoc_preview_grease_pencil_blend_size);
base_initialized = true;
}
#endif
@@ -234,7 +237,13 @@ void ED_preview_ensure_dbase(void)
static bool check_engine_supports_textures(Scene *scene)
{
RenderEngineType *type = RE_engines_find(scene->r.engine);
- return type->flag & RE_USE_TEXTURE_PREVIEW;
+ return (type->flag & RE_USE_TEXTURE_PREVIEW) != 0;
+}
+
+static bool check_engine_supports_preview(Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type->flag & RE_USE_PREVIEW) != 0;
}
void ED_preview_free_dbase(void)
@@ -244,6 +253,9 @@ void ED_preview_free_dbase(void)
if (G_pr_main_cycles)
BKE_main_free(G_pr_main_cycles);
+
+ if (G_pr_main_grease_pencil)
+ BKE_main_free(G_pr_main_grease_pencil);
}
static Scene *preview_get_scene(Main *pr_main)
@@ -312,6 +324,38 @@ static World *preview_get_localized_world(ShaderPreview *sp, World *world)
return sp->worldcopy;
}
+static ID *duplicate_ids(ID *id, Depsgraph *depsgraph)
+{
+ if (id == NULL) {
+ /* Non-ID preview render. */
+ return NULL;
+ }
+
+ ID *id_eval = id;
+
+ if (depsgraph) {
+ id_eval = DEG_get_evaluated_id(depsgraph, id);
+ }
+
+ switch (GS(id->name)) {
+ case ID_MA:
+ return (ID *)BKE_material_localize((Material *)id_eval);
+ case ID_TE:
+ return (ID *)BKE_texture_localize((Tex *)id_eval);
+ case ID_LA:
+ return (ID *)BKE_lamp_localize((Lamp *)id_eval);
+ case ID_WO:
+ return (ID *)BKE_world_localize((World *)id_eval);
+ case ID_IM:
+ case ID_BR:
+ case ID_SCR:
+ return NULL;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ return NULL;
+ }
+}
+
/* call this with a pointer to initialize preview scene */
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
@@ -373,8 +417,9 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
if (origmat) {
/* work on a copy */
- mat = BKE_material_localize(origmat);
- sp->matcopy = mat;
+ BLI_assert(sp->id_copy != NULL);
+ mat = sp->matcopy = (Material *)sp->id_copy;
+ sp->id_copy = NULL;
BLI_addtail(&pr_main->mat, mat);
/* use current scene world to light sphere */
@@ -400,13 +445,13 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origmat is not safe! */
BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
}
}
}
else {
sce->r.mode &= ~(R_OSA);
-
}
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
@@ -432,16 +477,18 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
Tex *tex = NULL, *origtex = (Tex *)id;
if (origtex) {
- tex = BKE_texture_localize(origtex);
- sp->texcopy = tex;
+ BLI_assert(sp->id_copy != NULL);
+ tex = sp->texcopy = (Tex *)sp->id_copy;
+ sp->id_copy = NULL;
BLI_addtail(&pr_main->tex, tex);
}
set_preview_collection(sce, view_layer, MA_TEXTURE);
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origtex is not safe! */
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
}
}
else if (id_type == ID_LA) {
@@ -449,8 +496,9 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
/* work on a copy */
if (origla) {
- la = BKE_lamp_localize(origla);
- sp->lampcopy = la;
+ BLI_assert(sp->id_copy != NULL);
+ la = sp->lampcopy = (Lamp *)sp->id_copy;
+ sp->id_copy = NULL;
BLI_addtail(&pr_main->lamp, la);
}
@@ -473,16 +521,18 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origla is not safe! */
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
}
}
else if (id_type == ID_WO) {
World *wrld = NULL, *origwrld = (World *)id;
if (origwrld) {
- wrld = BKE_world_localize(origwrld);
- sp->worldcopy = wrld;
+ BLI_assert(sp->id_copy != NULL);
+ wrld = sp->worldcopy = (World *)sp->id_copy;
+ sp->id_copy = NULL;
BLI_addtail(&pr_main->world, wrld);
}
@@ -492,6 +542,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origwrld is not safe! */
BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
}
}
@@ -685,7 +736,11 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
char name[32];
int sizex;
Main *pr_main = sp->pr_main;
- ID *id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
+ ID *id_eval = id;
+
+ if (sp->depsgraph) {
+ id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
+ }
/* in case of split preview, use border render */
if (split) {
@@ -704,6 +759,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
sce->r.size = 100;
}
+
/* get the stuff from the builtin preview dbase */
sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
if (sce == NULL) return;
@@ -795,70 +851,51 @@ static void shader_preview_free(void *customdata)
Main *pr_main = sp->pr_main;
if (sp->matcopy) {
- struct IDProperty *properties;
-
- /* node previews */
- shader_preview_updatejob(sp);
-
- /* get rid of copied material */
+ sp->id_copy = (ID *)sp->matcopy;
BLI_remlink(&pr_main->mat, sp->matcopy);
-
- BKE_material_free(sp->matcopy);
-
- properties = IDP_GetProperties((ID *)sp->matcopy, false);
- if (properties) {
- IDP_FreeProperty(properties);
- MEM_freeN(properties);
- }
- MEM_freeN(sp->matcopy);
}
if (sp->texcopy) {
- struct IDProperty *properties;
- /* node previews */
- shader_preview_updatejob(sp);
-
- /* get rid of copied texture */
+ sp->id_copy = (ID *)sp->texcopy;
BLI_remlink(&pr_main->tex, sp->texcopy);
- BKE_texture_free(sp->texcopy);
-
- properties = IDP_GetProperties((ID *)sp->texcopy, false);
- if (properties) {
- IDP_FreeProperty(properties);
- MEM_freeN(properties);
- }
- MEM_freeN(sp->texcopy);
}
if (sp->worldcopy) {
- struct IDProperty *properties;
- /* node previews */
- shader_preview_updatejob(sp);
-
- /* get rid of copied world */
+ sp->id_copy = (ID *)sp->worldcopy;
BLI_remlink(&pr_main->world, sp->worldcopy);
- BKE_world_free(sp->worldcopy);
-
- properties = IDP_GetProperties((ID *)sp->worldcopy, false);
- if (properties) {
- IDP_FreeProperty(properties);
- MEM_freeN(properties);
- }
- MEM_freeN(sp->worldcopy);
}
if (sp->lampcopy) {
- struct IDProperty *properties;
+ sp->id_copy = (ID *)sp->lampcopy;
+ BLI_remlink(&pr_main->lamp, sp->lampcopy);
+ }
+ if (sp->id_copy) {
/* node previews */
shader_preview_updatejob(sp);
-
- /* get rid of copied lamp */
- BLI_remlink(&pr_main->lamp, sp->lampcopy);
- BKE_lamp_free(sp->lampcopy);
-
- properties = IDP_GetProperties((ID *)sp->lampcopy, false);
+ }
+ if (sp->id_copy && sp->own_id_copy) {
+ struct IDProperty *properties;
+ /* get rid of copied ID */
+ properties = IDP_GetProperties(sp->id_copy, false);
if (properties) {
IDP_FreeProperty(properties);
MEM_freeN(properties);
}
- MEM_freeN(sp->lampcopy);
+ switch (GS(sp->id_copy->name)) {
+ case ID_MA:
+ BKE_material_free((Material *)sp->id_copy);
+ break;
+ case ID_TE:
+ BKE_texture_free((Tex *)sp->id_copy);
+ break;
+ case ID_LA:
+ BKE_lamp_free((Lamp *)sp->id_copy);
+ break;
+ case ID_WO:
+ BKE_world_free((World *)sp->id_copy);
+ break;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ break;
+ }
+ MEM_freeN(sp->id_copy);
}
MEM_freeN(sp);
@@ -1062,6 +1099,10 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
continue;
}
+ if (!check_engine_supports_preview(ip->scene)) {
+ continue;
+ }
+
ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
@@ -1074,7 +1115,10 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
sp->pr_rect = cur_size->rect;
sp->id = ip->id;
+ sp->id_copy = ip->id_copy;
sp->bmain = ip->bmain;
+ sp->own_id_copy = false;
+ Material *ma = NULL;
if (is_render) {
BLI_assert(ip->id);
@@ -1082,10 +1126,22 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
* so don't even think of using cycle's bmain for
* texture icons
*/
- if (GS(ip->id->name) != ID_TE)
- sp->pr_main = G_pr_main_cycles;
- else
+ if (GS(ip->id->name) != ID_TE) {
+ /* grease pencil use its own preview file */
+ if (GS(ip->id->name) == ID_MA) {
+ ma = (Material *)ip->id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main_cycles;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+ }
+ else {
sp->pr_main = G_pr_main;
+ }
}
common_preview_startjob(sp, stop, do_update, progress);
@@ -1133,6 +1189,15 @@ static void icon_preview_free(void *customdata)
{
IconPreview *ip = (IconPreview *)customdata;
+ if (ip->id_copy) {
+ /* Feels a bit hacky just to reuse shader_preview_free() */
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ sp->id_copy = ip->id_copy;
+ sp->own_id_copy = true;
+ shader_preview_free(sp);
+ ip->id_copy = NULL;
+ }
+
BLI_freelistN(&ip->sizes);
MEM_freeN(ip);
}
@@ -1149,6 +1214,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec
ip.scene = scene;
ip.owner = BKE_previewimg_id_ensure(id);
ip.id = id;
+ ip.id_copy = duplicate_ids(id, NULL);
icon_preview_add_size(&ip, rect, sizex, sizey);
@@ -1183,6 +1249,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
ip->depsgraph = CTX_data_depsgraph(C);
ip->owner = owner;
ip->id = id;
+ ip->id_copy = duplicate_ids(id, ip->depsgraph);
icon_preview_add_size(ip, rect, sizex, sizey);
@@ -1212,6 +1279,10 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
/* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
+ if (!check_engine_supports_preview(scene)) {
+ return;
+ }
+
/* Only texture node preview is supported with Cycles. */
if (method == PR_NODE_RENDER && id_type != ID_TE) {
return;
@@ -1231,14 +1302,28 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
sp->sizey = sizey;
sp->pr_method = method;
sp->id = id;
+ sp->id_copy = duplicate_ids(id, sp->depsgraph);
+ sp->own_id_copy = true;
sp->parent = parent;
sp->slot = slot;
sp->bmain = CTX_data_main(C);
+ Material *ma = NULL;
/* hardcoded preview .blend for Eevee + Cycles, this should be solved
* once with custom preview .blend path for external engines */
if ((method != PR_NODE_RENDER) && id_type != ID_TE) {
- sp->pr_main = G_pr_main_cycles;
+ /* grease pencil use its own preview file */
+ if (GS(id->name) == ID_MA) {
+ ma = (Material *)id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main_cycles;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+
}
else {
sp->pr_main = G_pr_main;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 8077079a9b5..2dd4f328d06 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -469,6 +469,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
{
Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
@@ -477,7 +478,12 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_copy(bmain, ma);
}
else {
- ma = BKE_material_add(bmain, DATA_("Material"));
+ if ((!ob) || (ob->type != OB_GPENCIL)) {
+ ma = BKE_material_add(bmain, DATA_("Material"));
+ }
+ else {
+ ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
+ }
ED_node_shader_default(C, &ma->id);
ma->use_nodes = true;
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index e473b98b4a1..09d89e3b90f 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -144,7 +144,7 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
}
else {
RenderEngineType *engine_type =
- ED_view3d_engine_type(scene, v3d->drawtype);
+ ED_view3d_engine_type(scene, v3d->shading.type);
if (updated) {
DRW_notify_view_update(
(&(DRWUpdateContext){
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 41c3209dbb1..18bacee98b9 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -105,12 +105,12 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
float color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
- immBeginAtMost(GWN_PRIM_LINES, 8);
+ immBeginAtMost(GPU_PRIM_LINES, 8);
/* right */
if (sides & REGION_EMBOSS_RIGHT) {
@@ -146,7 +146,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
void ED_region_pixelspace(ARegion *ar)
{
wmOrtho2_region_pixelspace(ar);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
}
/* only exported for WM */
@@ -262,8 +262,8 @@ 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);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -271,7 +271,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
immUniformColor4f(0.0f, 1.0f, 1.0f, alpha);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, click_rect.xmin, click_rect.ymin);
immVertex2f(pos, click_rect.xmax, click_rect.ymax);
immVertex2f(pos, click_rect.xmin, click_rect.ymax);
@@ -295,8 +295,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;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_blend(true);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -352,8 +352,8 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- gpuPushMatrix();
- gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(-ar->winrct.xmin, -ar->winrct.ymin);
for (az = sa->actionzones.first; az; az = az->next) {
/* test if action zone is over this region */
@@ -388,7 +388,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
}
- gpuPopMatrix();
+ GPU_matrix_pop();
GPU_blend(false);
}
@@ -500,8 +500,8 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
/* for debugging unneeded area redraws and partial redraw */
#if 0
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_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,
@@ -1428,18 +1428,32 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
}
if (flag & ED_KEYMAP_GPENCIL) {
/* grease pencil */
- /* NOTE: This is now 2 keymaps - One for basic functionality,
- * and one that only applies when "Edit Mode" is enabled
- * for strokes.
+ /* NOTE: This is now 4 keymaps - One for basic functionality,
+ * and others for special stroke modes (edit, paint and sculpt).
*
- * For now, it's easier to just include both,
- * since you hardly want one without the other.
+ * For now, it's easier to just include all,
+ * since you hardly want one without the others.
*/
wmKeyMap *keymap_general = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0);
- wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
-
WM_event_add_keymap_handler(handlers, keymap_general);
+
+ wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_edit);
+
+ wmKeyMap *keymap_paint = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Paint Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint);
+
+ wmKeyMap *keymap_paint_draw = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_draw);
+
+ wmKeyMap *keymap_paint_erase = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_erase);
+
+ wmKeyMap *keymap_paint_fill = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_fill);
+
+ wmKeyMap *keymap_sculpt = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt);
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
@@ -2472,8 +2486,8 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(fill_color);
immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
@@ -2674,11 +2688,11 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
return;
/* find window pixel coordinates of origin */
- gpuPushMatrix();
+ GPU_matrix_push();
/* offset and zoom using ogl */
- gpuTranslate2f(x, y);
- gpuScale2f(zoomx, zoomy);
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
@@ -2691,8 +2705,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 */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_METADATA_BG);
immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2716,8 +2730,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 */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_METADATA_BG);
immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2732,7 +2746,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
BLF_disable(blf_mono_font, BLF_CLIPPING);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
@@ -2745,8 +2759,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);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, 20);
@@ -2778,12 +2792,12 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
int count_large = 1.0f / (4.0f * gridstep);
if (count_fine > 0) {
- GWN_vertformat_clear(format);
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPU_vertformat_clear(format);
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, 4 * count_fine + 4 * count_large);
+ immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
float theme_color[3];
UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color);
@@ -2877,7 +2891,7 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect)
void ED_region_cache_draw_background(const ARegion *ar)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(128, 128, 255, 64);
immRecti(pos, 0, 0, ar->winx, 8 * UI_DPI_FAC);
@@ -2897,7 +2911,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_CFRAME);
immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
@@ -2911,7 +2925,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
{
if (num_segments) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(128, 128, 255, 128);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 6cff82295f0..7fa093106df 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -140,9 +140,9 @@ static int get_cached_work_texture(int *r_w, int *r_h)
static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
{
- Gwn_VertFormat *vert_format = immVertexFormat();
- state->pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- state->texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *vert_format = immVertexFormat();
+ state->pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ state->texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
/* To be used before calling immDrawPixelsTex
@@ -297,7 +297,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
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]);
}
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
@@ -364,7 +364,7 @@ void bglPolygonOffset(float viewdist, float dist)
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
- gpuGetProjectionMatrix(winmat);
+ GPU_matrix_projection_get(winmat);
/* dist is from camera to center point */
@@ -401,7 +401,7 @@ void bglPolygonOffset(float viewdist, float dist)
offset = 0.0;
}
- gpuLoadProjectionMatrix(winmat);
+ GPU_matrix_projection_set(winmat);
}
/* **** Color management helper functions for GLSL display/transform ***** */
@@ -551,28 +551,28 @@ void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, flo
delta_y = min_ff(delta_y, border->ymax - border->ymin);
/* left bottom corner */
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_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 */
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_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 */
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_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 */
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_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);
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 17b1af29010..5a520540301 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -34,6 +34,7 @@
#include "DNA_object_types.h"
#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
@@ -44,10 +45,13 @@
#include "BLI_utildefines.h"
+#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_object.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_paint.h"
+#include "BKE_main.h"
#include "BKE_gpencil.h"
#include "BKE_layer.h"
#include "BKE_screen.h"
@@ -80,8 +84,7 @@ const char *screen_context_dir[] = {
"sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */
"gpencil_data", "gpencil_data_owner", /* grease pencil data */
"visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes",
- "active_gpencil_layer", "active_gpencil_frame", "active_gpencil_palette",
- "active_gpencil_palettecolor", "active_gpencil_brush",
+ "active_gpencil_layer", "active_gpencil_frame", "active_gpencil_brush",
"active_operator", "selected_editable_fcurves",
NULL};
@@ -164,7 +167,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "selectable_bases")) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLE) != 0) {
+ if ((base->flag & BASE_VISIBLE) && (base->flag & BASE_SELECTABLE) != 0) {
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
@@ -467,7 +470,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
* (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when
* called from context. For that reason, we end up using an alternative where we pass everything in!
*/
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
@@ -482,7 +485,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
PointerRNA ptr;
/* get pointer to Grease Pencil Data */
- gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, scene, sa, obact, &ptr);
+ gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, sa, scene, obact, &ptr);
if (gpd_ptr) {
CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
@@ -491,7 +494,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "active_gpencil_layer")) {
/* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
@@ -502,47 +505,17 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
}
- else if (CTX_data_equals(member, "active_gpencil_palette")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
-
- if (gpd) {
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
-
- if (palette) {
- CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilPalette, palette);
- return 1;
- }
- }
- }
- else if (CTX_data_equals(member, "active_gpencil_palettecolor")) {
- /* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
-
- if (gpd) {
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
-
- if (palette) {
- bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette);
- if (palcolor) {
- CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilPaletteColor, palcolor);
- return 1;
- }
- }
- }
- }
else if (CTX_data_equals(member, "active_gpencil_brush")) {
- /* XXX: see comment for gpencil_data case... */
- bGPDbrush *brush = BKE_gpencil_brush_getactive(scene->toolsettings);
+ Brush *brush = BKE_brush_getactive_gpencil(scene->toolsettings);
if (brush) {
- CTX_data_pointer_set(result, &scene->id, &RNA_GPencilBrush, brush);
+ CTX_data_pointer_set(result, &scene->id, &RNA_Brush, brush);
return 1;
}
}
else if (CTX_data_equals(member, "active_gpencil_frame")) {
/* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
if (gpd) {
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
@@ -555,7 +528,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "visible_gpencil_layers")) {
/* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
if (gpd) {
bGPDlayer *gpl;
@@ -571,7 +544,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "editable_gpencil_layers")) {
/* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
if (gpd) {
bGPDlayer *gpl;
@@ -587,24 +560,37 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
/* XXX: see comment for gpencil_data case... */
- bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, sa, scene, obact);
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
if (gpd) {
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
- bGPDframe *gpf = gpl->actframe;
+ bGPDframe *gpf;
bGPDstroke *gps;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
- continue;
+ for (gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
+ continue;
+ }
+
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
}
-
- CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
}
}
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 9c46938a90f..10d72d74b22 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -99,7 +99,7 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
}
}
- immBegin(GWN_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
@@ -107,7 +107,7 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
immEnd();
- immBegin(GWN_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
@@ -180,7 +180,7 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
}
}
- immBegin(GWN_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 0; i < 5; i++) {
immVertex2f(pos, points[i].x, points[i].y);
@@ -188,7 +188,7 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
immEnd();
- immBegin(GWN_PRIM_TRI_FAN, 5);
+ immBegin(GPU_PRIM_TRI_FAN, 5);
for (i = 4; i < 8; i++) {
immVertex2f(pos, points[i].x, points[i].y);
@@ -323,11 +323,11 @@ static void drawscredge_corner(ScrArea *sa, int sizex, int sizey)
/* Wrap up the corners with a nice embossing. */
rcti rect = sa->totrct;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
- immBeginAtMost(GWN_PRIM_LINES, 8);
+ immBeginAtMost(GPU_PRIM_LINES, 8);
/* Right. */
immVertex2f(pos, rect.xmax, rect.ymax);
@@ -386,7 +386,7 @@ static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, shor
return;
}
- immBegin(GWN_PRIM_LINES, count);
+ immBegin(GPU_PRIM_LINES, count);
/* right border area */
if (x2 < sizex - 1) {
@@ -439,7 +439,7 @@ void ED_screen_draw_edges(wmWindow *win)
ScrArea *sa;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* Note: first loop only draws if U.pixelsize > 1, skip otherwise */
@@ -477,7 +477,7 @@ void ED_screen_draw_edges(wmWindow *win)
*/
void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_width(1);
@@ -518,14 +518,14 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* splitpoint */
GPU_blend(true);
immUniformColor4ub(255, 255, 255, 100);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
if (dir == 'h') {
const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
@@ -537,7 +537,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immUniformColor4ub(0, 0, 0, 100);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, sa->totrct.xmin, y + 1);
immVertex2f(pos, sa->totrct.xmax, y + 1);
@@ -555,7 +555,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immUniformColor4ub(0, 0, 0, 100);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x + 1, sa->totrct.ymin);
immVertex2f(pos, x + 1, sa->totrct.ymax);
@@ -594,7 +594,7 @@ static void screen_preview_draw_areas(const bScreen *screen, const float scale[2
const float ofs_between_areas)
{
const float ofs_h = ofs_between_areas * 0.5f;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
@@ -607,7 +607,7 @@ static void screen_preview_draw_areas(const bScreen *screen, const float scale[2
.ymax = sa->totrct.ymax * scale[1] - ofs_h
};
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immVertex2f(pos, rect.xmin, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymin);
immVertex2f(pos, rect.xmax, rect.ymax);
@@ -627,14 +627,14 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
wmOrtho2(0.0f, size_x, 0.0f, size_y);
/* center */
- gpuPushMatrix();
- gpuLoadIdentity();
- gpuTranslate2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ GPU_matrix_translate_2f(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();
+ GPU_matrix_pop();
}
/**
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index cd71c07a3c0..9f845bf04ba 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -37,7 +37,7 @@ struct Main;
/* internal exports only */
-#define AZONESPOT (0.6f * U.widget_unit)
+#define AZONESPOT (0.8f * U.widget_unit)
#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index a837b32b0bb..c8ad2b954a5 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -47,6 +47,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_workspace_types.h"
@@ -359,6 +360,15 @@ bool ED_operator_editmesh_region_view3d(bContext *C)
return 0;
}
+bool ED_operator_editmesh_auto_smooth(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH && (((Mesh *)(obedit->data))->flag & ME_AUTOSMOOTH)) {
+ return NULL != BKE_editmesh_from_object(obedit);
+ }
+ return 0;
+}
+
bool ED_operator_editarmature(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
@@ -2608,11 +2618,14 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
/* populate tree with keyframe nodes */
scene_to_keylist(&ads, scene, &keys, NULL);
- gpencil_to_keylist(&ads, scene->gpd, &keys);
if (ob) {
ob_to_keylist(&ads, ob, &keys, NULL);
- gpencil_to_keylist(&ads, ob->gpd, &keys);
+
+ if (ob->type == OB_GPENCIL) {
+ const bool active = !(scene->flag & SCE_KEYS_NO_SELONLY);
+ gpencil_to_keylist(&ads, ob->data, &keys, active);
+ }
}
{
@@ -4813,7 +4826,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
}
-static bool open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
if (drag->type == WM_DRAG_PATH) {
if (drag->icon == ICON_FILE_BLEND)
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index afaad3963d5..9c0c59a7160 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -247,7 +247,7 @@ static void screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
screenshot_data_free(op);
}
-static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
@@ -266,7 +266,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiDefAutoButsRNA(layout, &ptr, screenshot_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
}
static bool screenshot_poll(bContext *C)
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 6b3c358d2ac..997fe1282f9 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -618,19 +618,19 @@ static void paint_draw_tex_overlay(
glDepthFunc(GL_ALWAYS);
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- gpuPushMatrix();
+ GPU_matrix_push();
/* brush rotation */
- gpuTranslate2f(x, y);
- gpuRotate2D(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec));
- gpuTranslate2f(-x, -y);
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_rotate_2d(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec));
+ GPU_matrix_translate_2f(-x, -y);
/* scale based on tablet pressure */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
const float scale = ups->size_pressure_value;
- gpuTranslate2f(x, y);
- gpuScale2f(scale, scale);
- gpuTranslate2f(-x, -y);
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(scale, scale);
+ GPU_matrix_translate_2f(-x, -y);
}
if (ups->draw_anchored) {
@@ -671,18 +671,18 @@ static void paint_draw_tex_overlay(
quad.xmax = brush->mask_stencil_dimension[0];
quad.ymax = brush->mask_stencil_dimension[1];
}
- gpuPushMatrix();
+ GPU_matrix_push();
if (primary)
- gpuTranslate2fv(brush->stencil_pos);
+ GPU_matrix_translate_2fv(brush->stencil_pos);
else
- gpuTranslate2fv(brush->mask_stencil_pos);
- gpuRotate2D(RAD2DEGF(mtex->rot));
+ GPU_matrix_translate_2fv(brush->mask_stencil_pos);
+ GPU_matrix_rotate_2d(RAD2DEGF(mtex->rot));
}
/* set quad color. Colored overlay does not get blending */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (col) {
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
@@ -696,7 +696,7 @@ static void paint_draw_tex_overlay(
/* draw textured quad */
immUniform1i("image", GL_TEXTURE0);
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texCoord, 0.0f, 0.0f);
immVertex2f(pos, quad.xmin, quad.ymin);
immAttrib2f(texCoord, 1.0f, 0.0f);
@@ -710,7 +710,7 @@ static void paint_draw_tex_overlay(
immUnbindProgram();
if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_VIEW)) {
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
}
@@ -762,16 +762,16 @@ static void paint_draw_cursor_overlay(
/* scale based on tablet pressure */
if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
do_pop = true;
- gpuPushMatrix();
- gpuLoadIdentity();
- gpuTranslate2fv(center);
- gpuScaleUniform(ups->size_pressure_value);
- gpuTranslate2f(-center[0], -center[1]);
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ GPU_matrix_translate_2fv(center);
+ GPU_matrix_scale_1f(ups->size_pressure_value);
+ GPU_matrix_translate_2f(-center[0], -center[1]);
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
@@ -782,7 +782,7 @@ static void paint_draw_cursor_overlay(
/* draw textured quad */
immUniform1i("image", 0);
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texCoord, 0.0f, 0.0f);
immVertex2f(pos, quad.xmin, quad.ymin);
immAttrib2f(texCoord, 1.0f, 0.0f);
@@ -796,7 +796,7 @@ static void paint_draw_cursor_overlay(
immUnbindProgram();
if (do_pop)
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
@@ -844,7 +844,7 @@ BLI_INLINE void draw_tri_point(
{co[0] + w, co[1] - w},
};
- immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
immVertex2fv(pos, tri[0]);
immVertex2fv(pos, tri[1]);
immVertex2fv(pos, tri[2]);
@@ -853,7 +853,7 @@ BLI_INLINE void draw_tri_point(
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
GPU_line_width(1.0f);
- immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immBegin(GPU_PRIM_LINE_LOOP, 3);
immVertex2fv(pos, tri[0]);
immVertex2fv(pos, tri[1]);
immVertex2fv(pos, tri[2]);
@@ -888,7 +888,7 @@ BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], Bez
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
GPU_line_width(3.0f);
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2fv(pos, bez->vec[0]);
immVertex2fv(pos, bez->vec[1]);
immVertex2fv(pos, bez->vec[2]);
@@ -902,7 +902,7 @@ BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], Bez
else {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, bez->vec[0]);
immVertex2fv(pos, bez->vec[1]);
immEnd();
@@ -913,7 +913,7 @@ BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], Bez
else {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, bez->vec[1]);
immVertex2fv(pos, bez->vec[2]);
immEnd();
@@ -930,7 +930,7 @@ static void paint_draw_curve_cursor(Brush *brush)
GPU_blend(true);
/* draw the bezier handles and the curve segment between the current and next point */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -961,7 +961,7 @@ static void paint_draw_curve_cursor(Brush *brush)
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
GPU_line_width(3.0f);
- immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
immVertex2fv(pos, v[j]);
}
@@ -969,7 +969,7 @@ static void paint_draw_curve_cursor(Brush *brush)
immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
GPU_line_width(1.0f);
- immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
immVertex2fv(pos, v[j]);
}
@@ -1118,7 +1118,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
GPU_blend(true); /* TODO: also set blend mode? */
GPU_line_smooth(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* set brush color */
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 6276a2838f5..897a74eb497 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -419,15 +419,15 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
GPU_line_smooth(true);
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_width(4.0);
immUniformColor4ub(0, 0, 0, 255);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2i(pos, x, y);
immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]);
immEnd();
@@ -435,7 +435,7 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
GPU_line_width(2.0);
immUniformColor4ub(255, 255, 255, 255);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2i(pos, x, y);
immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]);
immEnd();
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 04329697b54..7badd30e6d0 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -5442,7 +5442,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (h > maxsize) h = maxsize;
ibuf = ED_view3d_draw_offscreen_imbuf(
- depsgraph, scene, v3d->drawtype,
+ depsgraph, scene, v3d->shading.type,
v3d, CTX_wm_region(C),
w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, err_out);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 0f796020d9e..86d36ade477 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -29,20 +29,27 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_math_color.h"
#include "DNA_customdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_paint.h"
+#include "BKE_gpencil.h"
#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_image.h"
+#include "ED_gpencil.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -96,6 +103,43 @@ static void BRUSH_OT_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int brush_add_gpencil_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ /*int type = RNA_enum_get(op->ptr, "type");*/
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Paint *paint = &ts->gp_paint->paint;
+ Brush *br = BKE_paint_brush(paint);
+ Main *bmain = CTX_data_main(C);
+ // ePaintMode mode = ePaintGpencil;
+
+ if (br) {
+ br = BKE_brush_copy(bmain, br);
+ }
+ else {
+ br = BKE_brush_add(bmain, "Brush", OB_MODE_GPENCIL_PAINT);
+ id_us_min(&br->id); /* fake user only */
+ }
+
+ BKE_paint_brush_set(paint, br);
+
+ /* TODO init grease pencil specific data */
+
+ return OPERATOR_FINISHED;
+}
+
+static void BRUSH_OT_add_gpencil(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Drawing Brush";
+ ot->description = "Add brush for grease pencil";
+ ot->idname = "BRUSH_OT_add_gpencil";
+
+ /* api callbacks */
+ ot->exec = brush_add_gpencil_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
static int brush_scale_size_exec(bContext *C, wmOperator *op)
{
@@ -232,7 +276,6 @@ static void PALETTE_OT_color_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = BKE_paint_get_active_from_context(C);
@@ -1031,6 +1074,7 @@ void ED_operatortypes_paint(void)
/* brush */
WM_operatortype_append(BRUSH_OT_add);
+ WM_operatortype_append(BRUSH_OT_add_gpencil);
WM_operatortype_append(BRUSH_OT_scale_size);
WM_operatortype_append(BRUSH_OT_curve_preset);
WM_operatortype_append(BRUSH_OT_reset);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 0ef25eb63a1..fc008213ae0 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -155,11 +155,11 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
ARegion *ar = stroke->vc.ar;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(paint->paint_cursor_col);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, y);
immVertex2f(pos,
stroke->last_mouse_position[0] + ar->winrct.xmin,
@@ -181,7 +181,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
GPU_line_smooth(true);
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -194,7 +194,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
immUniformArray4fv("colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
immUniform1f("dash_width", 6.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
ARegion *ar = stroke->vc.ar;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 697ffc32759..e914a24092e 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -299,8 +299,8 @@ static void imapaint_pick_uv(Mesh *me_eval, Scene *scene, Object *ob_eval, unsig
/* get the needed opengl matrices */
GPU_viewport_size_get_i(view);
- gpuGetModelViewMatrix(matrix);
- gpuGetProjectionMatrix(proj);
+ GPU_matrix_model_view_get(matrix);
+ GPU_matrix_projection_get(proj);
view[0] = view[1] = 0;
mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
mul_m4_m4m4(matrix, proj, matrix);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index a0ef753e200..8fafc545fa9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -215,7 +215,7 @@ 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);
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fvAlpha(brush->add_col, alpha);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 3fc68a50057..15f688549a8 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -482,7 +482,7 @@ static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *even
#ifdef WITH_AUDASPACE
-static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
return !(STREQ(prop_id, "filepath") ||
@@ -635,7 +635,7 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
/* main draw call */
- uiDefAutoButsRNA(layout, &ptr, sound_mixdown_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiDefAutoButsRNA(layout, &ptr, sound_mixdown_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
}
#endif // WITH_AUDASPACE
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 8e521c997fd..e679688f887 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -211,8 +211,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* first backdrop strips */
y = (float)(-ACHANNEL_HEIGHT(ac));
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -326,7 +326,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
if (saction->flag & SACTION_MOVING) {
immUniformColor3f(0.0f, 0.0f, 0.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
immEnd();
@@ -404,7 +404,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* iterate over pointcaches on the active object, and draw each one's range */
@@ -436,9 +436,9 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
if (pid->cache->cached_frames == NULL)
continue;
- gpuPushMatrix();
- gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
- gpuScale2f(1.0, cache_draw_height);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
+ GPU_matrix_scale_2f(1.0, cache_draw_height);
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -492,7 +492,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
immUniformColor4fv(col);
if (len > 0) {
- immBeginAtMost(GWN_PRIM_TRIS, len);
+ immBeginAtMost(GPU_PRIM_TRIS, len);
/* draw a quad for each cached frame */
for (int i = sta; i <= end; i++) {
@@ -512,7 +512,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
yoffs += cache_draw_height;
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index c46d0fdb035..831c461538a 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -51,6 +51,7 @@
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_gpencil.h"
#include "UI_view2d.h"
@@ -134,15 +135,20 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
/* Now set the flags */
for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gplayer_frame_select_set(ale->data, sel);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frame_select_set(ale->data, sel);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
+ }
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -283,12 +289,16 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode);
}
+ ale->update |= ANIM_UPDATE_DEPS;
break;
}
#endif
case ANIMTYPE_GPLAYER:
+ {
ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
break;
+ }
case ANIMTYPE_MASKDATABLOCK:
{
Mask *mask = ale->data;
@@ -312,6 +322,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
}
/* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -493,6 +504,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
case ANIMTYPE_GPLAYER:
{
ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
break;
}
case ANIMTYPE_MASKDATABLOCK:
@@ -520,6 +532,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
}
/* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -707,6 +720,7 @@ static void markers_selectkeys_between(bAnimContext *ac)
}
else if (ale->type == ANIMTYPE_GPLAYER) {
ED_gplayer_frames_select_border(ale->data, min, max, SELECT_ADD);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frames_select_border(ale->data, min, max, SELECT_ADD);
@@ -717,6 +731,7 @@ static void markers_selectkeys_between(bAnimContext *ac)
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -796,17 +811,23 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
ked.f1 = ce->cfra;
/* select elements with frame number matching cfraelem */
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
}
/* free elements */
BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1081,12 +1102,16 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
- else if (ale->type == ANIMTYPE_GPLAYER)
+ else if (ale->type == ANIMTYPE_GPLAYER) {
ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
/* Sync marker support */
@@ -1111,6 +1136,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1227,6 +1253,7 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
/* select the nominated keyframe on the given frame */
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, selx, select_mode);
@@ -1244,12 +1271,14 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, selx, select_mode);
}
}
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1294,16 +1323,22 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
ked.f1 = selx;
/* select elements with frame number matching cfra */
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->key_data, selx, select_mode);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->key_data, selx, select_mode);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
/* free elements */
BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1318,6 +1353,7 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
/* select all keyframes in this channel */
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update = ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale->data, select_mode);
@@ -1335,12 +1371,14 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale->data, select_mode);
}
}
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1473,6 +1511,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
/* remove active channel from list of channels for separate treatment (since it's needed later on) */
BLI_remlink(&anim_data, ale);
+ ale->next = ale->prev = NULL;
/* cleanup temporary lists */
BLI_dlrbTree_free(&anim_keys);
@@ -1557,6 +1596,12 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
}
}
+ /* flush tagged updates
+ * NOTE: We temporarily add this channel back to the list so that this can happen
+ */
+ anim_data.first = anim_data.last = ale;
+ ANIM_animdata_update(ac, &anim_data);
+
/* free this channel */
MEM_freeN(ale);
}
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 7246812dc82..84de55a172d 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -136,6 +136,7 @@ void ED_spacetypes_init(void)
ED_gizmotypes_arrow_2d();
ED_gizmotypes_arrow_3d();
ED_gizmotypes_primitive_3d();
+ ED_gizmotypes_blank_3d();
ED_gizmotypes_cage_2d();
ED_gizmotypes_cage_3d();
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index faee9c2b7ac..67632f6a53a 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -237,6 +237,7 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
else if (RNA_struct_is_a(ptr->type, &RNA_Light) && (type == -1 || type == OB_LAMP)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) return 1;
+ else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) return 1;
/* try to get an object in the path, no pinning supported here */
else if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
@@ -260,7 +261,21 @@ static int buttons_context_path_modifier(ButsContextPath *path)
if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
- if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
+ if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE, OB_GPENCIL))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int buttons_context_path_shaderfx(ButsContextPath *path)
+{
+ Object *ob;
+
+ if (buttons_context_path_object(path)) {
+ ob = path->ptr[path->len - 1].data;
+
+ if (ob && ELEM(ob->type, OB_GPENCIL))
return 1;
}
@@ -485,6 +500,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
WorkSpace *workspace = CTX_wm_workspace(C);
ID *id;
int found;
+ Object *ob = CTX_data_active_object(C);
memset(path, 0, sizeof(*path));
path->flag = flag;
@@ -546,6 +562,9 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_MODIFIER:
found = buttons_context_path_modifier(path);
break;
+ case BCONTEXT_SHADERFX:
+ found = buttons_context_path_shaderfx(path);
+ break;
case BCONTEXT_DATA:
found = buttons_context_path_data(path, -1);
break;
@@ -553,7 +572,14 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
found = buttons_context_path_particle(path);
break;
case BCONTEXT_MATERIAL:
- found = buttons_context_path_material(path);
+ /* NOTE: Grease Pencil materials use different panels... */
+ if (ob && ob->type == OB_GPENCIL) {
+ /* XXX: Why path_data? */
+ found = buttons_context_path_data(path, -1);
+ }
+ else {
+ found = buttons_context_path_material(path);
+ }
break;
case BCONTEXT_TEXTURE:
found = buttons_context_path_texture(C, path, sbuts->texuser);
@@ -626,10 +652,18 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
if (a == BCONTEXT_DATA) {
ptr = &path->ptr[path->len - 1];
- if (ptr->type)
+ if (ptr->type) {
sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
- else
- sbuts->dataicon = ICON_EMPTY_DATA;
+ }
+ else {
+ Object *ob = CTX_data_active_object(C);
+ if (ob->type == OB_GPENCIL) {
+ sbuts->dataicon = ICON_GREASEPENCIL;
+ }
+ else {
+ sbuts->dataicon = ICON_EMPTY_DATA;
+ }
+ }
}
}
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 66684de18ac..de422565abd 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -55,6 +55,7 @@
#include "BKE_layer.h"
#include "BKE_linestyle.h"
#include "BKE_modifier.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@@ -152,6 +153,19 @@ static void buttons_texture_modifier_foreach(void *userData, Object *ob, Modifie
N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
}
+static void buttons_texture_modifier_gpencil_foreach(void *userData, Object *ob, GpencilModifierData *md, const char *propname)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ ListBase *users = userData;
+
+ RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr);
+ prop = RNA_struct_find_property(&ptr, propname);
+
+ buttons_texture_user_property_add(users, &ob->id, ptr, prop,
+ N_("Grease Pencil Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
+}
+
static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceButs *sbuts)
{
Scene *scene = NULL;
@@ -203,6 +217,9 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
/* modifiers */
modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
+ /* grease pencil modifiers */
+ BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users);
+
/* particle systems */
if (psys && !limited_mode) {
for (a = 0; a < MAX_MTEX; a++) {
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 6f7a4ca971a..0350e3fcd14 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -180,6 +180,9 @@ static void buttons_main_region_layout_properties(const bContext *C, SpaceButs *
case BCONTEXT_MODIFIER:
contexts[0] = "modifier";
break;
+ case BCONTEXT_SHADERFX:
+ contexts[0] = "shaderfx";
+ break;
case BCONTEXT_CONSTRAINT:
contexts[0] = "constraint";
break;
@@ -200,8 +203,9 @@ static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar)
const char *contexts[3] = {NULL};
const WorkSpace *workspace = CTX_wm_workspace(C);
+ const int mode = CTX_data_mode_enum(C);
+
if (workspace->tools_space_type == SPACE_VIEW3D) {
- const int mode = CTX_data_mode_enum(C);
switch (mode) {
case CTX_MODE_EDIT_MESH:
ARRAY_SET_ITEMS(contexts, ".mesh_edit");
@@ -240,17 +244,44 @@ static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar)
ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
break;
case CTX_MODE_PARTICLE:
- ARRAY_SET_ITEMS(contexts, ".particlemode");
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
break;
case CTX_MODE_OBJECT:
ARRAY_SET_ITEMS(contexts, ".objectmode");
break;
+ case CTX_MODE_GPENCIL_PAINT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_GPENCIL_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_GPENCIL_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
}
}
else if (workspace->tools_space_type == SPACE_IMAGE) {
/* TODO */
}
+ /* for grease pencil we don't use tool system yet, so we need check outside
+ * workspace->tools_space_type because this value is not available
+ */
+ switch (mode) {
+ case CTX_MODE_GPENCIL_PAINT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_GPENCIL_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_GPENCIL_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ case CTX_MODE_GPENCIL_EDIT:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
+ break;
+ }
+
const bool vertical = true;
ED_region_panels_layout_ex(C, ar, contexts, -1, vertical);
}
@@ -495,6 +526,14 @@ static void buttons_area_listener(
break;
}
break;
+ case NC_GPENCIL:
+ switch (wmn->data) {
+ case ND_DATA:
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ ED_area_tag_redraw(sa);
+ break;
+ }
+ break;
case NC_NODE:
if (wmn->action == NA_SELECTED) {
ED_area_tag_redraw(sa);
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index db5f6c2451c..6953b7cfb71 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -107,7 +107,7 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiLayoutSetContextPointer(layout, "edit_movieclip", &clipptr);
if (!compact)
- uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (clip) {
uiLayout *col;
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 76450cba3cb..2aa0a3e2b9a 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -130,8 +130,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
uint keyframe_len = 0;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* don't use totrect set, as the width stays the same
@@ -215,14 +215,14 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
if (keyframe_len > 0) {
/* draw keyframe markers */
format = immVertexFormat();
- pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- uint outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, keyframe_len);
+ immBegin(GPU_PRIM_POINTS, keyframe_len);
/* all same size with black outline */
immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
@@ -315,8 +315,8 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
*/
float y = (float) CHANNEL_FIRST;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 164565192fd..ebdf5342172 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -80,7 +80,7 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid
int x = (frame - sfra) * framelen;
if (width == 1) {
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2i(pos, x, 0);
immVertex2i(pos, x, height * UI_DPI_FAC);
immEnd();
@@ -167,7 +167,7 @@ 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);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* track */
@@ -248,7 +248,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* solver keyframes */
@@ -290,7 +290,7 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx
{
int x, y;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* find window pixel coordinates of origin */
@@ -349,18 +349,18 @@ 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) {
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* Exclusive OR allows to get orig value when second operand is 0,
* and negative of orig value when second operand is 1. */
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_XOR);
- gpuPushMatrix();
- gpuTranslate2f(x, y);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
- gpuScale2f(zoomx, zoomy);
- gpuMultMatrix(sc->stabmat);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -377,7 +377,7 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
glDisable(GL_COLOR_LOGIC_OP);
}
@@ -452,7 +452,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
i++;
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -463,7 +463,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((b - a - 1) >= 1) {
GPU_point_size(5.0f);
- immBegin(GWN_PRIM_POINTS, b - a - 1);
+ immBegin(GPU_PRIM_POINTS, b - a - 1);
for (i = a; i < b; i++) {
if (i != curindex) {
@@ -478,7 +478,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((b - a) >= 2) {
GPU_line_width(3.0f);
- immBegin(GWN_PRIM_LINE_STRIP, b - a);
+ immBegin(GPU_PRIM_LINE_STRIP, b - a);
for (i = a; i < b; i++) {
immVertex2f(pos, path[i][0], path[i][1]);
@@ -494,7 +494,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((curindex - a) >= 1) {
immUniformThemeColor(TH_PATH_BEFORE);
- immBegin(GWN_PRIM_POINTS, curindex - a);
+ immBegin(GPU_PRIM_POINTS, curindex - a);
for (i = a; i < curindex; i++) {
immVertex2f(pos, path[i][0], path[i][1]);
@@ -506,7 +506,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((b - curindex - 1) >= 1) {
immUniformThemeColor(TH_PATH_AFTER);
- immBegin(GWN_PRIM_POINTS, b - curindex - 1);
+ immBegin(GPU_PRIM_POINTS, b - curindex - 1);
for (i = curindex + 1; i < b; i++) {
immVertex2f(pos, path[i][0], path[i][1]);
@@ -521,7 +521,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((curindex - a + 1) >= 2) {
immUniformThemeColor(TH_PATH_BEFORE);
- immBegin(GWN_PRIM_LINE_STRIP, curindex - a + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, curindex - a + 1);
for (i = a; i <= curindex; i++) {
immVertex2f(pos, path[i][0], path[i][1]);
@@ -533,7 +533,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
if ((b - curindex) >= 2) {
immUniformThemeColor(TH_PATH_AFTER);
- immBegin(GWN_PRIM_LINE_STRIP, b - curindex);
+ immBegin(GPU_PRIM_LINE_STRIP, b - curindex);
for (i = curindex; i < b; i++) {
immVertex2f(pos, path[i][0], path[i][1]);
@@ -579,12 +579,12 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
{
GPU_point_size(tiny ? 3.0f : 4.0f);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(position, pos[0], pos[1]);
immEnd();
}
else {
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(position, pos[0] + px[0] * 2, pos[1]);
immVertex2f(position, pos[0] + px[0] * 8, pos[1]);
@@ -603,11 +603,11 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
}
/* pattern and search outline */
- gpuPushMatrix();
- gpuTranslate2fv(marker_pos);
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2fv(position, marker->pattern_corners[0]);
immVertex2fv(position, marker->pattern_corners[1]);
immVertex2fv(position, marker->pattern_corners[2]);
@@ -625,7 +625,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
marker->search_max[1]);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
@@ -705,14 +705,14 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
immUniform1f("dash_factor", 2.0f); /* Solid "line" */
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(shdr_pos, pos[0], pos[1]);
immEnd();
}
else {
immUniform1f("dash_factor", 2.0f); /* Solid line */
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, pos[0] + px[0] * 3, pos[1]);
immVertex2f(shdr_pos, pos[0] + px[0] * 7, pos[1]);
@@ -735,7 +735,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_XOR);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(shdr_pos, pos);
immVertex2fv(shdr_pos, marker_pos);
immEnd();
@@ -745,8 +745,8 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
/* pattern */
- gpuPushMatrix();
- gpuTranslate2fv(marker_pos);
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
if (track->flag & TRACK_LOCKED) {
if (act) {
@@ -783,7 +783,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2fv(shdr_pos, marker->pattern_corners[0]);
immVertex2fv(shdr_pos, marker->pattern_corners[1]);
immVertex2fv(shdr_pos, marker->pattern_corners[2]);
@@ -800,12 +800,12 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
marker->search_max[0], marker->search_max[1]);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
/* Restore default shader */
immUnbindProgram();
- const uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
BLI_assert(pos == shdr_pos);
UNUSED_VARS_NDEBUG(pos);
@@ -857,7 +857,7 @@ static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int
tdy += px[1];
}
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
immVertex2f(pos, x, y);
immVertex2f(pos, x - tdx, y);
immVertex2f(pos, x, y + tdy);
@@ -884,8 +884,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
immUniformThemeColor(TH_MARKER_OUTLINE);
}
- gpuPushMatrix();
- gpuTranslate2fv(marker_pos);
+ GPU_matrix_push();
+ GPU_matrix_translate_2fv(marker_pos);
dx = 6.0f / width / sc->zoom;
dy = 6.0f / height / sc->zoom;
@@ -935,7 +935,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
GPU_line_width(outline ? 3.0f : 1.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, 0.0f, 0.0f);
immVertex2fv(pos, tilt_ctrl);
immEnd();
@@ -944,7 +944,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
@@ -1141,18 +1141,18 @@ 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);
- gpuPushMatrix();
- gpuMultMatrix(gl_matrix);
+ GPU_matrix_push();
+ GPU_matrix_mul(gl_matrix);
- Gwn_VertFormat *imm_format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *imm_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity);
immUniform1i("image", 0);
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texCoord, 0.0f, 0.0f);
immVertex2f(pos, 0.0f, 0.0f);
@@ -1170,7 +1170,7 @@ static void draw_plane_marker_image(Scene *scene,
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
glBindTexture(GL_TEXTURE_2D, 0);
@@ -1206,7 +1206,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
}
if (draw_plane_quad || is_selected_track) {
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -1239,7 +1239,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
}
/* Draw rectangle itself. */
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2fv(shdr_pos, plane_marker->corners[0]);
immVertex2fv(shdr_pos, plane_marker->corners[1]);
immVertex2fv(shdr_pos, plane_marker->corners[2]);
@@ -1252,7 +1252,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
immUniformColor3f(1.0f, 0.0f, 0.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
immVertex2fv(shdr_pos, plane_marker->corners[0]);
@@ -1262,7 +1262,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
immUniformColor3f(0.0f, 1.0f, 0.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
immVertex2fv(shdr_pos, plane_marker->corners[0]);
@@ -1342,13 +1342,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);
- gpuPushMatrix();
- gpuTranslate2f(x, y);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
- gpuPushMatrix();
- gpuScale2f(zoomx, zoomy);
- gpuMultMatrix(sc->stabmat);
- gpuScale2f(width, height);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
act_track = BKE_tracking_track_get_active(tracking);
@@ -1414,7 +1414,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
- uint position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint position = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1519,7 +1519,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
immUniformColor3f(1.0f, 0.0f, 0.0f);
}
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
if (undistort) {
immVertex2f(position, pos[0] / width, pos[1] / (height * aspy));
@@ -1539,7 +1539,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
if (sc->flag & SC_SHOW_NAMES) {
/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
@@ -1565,7 +1565,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
- gpuPopMatrix();
+ GPU_matrix_pop();
if (marker_pos)
MEM_freeN(marker_pos);
@@ -1592,13 +1592,13 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- gpuPushMatrix();
- gpuTranslate2f(x, y);
- gpuScale2f(zoomx, zoomy);
- gpuMultMatrix(sc->stabmat);
- gpuScale2f(width, height);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
- uint position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint position = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1675,7 +1675,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
immUniformColor3f(1.0f, 0.0f, 0.0f);
for (i = 0; i <= n; i++) {
- immBegin(GWN_PRIM_LINE_STRIP, n + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, n + 1);
for (j = 0; j <= n; j++) {
immVertex2fv(position, grid[i][j]);
@@ -1685,7 +1685,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
}
for (j = 0; j <= n; j++) {
- immBegin(GWN_PRIM_LINE_STRIP, n + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, n + 1);
for (i = 0; i <= n; i++) {
immVertex2fv(position, grid[i][j]);
@@ -1743,7 +1743,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
sub_v2_v2v2(dpos, npos, pos);
mul_v2_fl(dpos, 1.0f / steps);
- immBegin(GWN_PRIM_LINE_STRIP, steps + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, steps + 1);
for (j = 0; j <= steps; j++) {
BKE_tracking_distort_v2(tracking, pos, tpos);
@@ -1756,7 +1756,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
}
}
else if (stroke->totpoints == 1) {
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy);
immEnd();
}
@@ -1774,7 +1774,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
@@ -1871,8 +1871,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) {
- gpuPushMatrix();
- gpuMultMatrix(sc->unistabmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(sc->unistabmat);
if (is_track_source) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
@@ -1881,13 +1881,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);
- gpuTranslate2fv(marker->pos);
+ GPU_matrix_translate_2fv(marker->pos);
}
}
ED_gpencil_draw_2dimage(C);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
else {
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 34720b3a627..cc8541d9fd7 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -91,11 +91,11 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
immUniformColor4fv(col);
if (is_point) {
- immBeginAtMost(GWN_PRIM_POINTS, 1);
+ immBeginAtMost(GPU_PRIM_POINTS, 1);
}
else {
/* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GWN_PRIM_LINE_STRIP, track->markersnr);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
}
}
@@ -119,13 +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);
- gpuPushMatrix();
- gpuTranslate2f(scene_framenr, val);
- gpuScale2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(scene_framenr, val);
+ GPU_matrix_scale_2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
@@ -237,11 +237,11 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *
immUniformColor4fv(col);
if (is_point) { /* This probably never happens here, but just in case... */
- immBeginAtMost(GWN_PRIM_POINTS, 1);
+ immBeginAtMost(GPU_PRIM_POINTS, 1);
}
else {
/* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GWN_PRIM_LINE_STRIP, track->markersnr);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
}
}
}
@@ -300,7 +300,7 @@ static void draw_frame_curves(SpaceClip *sc, unsigned int pos)
}
if (!lines) {
- immBeginAtMost(GWN_PRIM_LINE_STRIP, reconstruction->camnr);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
lines = 1;
}
@@ -328,7 +328,7 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
UI_view2d_grid_free(grid);
if (clip) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_point_size(3.0f);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index c94853d4233..19d321a53bf 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -273,7 +273,7 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
@@ -287,7 +287,7 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
/* thin lines where the actual frames are */
GPU_line_width(1.0f);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 4ac9010d3b5..4f9fd9c65d7 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -236,7 +236,7 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
sc = MEM_callocN(sizeof(SpaceClip), "initclip");
sc->spacetype = SPACE_CLIP;
sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH |
- SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_FRAMES | SC_SHOW_GPENCIL;
+ SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_FRAMES | SC_SHOW_ANNOTATION;
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;
@@ -847,7 +847,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul
}
/* dropboxes */
-static bool clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
if (drag->type == WM_DRAG_PATH)
if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
@@ -1185,18 +1185,18 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
show_cursor |= sc->around == V3D_AROUND_CURSOR;
if (show_cursor) {
- gpuPushMatrix();
- gpuTranslate2f(x, y);
- gpuScale2f(zoomx, zoomy);
- gpuMultMatrix(sc->stabmat);
- gpuScale2f(width, height);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+ GPU_matrix_mul(sc->stabmat);
+ GPU_matrix_scale_2f(width, height);
ED_image_draw_cursor(ar, sc->cursor);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
clip_draw_cache_and_notes(C, sc, ar);
- if (sc->flag & SC_SHOW_GPENCIL) {
+ if (sc->flag & SC_SHOW_ANNOTATION) {
/* Grease Pencil */
clip_draw_grease_pencil((bContext *)C, true);
}
@@ -1204,7 +1204,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
- if (sc->flag & SC_SHOW_GPENCIL) {
+ if (sc->flag & SC_SHOW_ANNOTATION) {
/* draw Grease Pencil - screen space only */
clip_draw_grease_pencil((bContext *)C, false);
}
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 0ffbe451042..789194c21b9 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];
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_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_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 3a48d5ad7dd..3429d726349 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -170,31 +170,24 @@ static void console_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
/* ************* dropboxes ************* */
-static bool id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
-// SpaceConsole *sc = CTX_wm_space_console(C);
- if (drag->type == WM_DRAG_ID)
- return 1;
- return 0;
+ return WM_drag_ID(drag, 0) != NULL;
}
static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- char *text;
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
/* copy drag path to properties */
- text = RNA_path_full_ID_py(id);
+ char *text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
}
-static bool path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- // SpaceConsole *sc = CTX_wm_space_console(C);
- if (drag->type == WM_DRAG_PATH)
- return 1;
- return 0;
+ return (drag->type == WM_DRAG_PATH);
}
static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 42ad34b659b..4a71afbcf4a 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -402,8 +402,8 @@ static void file_draw_preview(
/* border */
if (use_dropshadow) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
@@ -466,7 +466,7 @@ static void draw_background(FileLayout *layout, View2D *v2d)
int i;
int sy;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, -7);
@@ -503,12 +503,12 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
v1[1] = v2d->cur.ymax - layout->tile_border_y;
v2[1] = v2d->cur.ymin;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, vertex_len);
+ immBegin(GPU_PRIM_LINES, vertex_len);
sx = (int)v2d->tot.xmin;
while (sx < v2d->cur.xmax) {
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 812a671ff33..cbf685e6ed8 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -43,6 +43,7 @@
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "ED_fileselect.h"
@@ -71,25 +72,33 @@ static void file_panel_operator_header(const bContext *C, Panel *pa)
BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
}
-static bool file_panel_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
-{
- const char *prop_id = RNA_property_identifier(prop);
- return !(STREQ(prop_id, "filepath") ||
- STREQ(prop_id, "directory") ||
- STREQ(prop_id, "filename")
- );
-}
-
static void file_panel_operator(const bContext *C, Panel *pa)
{
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
- // int empty = 1, flag;
UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
- uiTemplateOperatorPropertyButs(C, pa->layout, op, file_panel_check_prop, UI_BUT_LABEL_ALIGN_NONE,
- UI_TEMPLATE_OP_PROPS_SHOW_EMPTY);
+ /* Hack: temporary hide.*/
+ const char *hide[] = {"filepath", "files", "directory", "filename"};
+ for (int i = 0; i < ARRAY_SIZE(hide); i++) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
+ if (prop) {
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+
+ uiTemplateOperatorPropertyButs(
+ C, pa->layout, op, UI_BUT_LABEL_ALIGN_NONE,
+ UI_TEMPLATE_OP_PROPS_SHOW_EMPTY);
+
+ /* Hack: temporary hide.*/
+ for (int i = 0; i < ARRAY_SIZE(hide); i++) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, hide[i]);
+ if (prop) {
+ RNA_def_property_clear_flag(prop, PROP_HIDDEN);
+ }
+ }
UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 116cd700cc0..cb21659dbb8 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -720,7 +720,7 @@ static void file_ui_region_listener(
}
}
-static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
+static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
if (drag->type == WM_DRAG_PATH) {
SpaceFile *sfile = CTX_wm_space_file(C);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 16658c0d8db..ad9af8cb948 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -86,7 +86,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
int i;
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_line_width(1.0f);
@@ -103,7 +103,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
/* draw two black lines showing the standard reference levels */
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min);
immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min);
@@ -122,7 +122,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
/* for now, point color is fixed, and is white */
immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBeginAtMost(GWN_PRIM_POINTS, env->totvert * 2);
+ immBeginAtMost(GPU_PRIM_POINTS, env->totvert * 2);
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
/* only draw if visible
@@ -178,7 +178,7 @@ static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, boo
set_fcurve_vertex_color(fcu, sel);
- immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert);
+ immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert);
BezTriple *bezt = fcu->bezt;
for (int i = 0; i < fcu->totvert; i++, bezt++) {
@@ -230,7 +230,7 @@ static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool
immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */
- immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert * 2);
+ immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert * 2);
BezTriple *bezt = fcu->bezt;
BezTriple *prevbezt = NULL;
@@ -286,7 +286,7 @@ static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool
* - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
*/
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_blend(true);
GPU_enable_program_point_size();
@@ -330,12 +330,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
{
int sel, b;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBeginAtMost(GWN_PRIM_LINES, 4 * 2 * fcu->totvert);
+ immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert);
/* slightly hacky, but we want to draw unselected points before selected ones
* so that selected points are clearly visible
@@ -422,12 +422,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
{
/* adjust view transform before starting */
- gpuPushMatrix();
- gpuTranslate2f(x, y);
- gpuScale2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
/* draw X shape */
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, -0.7f, -0.7f);
immVertex2f(pos, +0.7f, +0.7f);
@@ -436,7 +436,7 @@ static void draw_fcurve_sample_control(float x, float y, float xscale, float ysc
immEnd();
/* restore view transform */
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* helper func - draw keyframe vertices only for an F-Curve */
@@ -459,7 +459,7 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(true);
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT);
@@ -551,7 +551,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
n = (etime - stime) / samplefreq + 0.5f;
if (n > 0) {
- immBegin(GWN_PRIM_LINE_STRIP, (n + 1));
+ immBegin(GPU_PRIM_LINE_STRIP, (n + 1));
for (i = 0; i <= n; i++) {
float ctime = stime + i * samplefreq;
@@ -585,12 +585,12 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
}
/* apply unit mapping */
- gpuPushMatrix();
+ GPU_matrix_push();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- gpuScale2f(1.0f, unit_scale);
- gpuTranslate2f(0.0f, offset);
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
- immBegin(GWN_PRIM_LINE_STRIP, count);
+ immBegin(GPU_PRIM_LINE_STRIP, count);
/* extrapolate to left? - left-side of view comes before first keyframe? */
if (prevfpt->vec[0] > v2d->cur.xmin) {
@@ -645,7 +645,7 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
immEnd();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* helper func - check if the F-Curve only contains easily drawable segments
@@ -679,15 +679,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 */
- gpuPushMatrix();
+ GPU_matrix_push();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- gpuScale2f(1.0f, unit_scale);
- gpuTranslate2f(0.0f, offset);
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
/* 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(GWN_PRIM_LINE_STRIP, (b * 32 + 3));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
/* extrapolate to left? */
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
@@ -827,7 +827,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
immEnd();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* Debugging -------------------------------- */
@@ -849,7 +849,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
// return;
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
@@ -874,7 +874,7 @@ 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
*/
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
t = v2d->cur.xmin;
immVertex2f(shdr_pos, t, (t + offset) * unitfac);
@@ -900,7 +900,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immUniform1f("dash_width", 10.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
+ immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
/* x-axis lookup */
co[0] = x;
@@ -926,7 +926,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immUnbindProgram();
- /* GWN_PRIM_POINTS do not survive dashed line geometry shader... */
+ /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* x marks the spot .................................................... */
@@ -934,7 +934,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immUniformColor3f(0.9f, 0.9f, 0.9f);
GPU_point_size(7.0);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(shdr_pos, x, y);
immEnd();
@@ -942,7 +942,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immUniformColor3f(0.9f, 0.0f, 0.0f);
GPU_point_size(3.0);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(shdr_pos, x, y);
immEnd();
}
@@ -969,7 +969,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
}
GPU_blend(true);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -1055,7 +1055,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
}
GPU_blend(true);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -1136,9 +1136,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 */
- gpuPushMatrix();
- gpuScale2f(1.0f, unit_scale);
- gpuTranslate2f(0.0f, offset);
+ GPU_matrix_push();
+ GPU_matrix_scale_2f(1.0f, unit_scale);
+ GPU_matrix_translate_2f(0.0f, offset);
/* set this once and for all - all handles and handle-verts should use the same thickness */
GPU_line_width(1.0);
@@ -1160,7 +1160,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
draw_fcurve_samples(sipo, ar, fcu);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 699dc29ff47..fa57df0393a 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -279,7 +279,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_grid_free(grid);
if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) {
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -292,7 +292,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
GPU_blend(true);
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, v2d->cur.xmin, y);
immVertex2f(pos, v2d->cur.xmax, y);
immEnd();
@@ -310,7 +310,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
GPU_blend(true);
GPU_line_width(2.0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, v2d->cur.ymin);
immVertex2f(pos, x, v2d->cur.ymax);
immEnd();
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 1d8c6721b64..afcae7a27ab 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -876,7 +876,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
if (!compact) {
uiTemplateID(
layout, C, ptr, propname,
- ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
}
if (ima) {
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 24b02106021..4cbe25462af 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -117,17 +117,17 @@ static void draw_render_info(const bContext *C,
int x, y;
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- gpuPushMatrix();
- gpuTranslate2f(x, y);
- gpuScale2f(zoomx, zoomy);
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
if (rd->mode & R_BORDER) {
/* TODO: round or floor instead of casting to int */
- gpuTranslate2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
+ GPU_matrix_translate_2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
(int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f));
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_FACE_SELECT);
@@ -144,7 +144,7 @@ static void draw_render_info(const bContext *C,
MEM_freeN(tiles);
}
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
}
@@ -174,7 +174,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* noisy, high contrast make impossible to read if lower alpha is used. */
@@ -330,7 +330,7 @@ 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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (channels == 4) {
@@ -367,7 +367,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
immUnbindProgram();
/* draw outline */
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ub(128, 128, 128);
imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
@@ -573,8 +573,8 @@ void draw_image_sample_line(SpaceImage *sima)
if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) {
Histogram *hist = &sima->sample_line_hist;
- Gwn_VertFormat *format = immVertexFormat();
- uint shdr_dashed_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint shdr_dashed_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -586,7 +586,7 @@ void draw_image_sample_line(SpaceImage *sima)
immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
immUniform1f("dash_width", 2.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(shdr_dashed_pos, hist->co[0]);
immVertex2fv(shdr_dashed_pos, hist->co[1]);
immEnd();
@@ -779,7 +779,7 @@ void draw_image_cache(const bContext *C, ARegion *ar)
/* Draw current frame. */
x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_CFRAME);
immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 29d63493a3c..be91f7abf99 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1410,7 +1410,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
return OPERATOR_RUNNING_MODAL;
}
-static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
@@ -1429,7 +1429,7 @@ static void image_open_draw(bContext *UNUSED(C), wmOperator *op)
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
@@ -2124,7 +2124,7 @@ static void image_save_as_cancel(bContext *UNUSED(C), wmOperator *op)
image_save_as_free(op);
}
-static bool image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop, void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
@@ -2149,7 +2149,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
/* multiview template */
if (is_multiview)
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 68b0f42768a..69bedf7c442 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -387,7 +387,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
}
/* dropboxes */
-static bool image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
if (drag->type == WM_DRAG_PATH)
if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
@@ -581,25 +581,25 @@ static int image_context(const bContext *C, const char *member, bContextDataResu
return 0;
}
-static void IMAGE_WGT_gizmo2d(wmGizmoGroupType *wgt)
+static void IMAGE_GGT_gizmo2d(wmGizmoGroupType *gzgt)
{
- wgt->name = "UV Transform Gizmo";
- wgt->idname = "IMAGE_WGT_gizmo2d";
+ gzgt->name = "UV Transform Gizmo";
+ gzgt->idname = "IMAGE_GGT_gizmo2d";
- wgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- wgt->poll = ED_widgetgroup_gizmo2d_poll;
- wgt->setup = ED_widgetgroup_gizmo2d_setup;
- wgt->refresh = ED_widgetgroup_gizmo2d_refresh;
- wgt->draw_prepare = ED_widgetgroup_gizmo2d_draw_prepare;
+ gzgt->poll = ED_widgetgroup_gizmo2d_poll;
+ gzgt->setup = ED_widgetgroup_gizmo2d_setup;
+ gzgt->refresh = ED_widgetgroup_gizmo2d_refresh;
+ gzgt->draw_prepare = ED_widgetgroup_gizmo2d_draw_prepare;
}
static void image_widgets(void)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
&(const struct wmGizmoMapType_Params){SPACE_IMAGE, RGN_TYPE_WINDOW});
- WM_gizmogrouptype_append_and_link(mmap_type, IMAGE_WGT_gizmo2d);
+ WM_gizmogrouptype_append_and_link(gzmap_type, IMAGE_GGT_gizmo2d);
}
/************************** main region ***************************/
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 3830e6d2792..fdf9d6df374 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -32,6 +32,7 @@
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
@@ -55,6 +56,7 @@
#include "BKE_particle.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
+#include "BKE_gpencil.h"
#include "ED_info.h"
#include "ED_armature.h"
@@ -72,6 +74,7 @@ typedef struct SceneStats {
int totobj, totobjsel;
int totlamp, totlampsel;
int tottri;
+ int totgplayer, totgpframe, totgpstroke, totgppoint;
char infostr[MAX_INFO_LEN];
} SceneStats;
@@ -85,6 +88,8 @@ typedef struct SceneStatsFmt {
char totobj[MAX_INFO_NUM_LEN], totobjsel[MAX_INFO_NUM_LEN];
char totlamp[MAX_INFO_NUM_LEN], totlampsel[MAX_INFO_NUM_LEN];
char tottri[MAX_INFO_NUM_LEN];
+ char totgplayer[MAX_INFO_NUM_LEN], totgpframe[MAX_INFO_NUM_LEN];
+ char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN];
} SceneStatsFmt;
static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
@@ -127,8 +132,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
int totv = 0, totf = 0, tottri = 0;
- if (ob->curve_cache && ob->curve_cache->disp.first)
- BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri);
+ if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first)
+ BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri);
totv *= totob;
totf *= totob;
@@ -144,6 +149,20 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
}
break;
}
+ case OB_GPENCIL:
+ {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* GPXX Review if we can move to other place when object change
+ * maybe to depsgraph evaluation
+ */
+ BKE_gpencil_stats_update(gpd);
+
+ stats->totgplayer = gpd->totlayer;
+ stats->totgpframe = gpd->totframe;
+ stats->totgpstroke = gpd->totstroke;
+ stats->totgppoint = gpd->totpoint;
+ break;
+ }
}
}
@@ -442,6 +461,11 @@ static void stats_string(ViewLayer *view_layer)
SCENE_STATS_FMT_INT(tottri);
+ SCENE_STATS_FMT_INT(totgplayer);
+ SCENE_STATS_FMT_INT(totgpframe);
+ SCENE_STATS_FMT_INT(totgpstroke);
+ SCENE_STATS_FMT_INT(totgppoint);
+
#undef SCENE_STATS_FMT_INT
@@ -501,6 +525,14 @@ static void stats_string(ViewLayer *view_layer)
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"),
stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
}
+ else if ((ob) && (ob->type == OB_GPENCIL)) {
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
+ IFACE_("Layers:%s | Frames:%s | Strokes:%s | Points:%s"),
+ stats_fmt.totgplayer, stats_fmt.totgpframe, stats_fmt.totgpstroke, stats_fmt.totgppoint);
+
+ ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
+ ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
+ }
else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
stats_fmt.tottri, gpumemstr);
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 5c1b23e140c..c94aaf6e861 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -85,8 +85,8 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2],
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(bg_sel);
@@ -191,8 +191,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
cdc->sel[1] = str_len - sel_orig[0];
if (bg) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv(bg);
@@ -242,8 +242,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
else { /* simple, no wrap */
if (bg) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv(bg);
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 57464cbf092..40caf919848 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -145,6 +145,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE:
{
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
@@ -287,7 +288,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
row = uiLayoutRow(layout, true);
uiTemplateID(
row, (bContext *)C, &adt_ptr, "action",
- "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL);
+ "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL, false);
/* extrapolation */
row = uiLayoutRow(layout, true);
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 3368ad4fe8d..51177a77f0d 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -182,6 +182,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE:
{
/* sanity checking... */
if (ale->adt) {
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 5b68c7b6bb7..7dd8c7f2eed 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -120,8 +120,8 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, floa
nla_action_get_color(adt, act, color);
color[3] *= 2.5f;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -142,13 +142,13 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, floa
if (key_len > 0) {
format = immVertexFormat();
- pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
- uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_enable_program_point_size();
- immBegin(GWN_PRIM_POINTS, key_len);
+ immBegin(GPU_PRIM_POINTS, key_len);
/* - disregard the selection status of keyframes so they draw a certain way
* - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
@@ -177,7 +177,7 @@ static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymax
if (ELEM(NULL, act, act->markers.first))
return;
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (dashed) {
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -194,7 +194,7 @@ static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymax
}
immUniformThemeColorShade(TH_STRIP_SELECT, shade);
- immBeginAtMost(GWN_PRIM_LINES, BLI_listbase_count(&act->markers) * 2);
+ immBeginAtMost(GPU_PRIM_LINES, BLI_listbase_count(&act->markers) * 2);
for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
@@ -318,7 +318,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
/* plot the curve (over the strip's main region) */
if (fcu) {
- immBegin(GWN_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
+ immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
/* sample at 1 frame intervals, and draw
* - min y-val is yminc, max is y-maxc, so clamp in those regions
@@ -335,7 +335,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
else {
/* use blend in/out values only if both aren't zero */
if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
- immBeginAtMost(GWN_PRIM_LINE_STRIP, 4);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, 4);
/* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
if (IS_EQF(strip->blendin, 0.0f) == 0) {
@@ -366,7 +366,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
static uint nla_draw_use_dashed_outlines(float color[4], bool muted)
{
/* Note that we use dashed shader here, and make it draw solid lines if not muted... */
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
@@ -403,7 +403,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* get color of strip */
nla_strip_get_color_inside(adt, strip, color);
- shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* draw extrapolation info first (as backdrop)
@@ -456,7 +456,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
/* restore current vertex format & program (roundbox trashes it) */
- shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
}
else {
@@ -518,7 +518,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* only draw lines for whole-numbered repeats, starting from the first full-repeat
* up to the last full repeat (but not if it lies on the end of the strip)
*/
- immBeginAtMost(GWN_PRIM_LINES, 2 * floorf(strip->repeat));
+ immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat));
for (int i = 1; i < strip->repeat; i++) {
float repeatPos = strip->start + (repeatLen * i);
@@ -534,7 +534,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
const float y = (ymaxc - yminc) * 0.5f + yminc;
- immBeginAtMost(GWN_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */
+ immBeginAtMost(GPU_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */
/* only draw first-level of child-strips, but don't draw any lines on the endpoints */
for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) {
@@ -706,7 +706,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
AnimData *adt = ale->adt;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
@@ -729,7 +729,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* white base-lines */
GPU_line_width(2.0f);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
@@ -739,7 +739,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* black top-lines */
GPU_line_width(1.0f);
immUniformColor3f(0.0f, 0.0f, 0.0f);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 97b112ebbd1..4dfbb92971b 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -744,7 +744,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -775,7 +775,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(
layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
@@ -793,7 +793,7 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(
layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!ima)
return;
@@ -1025,6 +1025,11 @@ static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), Pointer
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
}
+static void node_shader_buts_principled_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "parametrization", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -1207,6 +1212,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BSDF_HAIR:
ntype->draw_buttons = node_shader_buts_hair;
break;
+ case SH_NODE_BSDF_HAIR_PRINCIPLED:
+ ntype->draw_buttons = node_shader_buts_principled_hair;
+ break;
case SH_NODE_SCRIPT:
ntype->draw_buttons = node_shader_buts_script;
ntype->draw_buttons_ex = node_shader_buts_script_ex;
@@ -1266,7 +1274,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(
layout, C, ptr, "image",
- "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!node->id) return;
imaptr = RNA_pointer_get(ptr, "image");
@@ -1296,7 +1304,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer
const char *layer_name;
char scene_name[MAX_ID_NAME - 2];
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!node->id) return;
@@ -1410,7 +1418,7 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
- uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
@@ -1977,7 +1985,7 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
}
static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1985,7 +1993,7 @@ static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, Point
bNode *node = ptr->data;
PointerRNA clipptr;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!node->id)
return;
@@ -1999,7 +2007,7 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!node->id)
return;
@@ -2023,7 +2031,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (!node->id)
return;
@@ -2184,14 +2192,14 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo
const float cy = y + snode->zoom * backdropHeight * node->custom4;
const float cross_size = 12 * U.pixelsize;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, cx - cross_size, cy - cross_size);
immVertex2f(pos, cx + cross_size, cy + cross_size);
immVertex2f(pos, cx + cross_size, cy - cross_size);
@@ -2229,14 +2237,14 @@ 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;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x3, y3);
@@ -2273,14 +2281,14 @@ 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;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x3, y3);
@@ -2331,7 +2339,7 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
@@ -2353,7 +2361,7 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (node->id) {
MovieClip *clip = (MovieClip *) node->id;
@@ -2389,7 +2397,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
{
bNode *node = ptr->data;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (node->id) {
MovieClip *clip = (MovieClip *) node->id;
@@ -2429,7 +2437,7 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
bNode *node = ptr->data;
NodePlaneTrackDeformData *data = node->storage;
- uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
if (node->id) {
MovieClip *clip = (MovieClip *) node->id;
@@ -2473,6 +2481,25 @@ static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
+static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *col = uiLayoutColumn(layout, true);
+
+ uiItemL(col, IFACE_("Matte Objects:"), ICON_NONE);
+
+ uiLayout *row = uiLayoutRow(col, true);
+ uiTemplateCryptoPicker(row, ptr, "add");
+ uiTemplateCryptoPicker(row, ptr, "remove");
+
+ uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE);
+}
+
+static void node_composit_buts_cryptomatte_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+{
+ uiItemO(layout, IFACE_("Add Crypto Layer"), ICON_ZOOMIN, "NODE_OT_cryptomatte_layer_add");
+ uiItemO(layout, IFACE_("Remove Crypto Layer"), ICON_ZOOMOUT, "NODE_OT_cryptomatte_layer_remove");
+}
+
static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE);
@@ -2705,6 +2732,10 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_SUNBEAMS:
ntype->draw_buttons = node_composit_buts_sunbeams;
break;
+ case CMP_NODE_CRYPTOMATTE:
+ ntype->draw_buttons = node_composit_buts_cryptomatte;
+ ntype->draw_buttons_ex = node_composit_buts_cryptomatte_ex;
+ break;
case CMP_NODE_BRIGHTCONTRAST:
ntype->draw_buttons = node_composit_buts_brightcontrast;
}
@@ -2807,7 +2838,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL);
+ uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
}
static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -3193,8 +3224,8 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
if (ibuf) {
float x, y;
- gpuPushProjectionMatrix();
- gpuPushMatrix();
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
/* somehow the offset has to be calculated inverse */
wmOrtho2_region_pixelspace(ar);
@@ -3267,7 +3298,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
y + snode->zoom * viewer_border->ymin * ibuf->y,
y + snode->zoom * viewer_border->ymax * ibuf->y);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_ACTIVE);
@@ -3277,8 +3308,8 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
}
- gpuPopProjectionMatrix();
- gpuPopMatrix();
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
}
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -3322,7 +3353,16 @@ static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *l
}
/* may be called outside of drawing (so pass spacetype) */
- dist = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE) * 0.10f * fabsf(vec[0][0] - vec[3][0]);
+ int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE);
+
+ if (curving == 0) {
+ /* Straight line: align all points. */
+ mid_v2_v2v2(vec[1], vec[0], vec[3]);
+ mid_v2_v2v2(vec[2], vec[1], vec[3]);
+ return 1;
+ }
+
+ dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]);
deltax = vec[3][0] - vec[0][0];
deltay = vec[3][1] - vec[0][1];
/* check direction later, for top sockets */
@@ -3391,51 +3431,51 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
-struct {
- Gwn_Batch *batch; /* for batching line together */
- Gwn_Batch *batch_single; /* for single line */
- Gwn_VertBuf *inst_vbo;
+static struct {
+ GPUBatch *batch; /* for batching line together */
+ GPUBatch *batch_single; /* for single line */
+ GPUVertBuf *inst_vbo;
unsigned int p0_id, p1_id, p2_id, p3_id;
unsigned int colid_id;
- Gwn_VertBufRaw p0_step, p1_step, p2_step, p3_step;
- Gwn_VertBufRaw colid_step;
+ GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
+ GPUVertBufRaw colid_step;
unsigned int count;
bool enabled;
} g_batch_link = {0};
static void nodelink_batch_reset(void)
{
- GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
- GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
- GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
- GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
- GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
g_batch_link.count = 0;
}
static void set_nodelink_vertex(
- Gwn_VertBuf *vbo,
+ GPUVertBuf *vbo,
unsigned int uv_id, unsigned int pos_id, unsigned int exp_id, unsigned int v,
const unsigned char uv[2], const float pos[2], const float exp[2])
{
- GWN_vertbuf_attr_set(vbo, uv_id, v, uv);
- GWN_vertbuf_attr_set(vbo, pos_id, v, pos);
- GWN_vertbuf_attr_set(vbo, exp_id, v, exp);
+ GPU_vertbuf_attr_set(vbo, uv_id, v, uv);
+ GPU_vertbuf_attr_set(vbo, pos_id, v, pos);
+ GPU_vertbuf_attr_set(vbo, exp_id, v, exp);
}
static void nodelink_batch_init(void)
{
- Gwn_VertFormat format = {0};
- uint uv_id = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
- uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint expand_id = GWN_vertformat_attr_add(&format, "expand", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ GPUVertFormat format = {0};
+ uint uv_id = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_U8, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint expand_id = GPU_vertformat_attr_add(&format, "expand", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
int vcount = LINK_RESOL * 2; /* curve */
vcount += 2; /* restart strip */
vcount += 3 * 2; /* arrow */
vcount *= 2; /* shadow */
vcount += 2; /* restart strip */
- GWN_vertbuf_data_alloc(vbo, vcount);
+ GPU_vertbuf_data_alloc(vbo, vcount);
int v = 0;
for (int k = 0; k < 2; ++k) {
@@ -3479,23 +3519,23 @@ static void nodelink_batch_init(void)
set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
}
- g_batch_link.batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ g_batch_link.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(g_batch_link.batch);
- g_batch_link.batch_single = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, 0);
+ g_batch_link.batch_single = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, 0);
gpu_batch_presets_register(g_batch_link.batch_single);
/* Instances data */
- Gwn_VertFormat format_inst = {0};
- g_batch_link.p0_id = GWN_vertformat_attr_add(&format_inst, "P0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- g_batch_link.p1_id = GWN_vertformat_attr_add(&format_inst, "P1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- g_batch_link.p2_id = GWN_vertformat_attr_add(&format_inst, "P2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- g_batch_link.p3_id = GWN_vertformat_attr_add(&format_inst, "P3", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- g_batch_link.colid_id = GWN_vertformat_attr_add(&format_inst, "colid_doarrow", GWN_COMP_U8, 4, GWN_FETCH_INT);
- g_batch_link.inst_vbo = GWN_vertbuf_create_with_format_ex(&format_inst, GWN_USAGE_STREAM);
- GWN_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */
+ GPUVertFormat format_inst = {0};
+ g_batch_link.p0_id = GPU_vertformat_attr_add(&format_inst, "P0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p1_id = GPU_vertformat_attr_add(&format_inst, "P1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p2_id = GPU_vertformat_attr_add(&format_inst, "P2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.p3_id = GPU_vertformat_attr_add(&format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_batch_link.colid_id = GPU_vertformat_attr_add(&format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
+ GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */
- GWN_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
+ GPU_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
nodelink_batch_reset();
}
@@ -3526,14 +3566,14 @@ static void nodelink_batch_draw(SpaceNode *snode)
UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]);
- GWN_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count);
- GWN_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
+ GPU_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count);
+ GPU_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
- GWN_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
- GWN_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
- GWN_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
- GWN_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
- GWN_batch_draw(g_batch_link.batch);
+ GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
+ GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
+ GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
+ GPU_batch_draw(g_batch_link.batch);
nodelink_batch_reset();
@@ -3562,11 +3602,11 @@ static void nodelink_batch_add_link(
BLI_assert(ELEM(th_col3, TH_WIRE, -1));
g_batch_link.count++;
- copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p0_step), p0);
- copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p1_step), p1);
- copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p2_step), p2);
- copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p3_step), p3);
- char *colid = GWN_vertbuf_raw_step(&g_batch_link.colid_step);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2);
+ copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3);
+ char *colid = GPU_vertbuf_raw_step(&g_batch_link.colid_step);
colid[0] = nodelink_get_color_id(th_col1);
colid[1] = nodelink_get_color_id(th_col2);
colid[2] = nodelink_get_color_id(th_col3);
@@ -3604,14 +3644,14 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
UI_GetThemeColor4fv(th_col1, colors[1]);
UI_GetThemeColor4fv(th_col2, colors[2]);
- Gwn_Batch *batch = g_batch_link.batch_single;
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
- GWN_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
- GWN_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
- GWN_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
- GWN_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
- GWN_batch_uniform_1i(batch, "doArrow", drawarrow);
- GWN_batch_draw(batch);
+ GPUBatch *batch = g_batch_link.batch_single;
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
+ GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
+ GPU_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
+ GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
+ GPU_batch_uniform_1i(batch, "doArrow", drawarrow);
+ GPU_batch_draw(batch);
}
}
}
@@ -3660,7 +3700,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
{
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
if (border & (NODE_LEFT | NODE_RIGHT)) {
immVertex2f(pos, cent[0], v2d->cur.ymin);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index c632b354440..bba46771674 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -648,8 +648,8 @@ static void node_draw_preview_background(float tile, rctf *rect)
{
float x, y;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -721,7 +721,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
GPU_blend(false);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
@@ -771,9 +771,9 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
float scale;
UI_view2d_scale_get(v2d, &scale, NULL);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
GPU_blend(true);
GPU_enable_program_point_size();
@@ -788,7 +788,7 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
immUniform1f("outlineWidth", 1.0f);
immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
- immBeginAtMost(GWN_PRIM_POINTS, total_input_len + total_output_len);
+ immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
}
/* socket inputs */
@@ -832,7 +832,7 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
immUniform1f("outlineWidth", 1.5f);
- immBegin(GWN_PRIM_POINTS, selected_input_len + selected_output_len);
+ immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
if (selected_input_len) {
/* socket inputs */
@@ -951,18 +951,18 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* open/close entirely? */
{
uiBut *but;
- int but_size = UI_UNIT_X * 0.6f;
+ int but_size = UI_UNIT_X * 1.2f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
- rct->xmin + 0.5f * U.widget_unit - but_size / 2, rct->ymax - NODE_DY / 2.0f - but_size / 2,
+ rct->xmin + 0.6f * U.widget_unit - but_size / 2, rct->ymax - NODE_DY / 2.2f - but_size / 2,
but_size, but_size, NULL, 0, 0, 0, 0, "");
UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_hide_toggle");
UI_block_emboss_set(node->block, UI_EMBOSS);
UI_GetThemeColor4fv(TH_TEXT, color);
/* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color);
+ UI_draw_icon_tri(rct->xmin + 0.6f * U.widget_unit, rct->ymax - NODE_DY / 2.2f, 'v', color);
}
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -1071,7 +1071,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* open entirely icon */
{
uiBut *but;
- int but_size = UI_UNIT_X * 0.6f;
+ int but_size = UI_UNIT_X * 1.2f;
/* XXX button uses a custom triangle draw below, so make it invisible without icon */
UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
but = uiDefBut(node->block, UI_BTYPE_BUT_TOGGLE, B_REDR, "",
@@ -1102,13 +1102,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
/* scale widget thing */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(color_id, -10);
dx = 10.0f;
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
@@ -1119,7 +1119,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
immUniformThemeColorShade(color_id, 30);
dx -= snode->aspect;
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
@@ -1405,17 +1405,17 @@ void drawnodespace(const bContext *C, ARegion *ar)
{
float original_proj[4][4];
- gpuGetProjectionMatrix(original_proj);
+ GPU_matrix_projection_get(original_proj);
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
wmOrtho2_pixelspace(ar->winx, ar->winy);
WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
- gpuPopMatrix();
- gpuLoadProjectionMatrix(original_proj);
+ GPU_matrix_pop();
+ GPU_matrix_projection_set(original_proj);
}
draw_nodetree(C, ar, ntree, path->parent_key);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 1a6710035c2..edab76cd7e1 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2548,3 +2548,93 @@ void NODE_OT_clear_viewer_border(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/* ****************** Cryptomatte Add Socket ******************* */
+
+static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
+
+ if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ntreeCompositCryptomatteAddSocket(ntree, node);
+
+ snode_notify(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Cryptomatte Socket";
+ ot->description = "Add a new input layer to a Cryptomatte node";
+ ot->idname = "NODE_OT_cryptomatte_layer_add";
+
+ /* callbacks */
+ ot->exec = node_cryptomatte_add_socket_exec;
+ ot->poll = composite_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ****************** Cryptomatte Remove Socket ******************* */
+
+static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ PointerRNA ptr = CTX_data_pointer_get(C, "node");
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+
+ if (ptr.data) {
+ node = ptr.data;
+ ntree = ptr.id.data;
+ }
+ else if (snode && snode->edittree) {
+ ntree = snode->edittree;
+ node = nodeGetActive(snode->edittree);
+ }
+
+ if (!node || node->type != CMP_NODE_CRYPTOMATTE) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!ntreeCompositCryptomatteRemoveSocket(ntree, node)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ snode_notify(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Cryptomatte Socket";
+ ot->description = "Remove layer from a Crytpomatte node";
+ ot->idname = "NODE_OT_cryptomatte_layer_remove";
+
+ /* callbacks */
+ ot->exec = node_cryptomatte_remove_socket_exec;
+ ot->poll = composite_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c
index 37ea53aa710..b265d95c06a 100644
--- a/source/blender/editors/space_node/node_gizmo.c
+++ b/source/blender/editors/space_node/node_gizmo.c
@@ -83,12 +83,12 @@ static void node_gizmo_calc_matrix_space_with_image_dims(
* \{ */
static void gizmo_node_backdrop_prop_matrix_get(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- const SpaceNode *snode = mpr_prop->custom_func.user_data;
+ BLI_assert(gz_prop->type->array_length == 16);
+ const SpaceNode *snode = gz_prop->custom_func.user_data;
matrix[0][0] = snode->zoom;
matrix[1][1] = snode->zoom;
matrix[3][0] = snode->xof;
@@ -96,19 +96,19 @@ static void gizmo_node_backdrop_prop_matrix_get(
}
static void gizmo_node_backdrop_prop_matrix_set(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
const void *value_p)
{
const float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- SpaceNode *snode = mpr_prop->custom_func.user_data;
+ BLI_assert(gz_prop->type->array_length == 16);
+ SpaceNode *snode = gz_prop->custom_func.user_data;
snode->zoom = matrix[0][0];
snode->zoom = matrix[1][1];
snode->xof = matrix[3][0];
snode->yof = matrix[3][1];
}
-static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
SpaceNode *snode = CTX_wm_space_node(C);
@@ -127,22 +127,22 @@ static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType
return false;
}
-static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_WT_cage_2d", mgroup, NULL);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
RNA_enum_set(wwrapper->gizmo->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
- mgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
}
-static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- wmGizmo *cage = ((wmGizmoWrapper *)mgroup->customdata)->gizmo;
+ wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
const ARegion *ar = CTX_wm_region(C);
/* center is always at the origin */
const float origin[3] = {ar->winx / 2, ar->winy / 2};
@@ -186,16 +186,16 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *
BKE_image_release_ibuf(ima, ibuf, lock);
}
-void NODE_WGT_backdrop_transform(wmGizmoGroupType *wgt)
+void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt)
{
- wgt->name = "Backdrop Transform Widget";
- wgt->idname = "NODE_WGT_backdrop_transform";
+ gzgt->name = "Backdrop Transform Widget";
+ gzgt->idname = "NODE_GGT_backdrop_transform";
- wgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- wgt->poll = WIDGETGROUP_node_transform_poll;
- wgt->setup = WIDGETGROUP_node_transform_setup;
- wgt->refresh = WIDGETGROUP_node_transform_refresh;
+ gzgt->poll = WIDGETGROUP_node_transform_poll;
+ gzgt->setup = WIDGETGROUP_node_transform_setup;
+ gzgt->refresh = WIDGETGROUP_node_transform_refresh;
}
/** \} */
@@ -258,14 +258,14 @@ static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, const float dims
/* scale callbacks */
static void gizmo_node_crop_prop_matrix_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
const float *dims = crop_group->state.dims;
- const bNode *node = mpr_prop->custom_func.user_data;
+ const bNode *node = gz_prop->custom_func.user_data;
const NodeTwoXYs *nxy = node->storage;
bool is_relative = (bool)node->custom2;
rctf rct;
@@ -277,14 +277,14 @@ static void gizmo_node_crop_prop_matrix_get(
}
static void gizmo_node_crop_prop_matrix_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
const float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
const float *dims = crop_group->state.dims;
- bNode *node = mpr_prop->custom_func.user_data;
+ bNode *node = gz_prop->custom_func.user_data;
NodeTwoXYs *nxy = node->storage;
bool is_relative = (bool)node->custom2;
rctf rct;
@@ -296,7 +296,7 @@ static void gizmo_node_crop_prop_matrix_set(
gizmo_node_crop_update(crop_group);
}
-static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
SpaceNode *snode = CTX_wm_space_node(C);
@@ -318,33 +318,33 @@ static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUS
return false;
}
-static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__);
- crop_group->border = WM_gizmo_new("GIZMO_WT_cage_2d", mgroup, NULL);
+ crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
RNA_enum_set(crop_group->border->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- mgroup->customdata = crop_group;
+ gzgroup->customdata = crop_group;
}
-static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
ARegion *ar = CTX_wm_region(C);
- wmGizmo *mpr = mgroup->gizmos.first;
+ wmGizmo *gz = gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
- node_gizmo_calc_matrix_space(snode, ar, mpr->matrix_space);
+ node_gizmo_calc_matrix_space(snode, ar, gz->matrix_space);
}
-static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeCropWidgetGroup *crop_group = mgroup->customdata;
- wmGizmo *mpr = crop_group->border;
+ struct NodeCropWidgetGroup *crop_group = gzgroup->customdata;
+ wmGizmo *gz = crop_group->border;
void *lock;
Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -354,8 +354,8 @@ static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *mgrou
crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
- RNA_float_set_array(mpr->ptr, "dimensions", crop_group->state.dims);
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node = nodeGetActive(snode->edittree);
@@ -365,7 +365,7 @@ static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *mgrou
crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, "relative");
WM_gizmo_target_property_def_func(
- mpr, "matrix",
+ gz, "matrix",
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = gizmo_node_crop_prop_matrix_get,
.value_set_fn = gizmo_node_crop_prop_matrix_set,
@@ -374,23 +374,23 @@ static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *mgrou
});
}
else {
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
BKE_image_release_ibuf(ima, ibuf, lock);
}
-void NODE_WGT_backdrop_crop(wmGizmoGroupType *wgt)
+void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt)
{
- wgt->name = "Backdrop Crop Widget";
- wgt->idname = "NODE_WGT_backdrop_crop";
+ gzgt->name = "Backdrop Crop Widget";
+ gzgt->idname = "NODE_GGT_backdrop_crop";
- wgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- wgt->poll = WIDGETGROUP_node_crop_poll;
- wgt->setup = WIDGETGROUP_node_crop_setup;
- wgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
- wgt->refresh = WIDGETGROUP_node_crop_refresh;
+ gzgt->poll = WIDGETGROUP_node_crop_poll;
+ gzgt->setup = WIDGETGROUP_node_crop_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_crop_refresh;
}
/** \} */
@@ -408,7 +408,7 @@ struct NodeSunBeamsWidgetGroup {
} state;
};
-static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
SpaceNode *snode = CTX_wm_space_node(C);
@@ -427,36 +427,36 @@ static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNU
return false;
}
-static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), __func__);
- sbeam_group->gizmo = WM_gizmo_new("GIZMO_WT_grab_3d", mgroup, NULL);
- wmGizmo *mpr = sbeam_group->gizmo;
+ sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_grab_3d", gzgroup, NULL);
+ wmGizmo *gz = sbeam_group->gizmo;
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_CROSS_2D);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_CROSS_2D);
- mpr->scale_basis = 0.05f;
+ gz->scale_basis = 0.05f;
- mgroup->customdata = sbeam_group;
+ gzgroup->customdata = sbeam_group;
}
-static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata;
+ struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
ARegion *ar = CTX_wm_region(C);
- wmGizmo *mpr = mgroup->gizmos.first;
+ wmGizmo *gz = gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
- node_gizmo_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, mpr->matrix_space);
+ node_gizmo_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, gz->matrix_space);
}
-static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata;
- wmGizmo *mpr = sbeam_group->gizmo;
+ struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
+ wmGizmo *gz = sbeam_group->gizmo;
void *lock;
Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -472,28 +472,28 @@ static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *mgro
/* need to set property here for undo. TODO would prefer to do this in _init */
PointerRNA nodeptr;
RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
- WM_gizmo_target_property_def_rna(mpr, "offset", &nodeptr, "source", -1);
+ WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1);
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_MODAL, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
}
else {
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
BKE_image_release_ibuf(ima, ibuf, lock);
}
-void NODE_WGT_backdrop_sun_beams(wmGizmoGroupType *wgt)
+void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt)
{
- wgt->name = "Sun Beams Widget";
- wgt->idname = "NODE_WGT_sbeam";
+ gzgt->name = "Sun Beams Widget";
+ gzgt->idname = "NODE_GGT_sbeam";
- wgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- wgt->poll = WIDGETGROUP_node_sbeam_poll;
- wgt->setup = WIDGETGROUP_node_sbeam_setup;
- wgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
- wgt->refresh = WIDGETGROUP_node_sbeam_refresh;
+ gzgt->poll = WIDGETGROUP_node_sbeam_poll;
+ gzgt->setup = WIDGETGROUP_node_sbeam_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_sbeam_refresh;
}
/** \} */
@@ -513,7 +513,7 @@ struct NodeCornerPinWidgetGroup {
} state;
};
-static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
SpaceNode *snode = CTX_wm_space_node(C);
@@ -532,26 +532,26 @@ static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType
return false;
}
-static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(sizeof(struct NodeCornerPinWidgetGroup), __func__);
- const wmGizmoType *wt_grab_3d = WM_gizmotype_find("GIZMO_WT_grab_3d", false);
+ const wmGizmoType *gzt_grab_3d = WM_gizmotype_find("GIZMO_GT_grab_3d", false);
for (int i = 0; i < 4; i++) {
- cpin_group->gizmos[i] = WM_gizmo_new_ptr(wt_grab_3d, mgroup, NULL);
- wmGizmo *mpr = cpin_group->gizmos[i];
+ cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_grab_3d, gzgroup, NULL);
+ wmGizmo *gz = cpin_group->gizmos[i];
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_CROSS_2D);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_CROSS_2D);
- mpr->scale_basis = 0.01f;
+ gz->scale_basis = 0.01f;
}
- mgroup->customdata = cpin_group;
+ gzgroup->customdata = cpin_group;
}
-static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata;
+ struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
@@ -560,15 +560,15 @@ static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoG
node_gizmo_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space);
for (int i = 0; i < 4; i++) {
- wmGizmo *mpr = cpin_group->gizmos[i];
- copy_m4_m4(mpr->matrix_space, matrix_space);
+ wmGizmo *gz = cpin_group->gizmos[i];
+ copy_m4_m4(gz->matrix_space, matrix_space);
}
}
-static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata;
+ struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
void *lock;
Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -585,37 +585,37 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup
int i = 0;
for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
if (sock->type == SOCK_VECTOR) {
- wmGizmo *mpr = cpin_group->gizmos[i++];
+ wmGizmo *gz = cpin_group->gizmos[i++];
PointerRNA sockptr;
RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr);
- WM_gizmo_target_property_def_rna(mpr, "offset", &sockptr, "default_value", -1);
+ WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1);
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_MODAL, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
}
}
}
else {
for (int i = 0; i < 4; i++) {
- wmGizmo *mpr = cpin_group->gizmos[i];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ wmGizmo *gz = cpin_group->gizmos[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
BKE_image_release_ibuf(ima, ibuf, lock);
}
-void NODE_WGT_backdrop_corner_pin(wmGizmoGroupType *wgt)
+void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt)
{
- wgt->name = "Corner Pin Widget";
- wgt->idname = "NODE_WGT_backdrop_corner_pin";
+ gzgt->name = "Corner Pin Widget";
+ gzgt->idname = "NODE_GGT_backdrop_corner_pin";
- wgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
- wgt->poll = WIDGETGROUP_node_corner_pin_poll;
- wgt->setup = WIDGETGROUP_node_corner_pin_setup;
- wgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
- wgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
+ gzgt->poll = WIDGETGROUP_node_corner_pin_poll;
+ gzgt->setup = WIDGETGROUP_node_corner_pin_setup;
+ gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 742c3975c8d..3644c8d09e6 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -224,11 +224,13 @@ void NODE_OT_viewer_border(struct wmOperatorType *ot);
void NODE_OT_clear_viewer_border(struct wmOperatorType *ot);
/* node_widgets.c */
-void NODE_WGT_backdrop_transform(struct wmGizmoGroupType *wgt);
-void NODE_WGT_backdrop_crop(struct wmGizmoGroupType *wgt);
-void NODE_WGT_backdrop_sun_beams(struct wmGizmoGroupType *wgt);
-void NODE_WGT_backdrop_corner_pin(struct wmGizmoGroupType *wgt);
+void NODE_GGT_backdrop_transform(struct wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_crop(struct wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_sun_beams(struct wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_corner_pin(struct wmGizmoGroupType *gzgt);
+void NODE_OT_cryptomatte_layer_add(struct wmOperatorType *ot);
+void NODE_OT_cryptomatte_layer_remove(struct wmOperatorType *ot);
extern const char *node_context_dir[];
@@ -236,7 +238,7 @@ extern const char *node_context_dir[];
// nodes draw without dpi - the view zoom is flexible
#define HIDDEN_RAD (0.75f * U.widget_unit)
-#define BASIS_RAD (0.4f * U.widget_unit)
+#define BASIS_RAD (0.2f * U.widget_unit)
#define NODE_DYS (U.widget_unit / 2)
#define NODE_DY U.widget_unit
#define NODE_SOCKDY (0.08f * U.widget_unit)
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 2a585c42395..dccc999b2d1 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -129,6 +129,9 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_tree_socket_add);
WM_operatortype_append(NODE_OT_tree_socket_remove);
WM_operatortype_append(NODE_OT_tree_socket_move);
+
+ WM_operatortype_append(NODE_OT_cryptomatte_layer_add);
+ WM_operatortype_append(NODE_OT_cryptomatte_layer_remove);
}
void ED_operatormacros_node(void)
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 1149b910947..51ba3a62d1b 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -675,40 +675,31 @@ static void node_main_region_draw(const bContext *C, ARegion *ar)
/* ************* dropboxes ************* */
-static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_IM)
- return 1;
+ if (drag->type == WM_DRAG_PATH) {
+ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); /* rule might not work? */
}
- else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
- return 1;
+ else {
+ return WM_drag_ID(drag, ID_IM) != NULL;
}
- return 0;
}
-static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_MSK)
- return 1;
- }
- return 0;
+ return WM_drag_ID(drag, ID_MSK) != NULL;
}
static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -752,7 +743,7 @@ static void node_region_listener(
wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
wmNotifier *wmn, const Scene *UNUSED(scene))
{
- wmGizmoMap *mmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = ar->gizmo_map;
/* context changes */
switch (wmn->category) {
@@ -762,13 +753,13 @@ static void node_region_listener(
ED_region_tag_redraw(ar);
break;
case ND_SPACE_NODE_VIEW:
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
}
break;
case NC_SCREEN:
if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
switch (wmn->data) {
case ND_ANIMPLAY:
@@ -784,13 +775,13 @@ static void node_region_listener(
case NC_SCENE:
ED_region_tag_redraw(ar);
if (wmn->data == ND_RENDER_RESULT) {
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_NODE:
ED_region_tag_redraw(ar);
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_MATERIAL:
@@ -863,12 +854,12 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
static void node_widgets(void)
{
/* create the widgetmap for the area here */
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
&(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
- WM_gizmogrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_transform);
- WM_gizmogrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_crop);
- WM_gizmogrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_sun_beams);
- WM_gizmogrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_corner_pin);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
+ WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
}
static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 96d27c6fd89..796e8732fca 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -39,6 +39,7 @@ set(INC_SYS
set(SRC
outliner_collections.c
+ outliner_dragdrop.c
outliner_draw.c
outliner_edit.c
outliner_ops.c
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index ad94615a0d2..d4c85ce28bd 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -99,6 +99,24 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
return NULL;
}
+TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
+{
+ struct ObjectsSelectedData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (outliner_is_collection_tree_element(te)) {
+ return TRAVERSE_CONTINUE;
+ }
+
+ if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ BLI_addtail(&data->objects_selected_array, BLI_genericNodeN(te));
+
+ return TRAVERSE_CONTINUE;
+}
+
/* -------------------------------------------------------------------- */
/* Poll functions. */
@@ -138,8 +156,10 @@ static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void
static int collection_new_exec(bContext *C, wmOperator *op)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
struct CollectionNewData data = {
.error = false,
@@ -147,6 +167,8 @@ static int collection_new_exec(bContext *C, wmOperator *op)
};
if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_build_tree(bmain, scene, view_layer, soops, ar);
+
outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
if (data.error) {
@@ -574,7 +596,7 @@ static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, v
return TRAVERSE_CONTINUE;
}
-static bool collections_view_layer_poll(bContext *C, bool include)
+static bool collections_view_layer_poll(bContext *C, bool clear, int flag)
{
/* Poll function so the right click menu show current state of selected collections. */
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -593,10 +615,10 @@ static bool collections_view_layer_poll(bContext *C, bool include)
GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ if (clear && (lc->flag & flag)) {
result = true;
}
- else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ else if (!clear && !(lc->flag & flag)) {
result = true;
}
}
@@ -605,27 +627,47 @@ static bool collections_view_layer_poll(bContext *C, bool include)
return result;
}
-static bool collections_exclude_poll(bContext *C)
+static bool collections_exclude_set_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_EXCLUDE);
+}
+
+static bool collections_exclude_clear_poll(bContext *C)
{
- return collections_view_layer_poll(C, false);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_EXCLUDE);
}
-static bool collections_include_poll(bContext *C)
+static bool collections_holdout_set_poll(bContext *C)
{
- return collections_view_layer_poll(C, true);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_HOLDOUT);
}
-static void layer_collection_exclude_recursive_set(LayerCollection *lc)
+static bool collections_holdout_clear_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_HOLDOUT);
+}
+
+static bool collections_indirect_only_set_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_INDIRECT_ONLY);
+}
+
+static bool collections_indirect_only_clear_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_INDIRECT_ONLY);
+}
+
+static void layer_collection_flag_recursive_set(LayerCollection *lc, int flag)
{
for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- nlc->flag |= LAYER_COLLECTION_EXCLUDE;
+ if (lc->flag & flag) {
+ nlc->flag |= flag;
}
else {
- nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ nlc->flag &= ~flag;
}
- layer_collection_exclude_recursive_set(nlc);
+ layer_collection_flag_recursive_set(nlc, flag);
}
}
@@ -636,7 +678,10 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
struct CollectionEditData data = {.scene = scene, .soops = soops};
- bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
+ bool clear = strstr(op->idname, "clear") != NULL;
+ int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT :
+ strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY :
+ LAYER_COLLECTION_EXCLUDE;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@@ -647,14 +692,14 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
- if (include) {
- lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ if (clear) {
+ lc->flag &= ~flag;
}
else {
- lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ lc->flag |= flag;
}
- layer_collection_exclude_recursive_set(lc);
+ layer_collection_flag_recursive_set(lc, flag);
}
}
@@ -671,28 +716,88 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Exclude from View Layer";
+ ot->name = "Set Exclude";
ot->idname = "OUTLINER_OT_collection_exclude_set";
ot->description = "Exclude collection from the active view layer";
/* api callbacks */
ot->exec = collection_view_layer_exec;
- ot->poll = collections_exclude_poll;
+ ot->poll = collections_exclude_set_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
+void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Include in View Layer";
- ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->name = "Clear Exclude";
+ ot->idname = "OUTLINER_OT_collection_exclude_clear";
ot->description = "Include collection in the active view layer";
/* api callbacks */
ot->exec = collection_view_layer_exec;
- ot->poll = collections_include_poll;
+ ot->poll = collections_exclude_clear_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_holdout_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Holdout";
+ ot->idname = "OUTLINER_OT_collection_holdout_set";
+ ot->description = "Mask collection in the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_holdout_set_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_holdout_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Holdout";
+ ot->idname = "OUTLINER_OT_collection_holdout_clear";
+ ot->description = "Clear masking of collection in the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_holdout_clear_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_indirect_only_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Indirect Only";
+ ot->idname = "OUTLINER_OT_collection_indirect_only_set";
+ ot->description = "Set collection to only contribute indirectly (through shadows and reflections) in the view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_indirect_only_set_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Indirect Only";
+ ot->idname = "OUTLINER_OT_collection_indirect_only_clear";
+ ot->description = "Clear collection contributing only indirectly in the view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_indirect_only_clear_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
new file mode 100644
index 00000000000..55b9a561503
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -0,0 +1,954 @@
+/*
+ * ***** 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) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_outliner/outliner_dragdrop.c
+ * \ingroup spoutliner
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_group_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_collection.h"
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "ED_object.h"
+#include "ED_outliner.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "GPU_state.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "outliner_intern.h"
+
+/* ******************** Drop Target Find *********************** */
+
+static TreeElement *outliner_dropzone_element(TreeElement *te, const float fmval[2], const bool children)
+{
+ if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
+ /* name and first icon */
+ if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend))
+ return te;
+ }
+ /* Not it. Let's look at its children. */
+ if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
+ for (te = te->subtree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
+ if (te_valid)
+ return te_valid;
+ }
+ }
+ return NULL;
+}
+
+/* Find tree element to drop into. */
+static TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const bool children)
+{
+ TreeElement *te;
+
+ for (te = soops->tree.first; te; te = te->next) {
+ TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
+ if (te_valid)
+ return te_valid;
+ }
+ return NULL;
+}
+
+static TreeElement *outliner_drop_find(bContext *C, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ float fmval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ return outliner_dropzone_find(soops, fmval, true);
+}
+
+static ID *outliner_ID_drop_find(bContext *C, const wmEvent *event, short idcode)
+{
+ TreeElement *te = outliner_drop_find(C, event);
+ TreeStoreElem *tselem = (te) ? TREESTORE(te) : NULL;
+
+ if (te && te->idcode == idcode && tselem->type == 0) {
+ return tselem->id;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/* Find tree element to drop into, with additional before and after reorder support. */
+static TreeElement *outliner_drop_insert_find(
+ bContext *C, const wmEvent *event,
+ TreeElementInsertType *r_insert_type)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ 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 */
+ const float margin = UI_UNIT_Y * (1.0f / 4);
+
+ 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;
+ return te_hovered;
+ }
+ else {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return te_hovered->subtree.first;
+ }
+ }
+ else {
+ *r_insert_type = TE_INSERT_AFTER;
+ return te_hovered;
+ }
+ }
+ else if (view_mval[1] > (te_hovered->ys + (3 * margin))) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return te_hovered;
+ }
+ else {
+ *r_insert_type = TE_INSERT_INTO;
+ return te_hovered;
+ }
+ }
+ 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_insert_type = TE_INSERT_AFTER;
+ return last;
+ }
+ else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ return first;
+ }
+ else {
+ BLI_assert(0);
+ return NULL;
+ }
+ }
+}
+
+static TreeElement *outliner_drop_insert_collection_find(
+ bContext *C, const wmEvent *event,
+ TreeElementInsertType *r_insert_type)
+{
+ TreeElement *te = outliner_drop_insert_find(C, event, r_insert_type);
+ if (!te) {
+ return NULL;
+ }
+
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (!collection) {
+ return NULL;
+ }
+
+ /* We can't insert/before after master collection. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ if (*r_insert_type == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *r_insert_type = TE_INSERT_INTO;
+ }
+ else if (*r_insert_type == TE_INSERT_AFTER) {
+ te = te->subtree.last;
+ collection = outliner_collection_from_tree_element(te);
+ if (!collection) {
+ return NULL;
+ }
+ }
+ }
+
+ return te;
+}
+
+/* ******************** Parent Drop Operator *********************** */
+
+static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ if (!ob) {
+ return false;
+ }
+
+ /* Ensure item under cursor is valid drop target */
+ TreeElement *te = outliner_drop_find(C, event);
+ TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
+
+ if (!te) {
+ /* pass */
+ }
+ else if (te->idcode == ID_OB && tselem->type == 0) {
+ Scene *scene;
+ ID *te_id = tselem->id;
+
+ /* check if dropping self or parent */
+ if (te_id == &ob->id || (Object *)te_id == ob->parent)
+ return false;
+
+ /* check that parent/child are both in the same scene */
+ scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+
+ /* currently outliner organized in a way that if there's no parent scene
+ * element for object it means that all displayed objects belong to
+ * active scene and parenting them is allowed (sergey)
+ */
+ if (!scene) {
+ return true;
+ }
+ else {
+ for (ViewLayer *view_layer = scene->view_layers.first;
+ view_layer;
+ view_layer = view_layer->next)
+ {
+ if (BKE_view_layer_base_find(view_layer, ob)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static int parent_drop_exec(bContext *C, wmOperator *op)
+{
+ Object *par = NULL, *ob = NULL;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int partype = -1;
+ char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
+
+ partype = RNA_enum_get(op->ptr, "type");
+ RNA_string_get(op->ptr, "parent", parname);
+ par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
+
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_drop_find(C, event);
+ TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
+
+ if (!(te && te->idcode == ID_OB && tselem->type == 0)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *par = (Object *)tselem->id;
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+
+ if (ELEM(NULL, ob, par)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (ob == par) {
+ return OPERATOR_CANCELLED;
+ }
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ char childname[MAX_ID_NAME];
+ char parname[MAX_ID_NAME];
+ STRNCPY(childname, ob->id.name);
+ STRNCPY(parname, par->id.name);
+ RNA_string_set(op->ptr, "child", childname);
+ RNA_string_set(op->ptr, "parent", parname);
+
+ Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+
+ if (scene == NULL) {
+ /* currently outlier organized in a way, that if there's no parent scene
+ * element for object it means that all displayed objects belong to
+ * active scene and parenting them is allowed (sergey)
+ */
+
+ scene = CTX_data_scene(C);
+ }
+
+ if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
+ int partype = 0;
+ if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ }
+ }
+ else {
+ /* Menu creation */
+ 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;
+
+ /* Cannot use uiItemEnumO()... have multiple properties to set. */
+ uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_OBJECT);
+
+ /* par becomes parent, make the associated menus */
+ if (par->type == OB_ARMATURE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_ARMATURE);
+
+ uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ 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 Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ 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 Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ 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_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_BONE);
+ }
+ else if (par->type == OB_CURVE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_CURVE);
+
+ uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_FOLLOW);
+
+ uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
+ }
+ else if (par->type == OB_LATTICE) {
+ uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "parent", parname);
+ RNA_string_set(&ptr, "child", childname);
+ RNA_enum_set(&ptr, "type", PAR_LATTICE);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_parent_drop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Drop to Set Parent";
+ ot->description = "Drag to parent in Outliner";
+ ot->idname = "OUTLINER_OT_parent_drop";
+
+ /* api callbacks */
+ ot->invoke = parent_drop_invoke;
+ ot->exec = parent_drop_exec;
+
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
+ RNA_def_string(ot->srna, "parent", "Object", MAX_ID_NAME, "Parent", "Parent Object");
+ RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+}
+
+static bool parenting_poll(bContext *C)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ if (soops) {
+ if (soops->outlinevis == SO_SCENES) {
+ return true;
+ }
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* ******************** Parent Clear Operator *********************** */
+
+static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
+ return false;
+ }
+
+ Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ if (!(ob && ob->parent)) {
+ return false;
+ }
+
+ TreeElement *te = outliner_drop_find(C, event);
+ if (te) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ switch (te->idcode) {
+ case ID_SCE:
+ return (ELEM(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER));
+ case ID_OB:
+ return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
+ /* Other codes to ignore? */
+ }
+ }
+ return (te == NULL);
+}
+
+static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+
+ if (ob == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_object_parent_clear(ob, 0);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_parent_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Drop to Clear Parent";
+ ot->description = "Drag to clear parent in Outliner";
+ ot->idname = "OUTLINER_OT_parent_clear";
+
+ /* api callbacks */
+ ot->invoke = parent_clear_invoke;
+
+ ot->poll = parenting_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/* ******************** Scene Drop Operator *********************** */
+
+static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+{
+ /* Ensure item under cursor is valid drop target */
+ Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
+ return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL));
+}
+
+static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE);
+ Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB);
+
+ if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_scene_has_object(scene, ob)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Collection *collection;
+ if (scene != CTX_data_scene(C)) {
+ /* when linking to an inactive scene link to the master collection */
+ collection = BKE_collection_master(scene);
+ }
+ else {
+ collection = CTX_data_collection(C);
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_scene_drop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Drop Object to Scene";
+ ot->description = "Drag object to scene in Outliner";
+ ot->idname = "OUTLINER_OT_scene_drop";
+
+ /* api callbacks */
+ ot->invoke = scene_drop_invoke;
+
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/* ******************** Material Drop Operator *********************** */
+
+static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
+{
+ /* Ensure item under cursor is valid drop target */
+ Material *ma = (Material *)WM_drag_ID(drag, ID_MA);
+ return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL));
+}
+
+static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)outliner_ID_drop_find(C, event, ID_OB);
+ Material *ma = (Material *)WM_drag_ID_from_event(event, ID_MA);
+
+ if (ELEM(NULL, ob, ma)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ assign_material(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_material_drop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Drop Material on Object";
+ ot->description = "Drag material to object in Outliner";
+ ot->idname = "OUTLINER_OT_material_drop";
+
+ /* api callbacks */
+ ot->invoke = material_drop_invoke;
+
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/* ******************** Collection Drop Operator *********************** */
+
+typedef struct CollectionDrop {
+ Collection *from;
+ Collection *to;
+
+ TreeElement *te;
+ TreeElementInsertType insert_type;
+} CollectionDrop;
+
+static Collection *collection_parent_from_ID(ID *id)
+{
+ /* Can't change linked parent collections. */
+ if (!id || ID_IS_LINKED(id)) {
+ return NULL;
+ }
+
+ /* Also support dropping into/from scene collection. */
+ if (GS(id->name) == ID_SCE) {
+ return ((Scene *)id)->master_collection;
+ }
+ else if (GS(id->name) == ID_GR) {
+ return (Collection *)id;
+ }
+
+ return NULL;
+}
+
+static bool collection_drop_init(bContext *C, wmDrag *drag, const wmEvent *event, CollectionDrop *data)
+{
+ /* Get collection to drop into. */
+ TreeElementInsertType insert_type;
+ TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
+ if (!te) {
+ return false;
+ }
+
+ Collection *to_collection = outliner_collection_from_tree_element(te);
+ if (ID_IS_LINKED(to_collection)) {
+ return false;
+ }
+
+ /* Get drag datablocks. */
+ if (drag->type != WM_DRAG_ID) {
+ return false;
+ }
+
+ wmDragID *drag_id = drag->ids.first;
+ if (drag_id == NULL) {
+ return false;
+ }
+
+ ID *id = drag_id->id;
+ if (!(id && ELEM(GS(id->name), ID_GR, ID_OB))) {
+ return false;
+ }
+
+ /* Get collection to drag out of. */
+ ID *parent = drag_id->from_parent;
+ Collection *from_collection = collection_parent_from_ID(parent);
+ if (event->ctrl) {
+ from_collection = NULL;
+ }
+
+ /* Get collections. */
+ if (GS(id->name) == ID_GR) {
+ if (id == &to_collection->id) {
+ return false;
+ }
+ }
+ else {
+ insert_type = TE_INSERT_INTO;
+ }
+
+ data->from = from_collection;
+ data->to = to_collection;
+ data->te = te;
+ data->insert_type = insert_type;
+
+ return true;
+}
+
+static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
+
+ CollectionDrop data;
+ if (collection_drop_init(C, drag, event, &data)) {
+ if (!data.from || event->ctrl) {
+ *tooltip = IFACE_("Link inside Collection");
+ }
+ else {
+ TreeElement *te = data.te;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ switch (data.insert_type) {
+ case TE_INSERT_BEFORE:
+ tselem->flag |= TSE_DRAG_BEFORE;
+ changed = true;
+ if (te->prev && outliner_is_collection_tree_element(te->prev)) {
+ *tooltip = TIP_("Move between collections");
+ }
+ else {
+ *tooltip = TIP_("Move before collection");
+ }
+ break;
+ case TE_INSERT_AFTER:
+ tselem->flag |= TSE_DRAG_AFTER;
+ changed = true;
+ if (te->next && outliner_is_collection_tree_element(te->next)) {
+ *tooltip = TIP_("Move between collections");
+ }
+ else {
+ *tooltip = TIP_("Move after collection");
+ }
+ break;
+ case TE_INSERT_INTO:
+ tselem->flag |= TSE_DRAG_INTO;
+ changed = true;
+ *tooltip = TIP_("Move inside collection (Ctrl to link)");
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+
+ return true;
+}
+
+static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (event->custom != EVT_DATA_DRAGDROP) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ListBase *lb = event->customdata;
+ wmDrag *drag = lb->first;
+
+ CollectionDrop data;
+ if (!collection_drop_init(C, drag, event, &data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Before/after insert handling. */
+ Collection *relative = NULL;
+ bool relative_after = false;
+
+ if (ELEM(data.insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ relative = data.to;
+ relative_after = (data.insert_type == TE_INSERT_AFTER);
+
+ TreeElement *parent_te = outliner_find_parent_element(&soops->tree, NULL, data.te);
+ data.to = (parent_te) ? outliner_collection_from_tree_element(parent_te) : NULL;
+ }
+
+ if (!data.to) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ /* Ctrl enables linking, so we don't need a from collection then. */
+ Collection *from = (event->ctrl) ? NULL : collection_parent_from_ID(drag_id->from_parent);
+
+ if (GS(drag_id->id->name) == ID_OB) {
+ /* Move/link object into collection. */
+ Object *object = (Object *)drag_id->id;
+
+ if (from) {
+ BKE_collection_object_move(bmain, scene, data.to, from, object);
+ }
+ else {
+ BKE_collection_object_add(bmain, data.to, object);
+ }
+ }
+ else if (GS(drag_id->id->name) == ID_GR) {
+ /* Move/link collection into collection. */
+ Collection *collection = (Collection *)drag_id->id;
+
+ if (collection != from) {
+ BKE_collection_move(bmain, data.to, from, relative, relative_after, collection);
+ }
+ }
+
+ if (from) {
+ DEG_id_tag_update(&from->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ }
+
+ /* Update dependency graph. */
+ DEG_id_tag_update(&data.to->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_drop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Move to Collection";
+ ot->description = "Drag to move to collection in Outliner";
+ ot->idname = "OUTLINER_OT_collection_drop";
+
+ /* api callbacks */
+ ot->invoke = collection_drop_invoke;
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/* ********************* Outliner Drag Operator ******************** */
+
+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 int outliner_item_drag_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_item_drag_element_find(soops, ar, event);
+
+ if (!te) {
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ TreeElementIcon data = tree_element_get_icon(TREESTORE(te), te);
+ if (!data.drag_id) {
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP);
+
+ if (GS(data.drag_id->name) == ID_OB) {
+ /* For objects we cheat and drag all selected objects. */
+ TREESTORE(te)->flag |= TSE_SELECTED;
+
+ struct ObjectsSelectedData selected = {
+ .objects_selected_array = {NULL, NULL},
+ };
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &selected);
+ LISTBASE_FOREACH (LinkData *, link, &selected.objects_selected_array) {
+ TreeElement *ten_selected = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(ten_selected)->id;
+
+ /* Find parent collection of object. */
+ Collection *parent = NULL;
+
+ if (ten_selected->parent) {
+ for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
+ if (outliner_is_collection_tree_element(te_ob_parent)) {
+ parent = outliner_collection_from_tree_element(te_ob_parent);
+ break;
+ }
+ }
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ parent = BKE_collection_master(scene);
+ }
+
+ WM_drag_add_ID(drag, &ob->id, &parent->id);
+ }
+
+ BLI_freelistN(&selected.objects_selected_array);
+ }
+ else {
+ /* Add single ID. */
+ WM_drag_add_ID(drag, data.drag_id, data.drag_parent);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+}
+
+/* Outliner drag and drop. This operator mostly exists to support dragging
+ * from outliner text instead of only from the icon, and also to show a
+ * hint in the statusbar keymap. */
+
+void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
+{
+ ot->name = "Drag and Drop";
+ ot->idname = "OUTLINER_OT_item_drag_drop";
+ ot->description = "Drag and drop element to another place";
+
+ ot->invoke = outliner_item_drag_drop_invoke;
+ ot->poll = ED_operator_outliner_active;
+}
+
+/* *************************** Drop Boxes ************************** */
+
+/* region dropbox definition */
+void outliner_dropboxes(void)
+{
+ ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
+
+ WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", parent_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", parent_clear_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", scene_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_material_drop", material_drop_poll, NULL);
+ WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", collection_drop_poll, NULL);
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 8e111beec54..5244c364b80 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -32,6 +32,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lightprobe_types.h"
@@ -50,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
@@ -438,12 +440,16 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
case TSE_GP_LAYER:
{
- bGPdata *gpd = (bGPdata *)tselem->id; // id = GP Datablock
+ bGPdata *gpd = (bGPdata *)tselem->id; /* id = GP Datablock */
bGPDlayer *gpl = te->directdata;
+ /* always make layer active */
+ BKE_gpencil_layer_setactive(gpd, gpl);
+
// XXX: name needs translation stuff
BLI_uniquename(&gpd->layers, gpl, "GP Layer", '.',
offsetof(bGPDlayer, info), sizeof(gpl->info));
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
break;
}
@@ -742,11 +748,11 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
GPU_line_width(1.0f);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, sizex, v2d->cur.ymax);
immVertex2f(pos, sizex, miny);
@@ -844,394 +850,389 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
/* ****************************************************** */
/* Normal Drawing... */
-/* make function calls a bit compacter */
-struct DrawIconArg {
- uiBlock *block;
- ID *id;
- float xmax, x, y, xb, yb;
- float alpha;
-};
-
-static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
+TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
{
- /* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
- if (arg->x >= arg->xmax) {
- GPU_blend(true);
- UI_icon_draw_alpha(arg->x, arg->y, icon, arg->alpha);
- GPU_blend(false);
- }
- else {
- uiBut *but = uiDefIconBut(
- arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
- 0.0, 0.0, 1.0, arg->alpha,
- (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : "");
-
- if (arg->id)
- UI_but_drag_set_id(but, arg->id);
- }
-
-}
-
-static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg, ID *id, bGPDlayer *gpl)
-{
- /* restrict column clip - skip it for now... */
- if (arg->x >= arg->xmax) {
- /* pass */
- }
- else {
- PointerRNA ptr;
- const float eps = 0.001f;
- const bool is_stroke_visible = (gpl->color[3] > eps);
- const bool is_fill_visible = (gpl->fill[3] > eps);
- float w = 0.5f * UI_UNIT_X;
- float h = 0.85f * UI_UNIT_Y;
-
- RNA_pointer_create(id, &RNA_GPencilLayer, gpl, &ptr);
-
- UI_block_align_begin(arg->block);
-
- UI_block_emboss_set(arg->block, is_stroke_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
- uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb, arg->yb, w, h,
- &ptr, "color", -1,
- 0, 0, 0, 0, NULL);
-
- UI_block_emboss_set(arg->block, is_fill_visible ? UI_EMBOSS : UI_EMBOSS_NONE);
- uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb + w, arg->yb, w, h,
- &ptr, "fill_color", -1,
- 0, 0, 0, 0, NULL);
-
- UI_block_emboss_set(arg->block, UI_EMBOSS_NONE);
- UI_block_align_end(arg->block);
- }
-}
-
-static void tselem_draw_icon(
- uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
- float alpha, const bool is_clickable)
-{
- struct DrawIconArg arg;
- float aspect;
-
- /* make function calls a bit compacter */
- arg.block = block;
- arg.id = tselem->id;
- arg.xmax = xmax;
- 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;
- 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)
-#define ICON_CLICK_DRAW(_icon) if (!is_clickable) ICON_DRAW(_icon); else tselem_draw_icon_uibut(&arg, _icon)
+ TreeElementIcon data = {0};
if (tselem->type) {
switch (tselem->type) {
case TSE_ANIM_DATA:
- ICON_DRAW(ICON_ANIM_DATA); /* XXX */
+ data.icon = ICON_ANIM_DATA; /* XXX */
break;
case TSE_NLA:
- ICON_DRAW(ICON_NLA);
+ data.icon = ICON_NLA;
break;
case TSE_NLA_TRACK:
- ICON_DRAW(ICON_NLA); /* XXX */
+ data.icon = ICON_NLA; /* XXX */
break;
case TSE_NLA_ACTION:
- ICON_DRAW(ICON_ACTION);
+ data.icon = ICON_ACTION;
break;
case TSE_DRIVER_BASE:
- ICON_DRAW(ICON_DRIVER);
+ data.icon = ICON_DRIVER;
break;
case TSE_DEFGROUP_BASE:
- ICON_DRAW(ICON_GROUP_VERTEX);
+ data.icon = ICON_GROUP_VERTEX;
break;
case TSE_BONE:
case TSE_EBONE:
- ICON_DRAW(ICON_BONE_DATA);
+ data.icon = ICON_BONE_DATA;
break;
case TSE_CONSTRAINT_BASE:
- ICON_DRAW(ICON_CONSTRAINT);
+ data.icon = ICON_CONSTRAINT;
break;
case TSE_MODIFIER_BASE:
- ICON_DRAW(ICON_MODIFIER);
+ data.icon = ICON_MODIFIER;
break;
case TSE_LINKED_OB:
- ICON_DRAW(ICON_OBJECT_DATA);
+ data.icon = ICON_OBJECT_DATA;
break;
case TSE_LINKED_PSYS:
- ICON_DRAW(ICON_PARTICLES);
+ data.icon = 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:
- 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:
- ICON_DRAW(ICON_MOD_PARTICLES);
- break;
- case eModifierType_EdgeSplit:
- ICON_DRAW(ICON_MOD_EDGESPLIT);
- break;
- case eModifierType_Array:
- ICON_DRAW(ICON_MOD_ARRAY);
- break;
- case eModifierType_UVProject:
- case eModifierType_UVWarp: /* TODO, get own icon */
- ICON_DRAW(ICON_MOD_UVPROJECT);
- break;
- case eModifierType_Displace:
- ICON_DRAW(ICON_MOD_DISPLACE);
- break;
- case eModifierType_Shrinkwrap:
- ICON_DRAW(ICON_MOD_SHRINKWRAP);
- break;
- case eModifierType_Cast:
- ICON_DRAW(ICON_MOD_CAST);
- break;
- case eModifierType_MeshDeform:
- case eModifierType_SurfaceDeform:
- ICON_DRAW(ICON_MOD_MESHDEFORM);
- break;
- case eModifierType_Bevel:
- ICON_DRAW(ICON_MOD_BEVEL);
- break;
- case eModifierType_Smooth:
- case eModifierType_LaplacianSmooth:
- case eModifierType_CorrectiveSmooth:
- ICON_DRAW(ICON_MOD_SMOOTH);
- break;
- case eModifierType_SimpleDeform:
- ICON_DRAW(ICON_MOD_SIMPLEDEFORM);
- break;
- case eModifierType_Mask:
- ICON_DRAW(ICON_MOD_MASK);
- break;
- case eModifierType_Cloth:
- ICON_DRAW(ICON_MOD_CLOTH);
- break;
- case eModifierType_Explode:
- ICON_DRAW(ICON_MOD_EXPLODE);
- break;
- case eModifierType_Collision:
- case eModifierType_Surface:
- ICON_DRAW(ICON_MOD_PHYSICS);
- break;
- case eModifierType_Fluidsim:
- ICON_DRAW(ICON_MOD_FLUIDSIM);
- break;
- case eModifierType_Multires:
- ICON_DRAW(ICON_MOD_MULTIRES);
- break;
- case eModifierType_Smoke:
- ICON_DRAW(ICON_MOD_SMOKE);
- break;
- case eModifierType_Solidify:
- ICON_DRAW(ICON_MOD_SOLIDIFY);
- break;
- case eModifierType_Screw:
- ICON_DRAW(ICON_MOD_SCREW);
- break;
- case eModifierType_Remesh:
- ICON_DRAW(ICON_MOD_REMESH);
- break;
- case eModifierType_WeightVGEdit:
- case eModifierType_WeightVGMix:
- case eModifierType_WeightVGProximity:
- ICON_DRAW(ICON_MOD_VERTEX_WEIGHT);
- break;
- case eModifierType_DynamicPaint:
- ICON_DRAW(ICON_MOD_DYNAMICPAINT);
- break;
- case eModifierType_Ocean:
- ICON_DRAW(ICON_MOD_OCEAN);
- break;
- case eModifierType_Warp:
- ICON_DRAW(ICON_MOD_WARP);
- break;
- case eModifierType_Skin:
- ICON_DRAW(ICON_MOD_SKIN);
- break;
- case eModifierType_Triangulate:
- ICON_DRAW(ICON_MOD_TRIANGULATE);
- break;
- case eModifierType_MeshCache:
- ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
- break;
- case eModifierType_MeshSequenceCache:
- ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
- break;
- case eModifierType_Wireframe:
- ICON_DRAW(ICON_MOD_WIREFRAME);
- break;
- case eModifierType_LaplacianDeform:
- ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
- break;
- case eModifierType_DataTransfer:
- ICON_DRAW(ICON_MOD_DATA_TRANSFER);
- break;
- case eModifierType_NormalEdit:
- ICON_DRAW(ICON_MOD_NORMALEDIT);
- break;
- case eModifierType_Hair:
- ICON_DRAW(ICON_STRANDS);
- break;
- /* Default */
- case eModifierType_None:
- case eModifierType_ShapeKey:
- case NUM_MODIFIER_TYPES:
- ICON_DRAW(ICON_DOT);
- break;
+ if (ob->type != OB_GPENCIL) {
+ ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
+ switch ((ModifierType)md->type) {
+ case eModifierType_Subsurf:
+ data.icon = ICON_MOD_SUBSURF;
+ break;
+ case eModifierType_Armature:
+ data.icon = ICON_MOD_ARMATURE;
+ break;
+ case eModifierType_Lattice:
+ data.icon = ICON_MOD_LATTICE;
+ break;
+ case eModifierType_Curve:
+ data.icon = ICON_MOD_CURVE;
+ break;
+ case eModifierType_Build:
+ data.icon = ICON_MOD_BUILD;
+ break;
+ case eModifierType_Mirror:
+ data.icon = ICON_MOD_MIRROR;
+ break;
+ case eModifierType_Decimate:
+ data.icon = ICON_MOD_DECIM;
+ break;
+ case eModifierType_Wave:
+ data.icon = ICON_MOD_WAVE;
+ break;
+ case eModifierType_Hook:
+ data.icon = ICON_HOOK;
+ break;
+ case eModifierType_Softbody:
+ data.icon = ICON_MOD_SOFT;
+ break;
+ case eModifierType_Boolean:
+ data.icon = ICON_MOD_BOOLEAN;
+ break;
+ case eModifierType_ParticleSystem:
+ data.icon = ICON_MOD_PARTICLES;
+ break;
+ case eModifierType_ParticleInstance:
+ data.icon = ICON_MOD_PARTICLES;
+ break;
+ case eModifierType_EdgeSplit:
+ data.icon = ICON_MOD_EDGESPLIT;
+ break;
+ case eModifierType_Array:
+ data.icon = ICON_MOD_ARRAY;
+ break;
+ case eModifierType_UVProject:
+ case eModifierType_UVWarp: /* TODO, get own icon */
+ data.icon = ICON_MOD_UVPROJECT;
+ break;
+ case eModifierType_Displace:
+ data.icon = ICON_MOD_DISPLACE;
+ break;
+ case eModifierType_Shrinkwrap:
+ data.icon = ICON_MOD_SHRINKWRAP;
+ break;
+ case eModifierType_Cast:
+ data.icon = ICON_MOD_CAST;
+ break;
+ case eModifierType_MeshDeform:
+ case eModifierType_SurfaceDeform:
+ data.icon = ICON_MOD_MESHDEFORM;
+ break;
+ case eModifierType_Bevel:
+ data.icon = ICON_MOD_BEVEL;
+ break;
+ case eModifierType_Smooth:
+ case eModifierType_LaplacianSmooth:
+ case eModifierType_CorrectiveSmooth:
+ data.icon = ICON_MOD_SMOOTH;
+ break;
+ case eModifierType_SimpleDeform:
+ data.icon = ICON_MOD_SIMPLEDEFORM;
+ break;
+ case eModifierType_Mask:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case eModifierType_Cloth:
+ data.icon = ICON_MOD_CLOTH;
+ break;
+ case eModifierType_Explode:
+ data.icon = ICON_MOD_EXPLODE;
+ break;
+ case eModifierType_Collision:
+ case eModifierType_Surface:
+ data.icon = ICON_MOD_PHYSICS;
+ break;
+ case eModifierType_Fluidsim:
+ data.icon = ICON_MOD_FLUIDSIM;
+ break;
+ case eModifierType_Multires:
+ data.icon = ICON_MOD_MULTIRES;
+ break;
+ case eModifierType_Smoke:
+ data.icon = ICON_MOD_SMOKE;
+ break;
+ case eModifierType_Solidify:
+ data.icon = ICON_MOD_SOLIDIFY;
+ break;
+ case eModifierType_Screw:
+ data.icon = ICON_MOD_SCREW;
+ break;
+ case eModifierType_Remesh:
+ data.icon = ICON_MOD_REMESH;
+ break;
+ case eModifierType_WeightVGEdit:
+ case eModifierType_WeightVGMix:
+ case eModifierType_WeightVGProximity:
+ data.icon = ICON_MOD_VERTEX_WEIGHT;
+ break;
+ case eModifierType_DynamicPaint:
+ data.icon = ICON_MOD_DYNAMICPAINT;
+ break;
+ case eModifierType_Ocean:
+ data.icon = ICON_MOD_OCEAN;
+ break;
+ case eModifierType_Warp:
+ data.icon = ICON_MOD_WARP;
+ break;
+ case eModifierType_Skin:
+ data.icon = ICON_MOD_SKIN;
+ break;
+ case eModifierType_Triangulate:
+ data.icon = ICON_MOD_TRIANGULATE;
+ break;
+ case eModifierType_MeshCache:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_MeshSequenceCache:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_Wireframe:
+ data.icon = ICON_MOD_WIREFRAME;
+ break;
+ case eModifierType_LaplacianDeform:
+ data.icon = ICON_MOD_MESHDEFORM; /* XXX, needs own icon */
+ break;
+ case eModifierType_DataTransfer:
+ data.icon = ICON_MOD_DATA_TRANSFER;
+ break;
+ case eModifierType_NormalEdit:
+ case eModifierType_WeightedNormal:
+ data.icon = ICON_MOD_NORMALEDIT;
+ break;
+ case eModifierType_Hair:
+ data.icon = ICON_STRANDS;
+ break;
+ /* Default */
+ case eModifierType_None:
+ case eModifierType_ShapeKey:
+
+ case NUM_MODIFIER_TYPES:
+ data.icon = ICON_DOT;
+ break;
+ }
+ }
+ else {
+ /* grease pencil modifiers */
+ GpencilModifierData *md = BLI_findlink(&ob->greasepencil_modifiers, tselem->nr);
+ switch ((GpencilModifierType)md->type) {
+ case eGpencilModifierType_Noise:
+ data.icon = ICON_RNDCURVE;
+ break;
+ case eGpencilModifierType_Subdiv:
+ data.icon = ICON_MOD_SUBSURF;
+ break;
+ case eGpencilModifierType_Thick:
+ data.icon = ICON_MAN_ROT;
+ break;
+ case eGpencilModifierType_Tint:
+ data.icon = ICON_COLOR;
+ break;
+ case eGpencilModifierType_Instance:
+ data.icon = ICON_MOD_ARRAY;
+ break;
+ case eGpencilModifierType_Build:
+ data.icon = ICON_MOD_BUILD;
+ break;
+ case eGpencilModifierType_Opacity:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case eGpencilModifierType_Color:
+ data.icon = ICON_GROUP_VCOL;
+ break;
+ case eGpencilModifierType_Lattice:
+ data.icon = ICON_MOD_LATTICE;
+ break;
+ case eGpencilModifierType_Mirror:
+ data.icon = ICON_MOD_MIRROR;
+ break;
+ case eGpencilModifierType_Simplify:
+ data.icon = ICON_MOD_DECIM;
+ break;
+ case eGpencilModifierType_Smooth:
+ data.icon = ICON_MOD_SMOOTH;
+ break;
+ case eGpencilModifierType_Hook:
+ data.icon = ICON_HOOK;
+ break;
+ case eGpencilModifierType_Offset:
+ data.icon = ICON_MOD_DISPLACE;
+ break;
+
+ /* Default */
+ default:
+ data.icon = ICON_DOT;
+ break;
+ }
}
break;
}
case TSE_POSE_BASE:
- ICON_DRAW(ICON_ARMATURE_DATA);
+ data.icon = ICON_ARMATURE_DATA;
break;
case TSE_POSE_CHANNEL:
- ICON_DRAW(ICON_BONE_DATA);
+ data.icon = ICON_BONE_DATA;
break;
case TSE_PROXY:
- ICON_DRAW(ICON_GHOST);
+ data.icon = ICON_GHOST;
break;
case TSE_R_LAYER_BASE:
- ICON_DRAW(ICON_RENDERLAYERS);
+ data.icon = ICON_RENDERLAYERS;
break;
case TSE_SCENE_OBJECTS_BASE:
- ICON_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE);
+ data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
break;
case TSE_R_LAYER:
- ICON_DRAW(ICON_RENDER_RESULT);
+ data.icon = ICON_RENDER_RESULT;
break;
case TSE_LINKED_LAMP:
- ICON_DRAW(ICON_LIGHT_DATA);
+ data.icon = ICON_LIGHT_DATA;
break;
case TSE_LINKED_MAT:
- ICON_DRAW(ICON_MATERIAL_DATA);
+ data.icon = ICON_MATERIAL_DATA;
break;
case TSE_POSEGRP_BASE:
- ICON_DRAW(ICON_GROUP_BONE);
+ data.icon = ICON_GROUP_BONE;
break;
case TSE_SEQUENCE:
if (te->idcode == SEQ_TYPE_MOVIE)
- ICON_DRAW(ICON_SEQUENCE);
+ data.icon = ICON_SEQUENCE;
else if (te->idcode == SEQ_TYPE_META)
- ICON_DRAW(ICON_DOT);
+ data.icon = ICON_DOT;
else if (te->idcode == SEQ_TYPE_SCENE)
- ICON_DRAW(ICON_SCENE);
+ data.icon = ICON_SCENE;
else if (te->idcode == SEQ_TYPE_SOUND_RAM)
- ICON_DRAW(ICON_SOUND);
+ data.icon = ICON_SOUND;
else if (te->idcode == SEQ_TYPE_IMAGE)
- ICON_DRAW(ICON_IMAGE_COL);
+ data.icon = ICON_IMAGE_COL;
else
- ICON_DRAW(ICON_PARTICLES);
+ data.icon = ICON_PARTICLES;
break;
case TSE_SEQ_STRIP:
- ICON_DRAW(ICON_LIBRARY_DATA_DIRECT);
+ data.icon = ICON_LIBRARY_DATA_DIRECT;
break;
case TSE_SEQUENCE_DUP:
- ICON_DRAW(ICON_OBJECT_DATA);
+ data.icon = 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));
+ data.drag_id = (ID *)te->rnaptr.data;
+ data.icon = RNA_struct_ui_icon(te->rnaptr.type);
}
else {
- int icon = RNA_struct_ui_icon(te->rnaptr.type);
- ICON_DRAW(icon);
+ data.icon = RNA_struct_ui_icon(te->rnaptr.type);
}
break;
case TSE_LAYER_COLLECTION:
case TSE_SCENE_COLLECTION_BASE:
case TSE_VIEW_COLLECTION_BASE:
- ICON_DRAW(ICON_GROUP);
+ {
+ Collection *collection = outliner_collection_from_tree_element(te);
+ if (collection && !(collection->flag & COLLECTION_IS_MASTER)) {
+ data.drag_id = tselem->id;
+ data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
+ }
+
+ data.icon = ICON_GROUP;
break;
+ }
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
-#if 0
case TSE_GP_LAYER:
- tselem_draw_gp_icon_uibut(&arg, tselem->id, te->directdata);
+ {
+ /* indicate whether layer is active */
+ bGPDlayer *gpl = te->directdata;
+ if (gpl->flag & GP_LAYER_ACTIVE) {
+ data.icon = ICON_GREASEPENCIL;
+ }
+ else {
+ data.icon = ICON_DOT;
+ }
break;
-#endif
+ }
default:
- ICON_DRAW(ICON_DOT);
+ data.icon = ICON_DOT;
break;
}
}
else if (tselem->id) {
+ data.drag_id = tselem->id;
+ data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL;
+
if (GS(tselem->id->name) == ID_OB) {
Object *ob = (Object *)tselem->id;
switch (ob->type) {
case OB_LAMP:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHT); break;
+ data.icon = ICON_OUTLINER_OB_LIGHT; break;
case OB_MESH:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_MESH); break;
+ data.icon = ICON_OUTLINER_OB_MESH; break;
case OB_CAMERA:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_CAMERA); break;
+ data.icon = ICON_OUTLINER_OB_CAMERA; break;
case OB_CURVE:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_CURVE); break;
+ data.icon = ICON_OUTLINER_OB_CURVE; break;
case OB_MBALL:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_META); break;
+ data.icon = ICON_OUTLINER_OB_META; break;
case OB_LATTICE:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_LATTICE); break;
+ data.icon = ICON_OUTLINER_OB_LATTICE; break;
case OB_ARMATURE:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_ARMATURE); break;
+ data.icon = ICON_OUTLINER_OB_ARMATURE; break;
case OB_FONT:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_FONT); break;
+ data.icon = ICON_OUTLINER_OB_FONT; break;
case OB_SURF:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_SURFACE); break;
+ data.icon = ICON_OUTLINER_OB_SURFACE; break;
case OB_SPEAKER:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_SPEAKER); break;
+ data.icon = ICON_OUTLINER_OB_SPEAKER; break;
case OB_LIGHTPROBE:
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_LIGHTPROBE); break;
+ data.icon = ICON_OUTLINER_OB_LIGHTPROBE; break;
case OB_EMPTY:
if (ob->dup_group) {
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_GROUP_INSTANCE);
+ data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
}
else {
- ICON_CLICK_DRAW(ICON_OUTLINER_OB_EMPTY);
+ data.icon = ICON_OUTLINER_OB_EMPTY;
}
break;
+ case OB_GPENCIL:
+ data.icon = ICON_OUTLINER_OB_GREASEPENCIL; break;
+ break;
}
}
else {
@@ -1240,101 +1241,129 @@ static void tselem_draw_icon(
*/
switch ((short)GS(tselem->id->name)) {
case ID_SCE:
- tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
+ data.icon = ICON_SCENE_DATA; break;
case ID_ME:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
+ data.icon = ICON_OUTLINER_DATA_MESH; break;
case ID_CU:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
+ data.icon = ICON_OUTLINER_DATA_CURVE; break;
case ID_MB:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
+ data.icon = ICON_OUTLINER_DATA_META; break;
case ID_LT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
+ data.icon = ICON_OUTLINER_DATA_LATTICE; break;
case ID_LA:
{
Lamp *la = (Lamp *)tselem->id;
switch (la->type) {
case LA_LOCAL:
- tselem_draw_icon_uibut(&arg, ICON_LIGHT_POINT); break;
+ data.icon = ICON_LIGHT_POINT; break;
case LA_SUN:
- tselem_draw_icon_uibut(&arg, ICON_LIGHT_SUN); break;
+ data.icon = ICON_LIGHT_SUN; break;
case LA_SPOT:
- tselem_draw_icon_uibut(&arg, ICON_LIGHT_SPOT); break;
+ data.icon = ICON_LIGHT_SPOT; break;
case LA_HEMI:
- tselem_draw_icon_uibut(&arg, ICON_LIGHT_HEMI); break;
+ data.icon = ICON_LIGHT_HEMI; break;
case LA_AREA:
- tselem_draw_icon_uibut(&arg, ICON_LIGHT_AREA); break;
+ data.icon = ICON_LIGHT_AREA; break;
default:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LIGHT); break;
+ data.icon = ICON_OUTLINER_DATA_LIGHT; break;
}
break;
}
case ID_MA:
- tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
+ data.icon = ICON_MATERIAL_DATA; break;
case ID_TE:
- tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
+ data.icon = ICON_TEXTURE_DATA; break;
case ID_IM:
- tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
+ data.icon = ICON_IMAGE_DATA; break;
case ID_SPK:
case ID_SO:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
+ data.icon = ICON_OUTLINER_DATA_SPEAKER; break;
case ID_AR:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
+ data.icon = ICON_OUTLINER_DATA_ARMATURE; break;
case ID_CA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
+ data.icon = ICON_OUTLINER_DATA_CAMERA; break;
case ID_KE:
- tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
+ data.icon = ICON_SHAPEKEY_DATA; break;
case ID_WO:
- tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
+ data.icon = ICON_WORLD_DATA; break;
case ID_AC:
- tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
+ data.icon = ICON_ACTION; break;
case ID_NLA:
- tselem_draw_icon_uibut(&arg, ICON_NLA); break;
+ data.icon = ICON_NLA; break;
case ID_TXT:
- tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
+ data.icon = ICON_SCRIPT; break;
case ID_GR:
- tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
+ data.icon = ICON_GROUP; break;
case ID_LI:
if (tselem->id->tag & LIB_TAG_MISSING) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
+ data.icon = ICON_LIBRARY_DATA_BROKEN;
}
else if (((Library *)tselem->id)->parent) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
+ data.icon = ICON_LIBRARY_DATA_INDIRECT;
}
else {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
+ data.icon = ICON_LIBRARY_DATA_DIRECT;
}
break;
case ID_LS:
- tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
+ data.icon = ICON_LINE_DATA; break;
case ID_GD:
- tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
+ data.icon = ICON_OUTLINER_DATA_GREASEPENCIL; break;
case ID_LP:
{
LightProbe * lp = (LightProbe *)tselem->id;
switch (lp->type) {
case LIGHTPROBE_TYPE_CUBE:
- tselem_draw_icon_uibut(&arg, ICON_LIGHTPROBE_CUBEMAP); break;
+ data.icon = ICON_LIGHTPROBE_CUBEMAP; break;
case LIGHTPROBE_TYPE_PLANAR:
- tselem_draw_icon_uibut(&arg, ICON_LIGHTPROBE_PLANAR); break;
+ data.icon = ICON_LIGHTPROBE_PLANAR; break;
case LIGHTPROBE_TYPE_GRID:
- tselem_draw_icon_uibut(&arg, ICON_LIGHTPROBE_GRID); break;
+ data.icon = ICON_LIGHTPROBE_GRID; break;
default:
- tselem_draw_icon_uibut(&arg, ICON_LIGHTPROBE_CUBEMAP); break;
+ data.icon = ICON_LIGHTPROBE_CUBEMAP; break;
}
break;
}
case ID_BR:
- tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break;
+ data.icon = ICON_BRUSH_DATA; break;
case ID_SCR:
case ID_WS:
- tselem_draw_icon_uibut(&arg, ICON_SPLITSCREEN); break;
+ data.icon = ICON_SPLITSCREEN; break;
default:
break;
}
}
}
-#undef ICON_DRAW
+ return data;
+}
+
+static void tselem_draw_icon(
+ uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
+ float alpha, const bool is_clickable)
+{
+ TreeElementIcon data = tree_element_get_icon(tselem, te);
+
+ if (data.icon == 0) {
+ return;
+ }
+
+ if (!is_clickable || x >= xmax) {
+ /* placement of icons, copied from interface_widgets.c */
+ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+
+ /* restrict column clip... it has been coded by simply overdrawing,
+ * doesnt work for buttons */
+ UI_icon_draw_alpha(x, y, data.icon, alpha);
+ }
+ else {
+ uiDefIconBut(
+ block, UI_BTYPE_LABEL, 0, data.icon, x, y, UI_UNIT_X, UI_UNIT_Y, NULL,
+ 0.0, 0.0, 1.0, alpha,
+ (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->name : "");
+ }
}
/**
@@ -1344,16 +1373,9 @@ static void tselem_draw_icon(
static void outliner_draw_iconrow_number(
const uiFontStyle *fstyle,
int offsx, int ys,
- const eOLDrawState active,
const int num_elements)
{
- float color[4] = {0.4f, 0.4f, 0.4f, 0.9f};
- copy_v3_fl(color, 0.2f);
- if (active != OL_DRAWSEL_NONE) {
- copy_v3_fl(color, 0.65f);
- color[3] = 1.0f;
- }
-
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
float ufac = 0.25f * UI_UNIT_X;
float offset_x = (float) offsx + UI_UNIT_X * 0.35f;
@@ -1417,13 +1439,13 @@ static void outliner_draw_iconrow_doit(
}
/* No inlined icon should be clickable. */
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac, false);
+ tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.8f * alpha_fac, false);
te->xs = *offsx;
te->ys = ys;
te->xend = (short)*offsx + UI_UNIT_X;
if (num_elements > 1) {
- outliner_draw_iconrow_number(fstyle, *offsx, ys, active, num_elements);
+ outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements);
}
(*offsx) += UI_UNIT_X;
}
@@ -1451,23 +1473,19 @@ static int tree_element_id_type_to_index(TreeElement *te)
}
}
+typedef struct MergedIconRow {
+ eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX];
+ int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
+ TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX];
+} MergedIconRow;
+
static void outliner_draw_iconrow(
bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
- ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
+ ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac, MergedIconRow *merged)
{
eOLDrawState active;
const Object *obact = OBACT(view_layer);
- struct {
- eOLDrawState active[INDEX_ID_MAX + OB_TYPE_MAX];
- int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
- TreeElement *tree_element[INDEX_ID_MAX + OB_TYPE_MAX];
- } data = {
- .active = {0},
- .num_elements = {0},
- .tree_element = {NULL},
- };
-
for (TreeElement *te = lb->first; te; te = te->next) {
/* exit drawing early */
if ((*offsx) - UI_UNIT_X > xmax)
@@ -1498,13 +1516,13 @@ static void outliner_draw_iconrow(
}
else {
const int index = tree_element_id_type_to_index(te);
- data.num_elements[index]++;
- if ((data.tree_element[index] == NULL) ||
- (active > data.active[index]))
+ merged->num_elements[index]++;
+ if ((merged->tree_element[index] == NULL) ||
+ (active > merged->active[index]))
{
- data.tree_element[index] = te;
+ merged->tree_element[index] = te;
}
- data.active[index] = MAX2(active, data.active[index]);
+ merged->active[index] = MAX2(active, merged->active[index]);
}
}
@@ -1512,26 +1530,28 @@ static void outliner_draw_iconrow(
if (tselem->type != TSE_R_LAYER) {
outliner_draw_iconrow(
C, block, fstyle, scene, view_layer, soops,
- &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
+ &te->subtree, level + 1, xmax, offsx, ys, alpha_fac, merged);
}
}
- for (int i = 0; i < INDEX_ID_MAX; i++) {
- const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
- /* See tree_element_id_type_to_index for the index logic. */
- int index_base = i;
- if (i > INDEX_ID_OB) {
- index_base += OB_TYPE_MAX;
- }
- for (int j = 0; j < num_subtypes; j++) {
- const int index = index_base + j;
- if (data.num_elements[index] != 0) {
- outliner_draw_iconrow_doit(block,
- data.tree_element[index],
- fstyle,
- xmax, offsx, ys, alpha_fac,
- data.active[index],
- data.num_elements[index]);
+ if (level == 0) {
+ for (int i = 0; i < INDEX_ID_MAX; i++) {
+ const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
+ /* See tree_element_id_type_to_index for the index logic. */
+ int index_base = i;
+ if (i > INDEX_ID_OB) {
+ index_base += OB_TYPE_MAX;
+ }
+ for (int j = 0; j < num_subtypes; j++) {
+ const int index = index_base + j;
+ if (merged->num_elements[index] != 0) {
+ outliner_draw_iconrow_doit(block,
+ merged->tree_element[index],
+ fstyle,
+ xmax, offsx, ys, alpha_fac,
+ merged->active[index],
+ merged->num_elements[index]);
+ }
}
}
}
@@ -1558,7 +1578,7 @@ 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, ViewLayer *view_layer,
ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out,
- int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating)
+ int startx, int *starty, TreeElement **te_edit)
{
TreeStoreElem *tselem;
float ufac = UI_UNIT_X / 20.0f;
@@ -1575,9 +1595,6 @@ static void outliner_draw_tree_element(
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)
@@ -1742,8 +1759,8 @@ static void outliner_draw_tree_element(
/* divider */
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
unsigned char col[4];
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1758,9 +1775,10 @@ static void outliner_draw_tree_element(
immUnbindProgram();
}
+ MergedIconRow merged = {{0}};
outliner_draw_iconrow(
C, block, fstyle, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx,
- *starty, alpha_fac);
+ *starty, alpha_fac, &merged);
GPU_blend(false);
}
@@ -1778,11 +1796,11 @@ static void outliner_draw_tree_element(
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);
+ bool draw_childs_grayed_out = draw_grayed_out || (ten->flag & TE_DRAGGING);
outliner_draw_tree_element(
C, block, fstyle, scene, view_layer,
ar, soops, ten, draw_childs_grayed_out,
- startx + UI_UNIT_X, starty, te_edit, te_floating);
+ startx + UI_UNIT_X, starty, te_edit);
}
}
else {
@@ -1794,54 +1812,6 @@ static void outliner_draw_tree_element(
}
}
-static void outliner_draw_tree_element_floating(
- const ARegion *ar, const TreeElement *te_floating)
-{
- const TreeElement *te_insert = te_floating->drag_data->insert_handle;
- const int line_width = 2;
-
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- int coord_y = te_insert->ys;
- int coord_x = te_insert->xs;
- float col[4];
-
- if (te_insert == te_floating) {
- /* don't draw anything */
- return;
- }
-
- UI_GetThemeColorShade4fv(TH_BACK, -40, col);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_blend(true);
-
- 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;
- }
- immUniformColor4fv(col);
- GPU_line_width(line_width);
-
- immBegin(GWN_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);
- immUniformColor3fvAlpha(col, col[3] * 0.5f);
-
- immBegin(GWN_PRIM_TRI_STRIP, 4);
- immVertex2f(pos, coord_x, coord_y + UI_UNIT_Y);
- immVertex2f(pos, coord_x, coord_y);
- immVertex2f(pos, ar->v2d.cur.xmax, coord_y + UI_UNIT_Y);
- immVertex2f(pos, ar->v2d.cur.xmax, coord_y);
- immEnd();
- }
-
- GPU_blend(false);
- 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,
@@ -1859,7 +1829,7 @@ static void outliner_draw_hierarchy_lines_recursive(
/* For vertical lines between objects. */
y1 = y2 = *starty;
for (te = lb->first; te; te = te->next) {
- bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL);
+ bool draw_childs_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING);
TreeStoreElem *tselem = TREESTORE(te);
if (draw_childs_grayed_out) {
@@ -1904,8 +1874,8 @@ static void outliner_draw_hierarchy_lines_recursive(
static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
{
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
unsigned char col[4];
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1927,8 +1897,8 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
/* selection status */
if (TSELEM_OPEN(tselem, soops)) {
if (tselem->type == TSE_RNA_STRUCT) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immThemeColorShadeAlpha(TH_BACK, -15, -200);
immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
@@ -1940,12 +1910,12 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
if (tselem->type == TSE_RNA_STRUCT) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
immEnd();
@@ -1976,18 +1946,42 @@ static void outliner_draw_highlights_recursive(
immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
}
- /* search match highlights
- * we don't expand items when searching in the datablocks but we
- * still want to highlight any filter matches. */
- if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
- immUniformColor4fv(col_searchmatch);
- immRecti(pos, start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
- }
+ /* highlights */
+ if (tselem->flag & (TSE_DRAG_ANY | TSE_HIGHLIGHTED | TSE_SEARCHMATCH)) {
+ const int end_x = (int)ar->v2d.cur.xmax;
- /* mouse hover highlights */
- 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);
+ if (tselem->flag & TSE_DRAG_ANY) {
+ /* drag and drop highlight */
+ float col[4];
+ UI_GetThemeColorShade4fv(TH_BACK, -40, col);
+
+ if (tselem->flag & TSE_DRAG_BEFORE) {
+ immUniformColor4fv(col);
+ immRecti(pos, start_x, start_y + UI_UNIT_Y - 1, end_x, start_y + UI_UNIT_Y + 1);
+ }
+ else if (tselem->flag & TSE_DRAG_AFTER) {
+ immUniformColor4fv(col);
+ immRecti(pos, start_x, start_y - 1, end_x, start_y + 1);
+ }
+ else {
+ immUniformColor3fvAlpha(col, col[3] * 0.5f);
+ immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ }
+ else {
+ if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
+ /* search match highlights
+ * we don't expand items when searching in the datablocks but we
+ * still want to highlight any filter matches. */
+ immUniformColor4fv(col_searchmatch);
+ immRecti(pos, start_x, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ else if (tselem->flag & TSE_HIGHLIGHTED) {
+ /* mouse hover highlight */
+ immUniformColor4fv(col_highlight);
+ immRecti(pos, 0, start_y + 1, end_x, start_y + UI_UNIT_Y - 1);
+ }
+ }
}
*io_start_y -= UI_UNIT_Y;
@@ -2010,8 +2004,8 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
col_searchmatch[3] = 0.5f;
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
outliner_draw_highlights_recursive(
pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
@@ -2026,7 +2020,6 @@ static void outliner_draw_tree(
TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- TreeElement *te_floating = NULL;
int starty, startx;
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); // only once
@@ -2064,11 +2057,8 @@ static void outliner_draw_tree(
for (TreeElement *te = soops->tree.first; te; te = te->next) {
outliner_draw_tree_element(
C, block, fstyle, scene, view_layer,
- 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);
+ ar, soops, te, (te->flag & TE_DRAGGING) != 0,
+ startx, &starty, te_edit);
}
if (has_restrict_icons) {
@@ -2085,8 +2075,8 @@ static void outliner_back(ARegion *ar)
ystart = (int)ar->v2d.tot.ymax;
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, 6);
@@ -2096,7 +2086,7 @@ static void outliner_back(ARegion *ar)
int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
if (tot > 0) {
- immBegin(GWN_PRIM_TRIS, 6 * tot);
+ immBegin(GPU_PRIM_TRIS, 6 * tot);
while (tot--) {
y1 -= 2 * UI_UNIT_Y;
y2 = y1 + UI_UNIT_Y;
@@ -2117,10 +2107,10 @@ static void outliner_draw_restrictcols(ARegion *ar)
{
GPU_line_width(1.0f);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax);
immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymin);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index d9bcf05fa29..e895ff53bc5 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -90,73 +90,17 @@
#include "outliner_intern.h"
/* ************************************************************** */
-/* Unused Utilities */
-// XXX: where to place these?
-
-/* This is not used anywhere at the moment */
-#if 0
-static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- /* check if this tree-element was the one we're seeking */
- if (te == teFind) {
- *found = 1;
- return;
- }
-
- /* try to see if sub-tree contains it then */
- outliner_open_reveal(soops, &te->subtree, teFind, found);
- if (*found) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_CLOSED)
- tselem->flag &= ~TSE_CLOSED;
- return;
- }
- }
-}
-#endif
-
-static TreeElement *outliner_dropzone_element(TreeElement *te, const float fmval[2], const bool children)
-{
- if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
- /* name and first icon */
- if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend))
- return te;
- }
- /* Not it. Let's look at its children. */
- if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) {
- for (te = te->subtree.first; te; te = te->next) {
- TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
- if (te_valid)
- return te_valid;
- }
- }
- return NULL;
-}
-
-/* Used for drag and drop parenting */
-TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const bool children)
-{
- TreeElement *te;
-
- for (te = soops->tree.first; te; te = te->next) {
- TreeElement *te_valid = outliner_dropzone_element(te, fmval, children);
- if (te_valid)
- return te_valid;
- }
- return NULL;
-}
-
-
-/* ************************************************************** */
/* Highlight --------------------------------------------------- */
static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
+ /* Drag and drop does own highlighting. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->drags.first) {
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
@@ -165,7 +109,7 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
bool changed = false;
if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
- changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false);
+ changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
if (hovered_te) {
hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
changed = true;
@@ -1951,474 +1895,3 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
-/* ************************************************************** */
-/* DRAG AND DROP OPERATORS */
-
-/* ******************** Parent Drop Operator *********************** */
-
-static int parent_drop_exec(bContext *C, wmOperator *op)
-{
- Object *par = NULL, *ob = NULL;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int partype = -1;
- char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
-
- partype = RNA_enum_get(op->ptr, "type");
- RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
-
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
- }
-
- ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Object *par = NULL;
- Object *ob = NULL;
- SpaceOops *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = NULL;
- TreeElement *te = NULL;
- char childname[MAX_ID_NAME];
- char parname[MAX_ID_NAME];
- int partype = 0;
- float fmval[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- /* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, true);
-
- if (te) {
- RNA_string_set(op->ptr, "parent", te->name);
- /* Identify parent and child */
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
- RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname);
-
- if (ELEM(NULL, ob, par)) {
- if (par == NULL) printf("par==NULL\n");
- return OPERATOR_CANCELLED;
- }
- if (ob == par) {
- return OPERATOR_CANCELLED;
- }
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
- }
-
- scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
-
- if (scene == NULL) {
- /* currently outlier organized in a way, that if there's no parent scene
- * element for object it means that all displayed objects belong to
- * active scene and parenting them is allowed (sergey)
- */
-
- scene = CTX_data_scene(C);
- }
-
- if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
- if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- }
- }
- else {
- /* Menu creation */
- 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;
-
- /* Cannot use uiItemEnumO()... have multiple properties to set. */
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_OBJECT);
-
- /* par becomes parent, make the associated menus */
- if (par->type == OB_ARMATURE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_ARMATURE);
-
- uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- 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 Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- 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 Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- 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_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_BONE);
- }
- else if (par->type == OB_CURVE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_CURVE);
-
- uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_FOLLOW);
-
- uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
- }
- else if (par->type == OB_LATTICE) {
- uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr);
- RNA_string_set(&ptr, "parent", parname);
- RNA_string_set(&ptr, "child", childname);
- RNA_enum_set(&ptr, "type", PAR_LATTICE);
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
- }
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_parent_drop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Drop to Set Parent";
- ot->description = "Drag to parent in Outliner";
- ot->idname = "OUTLINER_OT_parent_drop";
-
- /* api callbacks */
- ot->invoke = parent_drop_invoke;
- ot->exec = parent_drop_exec;
-
- ot->poll = ED_operator_outliner_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
- RNA_def_string(ot->srna, "parent", "Object", MAX_ID_NAME, "Parent", "Parent Object");
- RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
-}
-
-static bool outliner_parenting_poll(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- if (soops) {
- if (soops->outlinevis == SO_SCENES) {
- return true;
- }
- else if ((soops->outlinevis == SO_VIEW_LAYER) &&
- (soops->filter & SO_FILTER_NO_COLLECTION))
- {
- return true;
- }
- }
-
- return false;
-}
-
-static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- Main *bmain = CTX_data_main(C);
- Object *ob = NULL;
- SpaceOops *soops = CTX_wm_space_outliner(C);
- char obname[MAX_ID_NAME];
-
- RNA_string_get(op->ptr, "dragged_obj", obname);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname);
-
- /* search forwards to find the object */
- outliner_find_id(soops, &soops->tree, (ID *)ob);
-
- ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_parent_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Drop to Clear Parent";
- ot->description = "Drag to clear parent in Outliner";
- ot->idname = "OUTLINER_OT_parent_clear";
-
- /* api callbacks */
- ot->invoke = parent_clear_invoke;
-
- ot->poll = outliner_parenting_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_string(ot->srna, "dragged_obj", "Object", MAX_ID_NAME, "Child", "Child Object");
- RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
-}
-
-static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Scene *scene = NULL;
- Object *ob = NULL;
- SpaceOops *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Main *bmain = CTX_data_main(C);
- TreeElement *te = NULL;
- char obname[MAX_ID_NAME];
- float fmval[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- /* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, false);
-
- if (te) {
- RNA_string_set(op->ptr, "scene", te->name);
- scene = (Scene *)BKE_libblock_find_name(bmain, ID_SCE, te->name);
-
- RNA_string_get(op->ptr, "object", obname);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname);
-
- if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) {
- return OPERATOR_CANCELLED;
- }
-
- if (BKE_scene_has_object(scene, ob)) {
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection;
- if (scene != CTX_data_scene(C)) {
- /* when linking to an inactive scene link to the master collection */
- collection = BKE_collection_master(scene);
- }
- else {
- collection = CTX_data_collection(C);
- }
-
- BKE_collection_object_add(bmain, collection, ob);
-
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
-
- DEG_relations_tag_update(bmain);
-
- DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
-}
-
-void OUTLINER_OT_scene_drop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Drop Object to Scene";
- ot->description = "Drag object to scene in Outliner";
- ot->idname = "OUTLINER_OT_scene_drop";
-
- /* api callbacks */
- ot->invoke = scene_drop_invoke;
-
- ot->poll = ED_operator_outliner_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
- RNA_def_string(ot->srna, "scene", "Scene", MAX_ID_NAME, "Scene", "Target Scene");
-}
-
-static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Material *ma = NULL;
- Object *ob = NULL;
- Main *bmain = CTX_data_main(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- TreeElement *te = NULL;
- char mat_name[MAX_ID_NAME - 2];
- float fmval[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- /* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, true);
-
- if (te) {
- RNA_string_set(op->ptr, "object", te->name);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, te->name);
-
- RNA_string_get(op->ptr, "material", mat_name);
- ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, mat_name);
-
- if (ELEM(NULL, ob, ma)) {
- return OPERATOR_CANCELLED;
- }
-
- assign_material(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
-}
-
-void OUTLINER_OT_material_drop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Drop Material on Object";
- ot->description = "Drag material to object in Outliner";
- ot->idname = "OUTLINER_OT_material_drop";
-
- /* api callbacks */
- ot->invoke = material_drop_invoke;
-
- ot->poll = ED_operator_outliner_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
- RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
-}
-
-/* ******************** Collection Drop Operator *********************** */
-
-static int collection_drop_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
-{
- /* TODO: implement */
-#if 0
- Object *par = NULL, *ob = NULL;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int partype = -1;
- char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
-
- RNA_string_get(op->ptr, "parent", parname);
- par = (Object *)BKE_libblock_find_name(ID_OB, parname);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
-
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
- }
-
- ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
-#endif
-
- return OPERATOR_FINISHED;
-}
-
-static int collection_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
- Main *bmain = CTX_data_main(C);
- char childname[MAX_ID_NAME];
- float fmval[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- /* Find object hovered over */
- TreeElement *te = outliner_dropzone_find(soops, fmval, true);
-
- if (!te || !outliner_is_collection_tree_element(te)) {
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection = outliner_collection_from_tree_element(te);
-
- // TODO: don't use scene, makes no sense anymore
- // TODO: move rather than link, change hover text
- Scene *scene = BKE_scene_find_from_collection(bmain, collection);
- BLI_assert(scene);
- RNA_string_get(op->ptr, "child", childname);
- Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname);
- BKE_collection_object_add(bmain, collection, ob);
-
- DEG_id_tag_update(&collection->id, DEG_TAG_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_drop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Link to Collection"; // TODO: rename to move?
- ot->description = "Drag to move to collection in Outliner";
- ot->idname = "OUTLINER_OT_collection_drop";
-
- /* api callbacks */
- ot->invoke = collection_drop_invoke;
- ot->exec = collection_drop_exec;
-
- ot->poll = ED_operator_outliner_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
-
- /* properties */
- RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
- RNA_def_string(ot->srna, "parent", "Collection", MAX_ID_NAME, "Parent", "Parent Collection");
-}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 093ad9361c2..f8dc41b8d37 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -67,23 +67,6 @@ typedef enum TreeTraversalAction {
TRAVERSE_SKIP_CHILDS,
} TreeTraversalAction;
-/**
- * Callback type for reinserting elements at a different position, used to allow user customizable element order.
- */
-typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
- struct Scene *scene,
- struct SpaceOops *soops,
- struct TreeElement *insert_element,
- struct TreeElement *insert_handle,
- TreeElementInsertType action,
- const struct wmEvent *event);
-/**
- * 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 TreeElement *insert_element,
- struct TreeElement **io_insert_handle, TreeElementInsertType *io_action);
typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata);
@@ -99,19 +82,13 @@ typedef struct TreeElement {
const char *name;
void *directdata; // Armature Bones, Base, Sequence, Strip...
PointerRNA rnaptr; // RNA Pointer
-
- /* 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;
- void *tooltip_draw_handle;
- } *drag_data;
} TreeElement;
+typedef struct TreeElementIcon {
+ struct ID *drag_id, *drag_parent;
+ int icon;
+} TreeElementIcon;
+
#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) || \
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS, ID_LP) || \
@@ -126,6 +103,7 @@ enum {
TE_LAZY_CLOSED = (1 << 2),
TE_FREE_NAME = (1 << 3),
TE_DISABLED = (1 << 4),
+ TE_DRAGGING = (1 << 5),
};
/* button events */
@@ -209,6 +187,8 @@ TreeTraversalAction outliner_find_selected_objects(struct TreeElement *te, void
void draw_outliner(const struct bContext *C);
void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag);
+TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te);
+
/* outliner_select.c -------------------------------------------- */
eOLDrawState tree_element_type_active(
struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct SpaceOops *soops,
@@ -284,10 +264,18 @@ void item_object_mode_exit_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene,
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
-
void outliner_set_coordinates(struct ARegion *ar, struct SpaceOops *soops);
+/* outliner_dragdrop.c */
+void outliner_dropboxes(void);
+
+void OUTLINER_OT_item_drag_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
+void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_drop(struct wmOperatorType *ot);
+
/* ...................................................... */
void OUTLINER_OT_highlight_update(struct wmOperatorType *ot);
@@ -319,12 +307,6 @@ void OUTLINER_OT_drivers_delete_selected(struct wmOperatorType *ot);
void OUTLINER_OT_orphans_purge(struct wmOperatorType *ot);
-void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
-void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_drop(struct wmOperatorType *ot);
-
/* outliner_tools.c ---------------------------------------------- */
void OUTLINER_OT_operation(struct wmOperatorType *ot);
@@ -358,7 +340,11 @@ void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_clear(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_holdout_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_holdout_clear(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_indirect_only_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_indirect_only_clear(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 0dd492839c9..34d79ea5a61 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -55,353 +55,6 @@
#include "outliner_intern.h"
-typedef struct OutlinerDragDropTooltip {
- TreeElement *te;
- void *handle;
-} OutlinerDragDropTooltip;
-
-enum {
- OUTLINER_ITEM_DRAG_CANCEL,
- OUTLINER_ITEM_DRAG_CONFIRM,
-};
-
-static bool 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_VIEW_LAYER, SO_LIBRARIES);
-}
-
-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(wmWindow *win, OutlinerDragDropTooltip *data)
-{
- MEM_SAFE_FREE(data->te->drag_data);
-
- if (data->handle) {
- WM_draw_cb_exit(win, data->handle);
- }
-
- MEM_SAFE_FREE(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(
- 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(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;
-}
-
-/**
- * Returns true if it is a collection and empty.
- */
-static bool is_empty_collection(TreeElement *te)
-{
- Collection *collection = outliner_collection_from_tree_element(te);
-
- if (!collection) {
- return false;
- }
-
- return BLI_listbase_is_empty(&collection->gobject) &&
- BLI_listbase_is_empty(&collection->children);
-}
-
-static bool outliner_item_drag_drop_apply(
- Main *bmain,
- Scene *scene,
- SpaceOops *soops,
- OutlinerDragDropTooltip *data,
- const wmEvent *event)
-{
- TreeElement *dragged_te = data->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(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);
-
- /* If the collection was just created and you moved objects/collections inside it,
- * it is strange to have it closed and we not see the newly dragged elements. */
- const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle);
-
- dragged_te->reinsert(bmain, scene, soops, dragged_te, insert_handle, insert_type, event);
-
- if (should_open_collection && !is_empty_collection(insert_handle)) {
- TREESTORE(insert_handle)->flag &= ~TSE_CLOSED;
- }
- return true;
- }
-
- return false;
-}
-
-static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- OutlinerDragDropTooltip *data = op->customdata;
- TreeElement *te_dragged = data->te;
- 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(bmain, scene, soops, data, event)) {
- 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(CTX_wm_window(C), data);
- redraw = true;
- break;
- case MOUSEMOVE:
- outliner_item_drag_handle(soops, ar, event, te_dragged);
- redraw = true;
- break;
- }
-
- if (redraw) {
- if (skip_rebuild) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
- else {
- ED_region_tag_redraw(ar);
- }
- }
-
- return retval;
-}
-
-static const char *outliner_drag_drop_tooltip_get(
- const TreeElement *te_float)
-{
- const char *name = NULL;
-
- const TreeElement *te_insert = te_float->drag_data->insert_handle;
- if (te_float && outliner_is_collection_tree_element(te_float)) {
- if (te_insert == NULL) {
- name = TIP_("Move collection");
- }
- else {
- switch (te_float->drag_data->insert_type) {
- case TE_INSERT_BEFORE:
- if (te_insert->prev && outliner_is_collection_tree_element(te_insert->prev)) {
- name = TIP_("Move between collections");
- }
- else {
- name = TIP_("Move before collection");
- }
- break;
- case TE_INSERT_AFTER:
- if (te_insert->next && outliner_is_collection_tree_element(te_insert->next)) {
- name = TIP_("Move between collections");
- }
- else {
- name = TIP_("Move after collection");
- }
- break;
- case TE_INSERT_INTO:
- name = TIP_("Move inside collection");
- break;
- }
- }
- }
- else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) {
- name = TIP_("Move to collection (Ctrl to link)");
- }
-
- return name;
-}
-
-static void outliner_drag_drop_tooltip_cb(const wmWindow *win, void *vdata)
-{
- OutlinerDragDropTooltip *data = vdata;
- const char *tooltip;
-
- int cursorx, cursory;
- int x, y;
-
- tooltip = outliner_drag_drop_tooltip_get(data->te);
- if (tooltip == NULL) {
- return;
- }
-
- cursorx = win->eventstate->x;
- cursory = win->eventstate->y;
-
- x = cursorx + U.widget_unit;
- y = cursory - U.widget_unit;
-
- /* Drawing. */
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
-
- const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
-
- GPU_blend(true);
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y, tooltip, col_fg, col_bg);
- GPU_blend(false);
-}
-
-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);
- }
-
- OutlinerDragDropTooltip *data = MEM_mallocN(sizeof(OutlinerDragDropTooltip), __func__);
- data->te = te_dragged;
-
- op->customdata = data;
- 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_flag_set(&soops->tree, TSE_HIGHLIGHTED, false);
-
- ED_region_tag_redraw_no_rebuild(ar);
-
- WM_event_add_modal_handler(C, op);
-
- data->handle = WM_draw_cb_activate(CTX_wm_window(C), outliner_drag_drop_tooltip_cb, data);
-
- 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";
- 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)
@@ -457,37 +110,11 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_link);
WM_operatortype_append(OUTLINER_OT_collection_instance);
WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
- WM_operatortype_append(OUTLINER_OT_collection_include_set);
-}
-
-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 Drag & 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;
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_clear);
+ WM_operatortype_append(OUTLINER_OT_collection_holdout_set);
+ WM_operatortype_append(OUTLINER_OT_collection_holdout_clear);
+ WM_operatortype_append(OUTLINER_OT_collection_indirect_only_set);
+ WM_operatortype_append(OUTLINER_OT_collection_indirect_only_clear);
}
void outliner_keymap(wmKeyConfig *keyconf)
@@ -570,12 +197,13 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "OUTLINER_OT_collection_exclude_set", EKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OUTLINER_OT_collection_exclude_clear", EKEY, KM_PRESS, KM_ALT, 0);
+
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "select", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
-
- 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 7ab13f36953..ec5e11520a6 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -39,6 +39,7 @@
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_world_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
@@ -46,9 +47,11 @@
#include "BKE_armature.h"
#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_gpencil.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_workspace.h"
@@ -60,6 +63,7 @@
#include "ED_screen.h"
#include "ED_sequencer.h"
#include "ED_undo.h"
+#include "ED_gpencil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -470,6 +474,28 @@ static eOLDrawState tree_element_active_defgroup(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState UNUSED_FUNCTION(tree_element_active_gplayer)(
+ bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+{
+ bGPdata *gpd = (bGPdata *)tselem->id;
+ bGPDlayer *gpl = te->directdata;
+
+ /* We can only have a single "active" layer at a time
+ * and there must always be an active layer...
+ */
+ if (set != OL_SETSEL_NONE) {
+ if (gpl) {
+ BKE_gpencil_layer_setactive(gpd, gpl);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
+ }
+ }
+ else {
+ return OL_DRAWSEL_NORMAL;
+ }
+
+ return OL_DRAWSEL_NONE;
+}
+
static eOLDrawState tree_element_active_posegroup(
bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
@@ -1006,6 +1032,10 @@ static void do_outliner_item_activate_tree_element(
}
}
}
+ else if (ELEM(te->idcode, ID_GD)) {
+ /* set grease pencil to object mode */
+ WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
else { // rest of types
tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 28890e42139..55a437d6ad5 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -319,112 +319,11 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
if (outliner_animdata_test(sce->adt))
outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
- /* Grease Pencil */
- outliner_add_element(soops, lb, sce->gpd, te, 0, 0);
-}
-
-TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
-{
- struct ObjectsSelectedData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- if (outliner_is_collection_tree_element(te)) {
- return TRAVERSE_CONTINUE;
- }
-
- if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
- return TRAVERSE_SKIP_CHILDS;
- }
-
- BLI_addtail(&data->objects_selected_array, BLI_genericNodeN(te));
-
- return TRAVERSE_CONTINUE;
-}
-
-/**
- * Move objects from a collection to another.
- * We ignore the original object being inserted, we used it for polling only.
- * Instead we move all the selected objects around.
- */
-static void outliner_object_reorder(
- Main *bmain, Scene *scene,
- SpaceOops *soops,
- TreeElement *insert_element,
- TreeElement *insert_handle, TreeElementInsertType action,
- const wmEvent *event)
-{
- Collection *collection = outliner_collection_from_tree_element(insert_handle);
- Collection *collection_ob_parent = NULL;
- ID *id = insert_handle->store_elem->id;
-
- BLI_assert(action == TE_INSERT_INTO);
- UNUSED_VARS_NDEBUG(action);
-
- struct ObjectsSelectedData data = {
- .objects_selected_array = {NULL, NULL},
- };
-
- const bool is_append = event->ctrl;
-
- /* Make sure we include the originally inserted element as well. */
- TREESTORE(insert_element)->flag |= TSE_SELECTED;
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *ten_selected = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(ten_selected)->id;
-
- if (is_append) {
- BKE_collection_object_add(bmain, collection, ob);
- continue;
- }
-
- /* Find parent collection of object. */
- if (ten_selected->parent) {
- for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
- if (outliner_is_collection_tree_element(te_ob_parent)) {
- collection_ob_parent = outliner_collection_from_tree_element(te_ob_parent);
- break;
- }
- }
- }
- else {
- collection_ob_parent = BKE_collection_master(scene);
- }
-
- BKE_collection_object_move(bmain, scene, collection, collection_ob_parent, ob);
- }
-
- BLI_freelistN(&data.objects_selected_array);
-
- DEG_relations_tag_update(bmain);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-}
-
-static bool outliner_object_reorder_poll(
- const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *io_action)
-{
- if (outliner_is_collection_tree_element(*io_insert_handle) &&
- (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);
@@ -1387,80 +1286,6 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
-static void outliner_collections_reorder(
- Main *bmain,
- Scene *UNUSED(scene),
- SpaceOops *soops,
- TreeElement *insert_element,
- TreeElement *insert_handle,
- TreeElementInsertType action,
- const wmEvent *UNUSED(event))
-{
- TreeElement *from_parent_te, *to_parent_te;
- Collection *from_parent, *to_parent;
-
- Collection *collection = outliner_collection_from_tree_element(insert_element);
- Collection *relative = NULL;
- bool relative_after = false;
-
- from_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_element);
- from_parent = (from_parent_te) ? outliner_collection_from_tree_element(from_parent_te) : NULL;
-
- if (ELEM(action, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
- to_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_handle);
- to_parent = (to_parent_te) ? outliner_collection_from_tree_element(to_parent_te) : NULL;
-
- relative = outliner_collection_from_tree_element(insert_handle);
- relative_after = (action == TE_INSERT_AFTER);
- }
- else if (action == TE_INSERT_INTO) {
- to_parent = outliner_collection_from_tree_element(insert_handle);
- }
- else {
- BLI_assert(0);
- return;
- }
-
- if (!to_parent) {
- return;
- }
-
- BKE_collection_move(bmain, to_parent, from_parent, relative, relative_after, collection);
-
- DEG_relations_tag_update(bmain);
-}
-
-static bool outliner_collections_reorder_poll(
- const TreeElement *insert_element,
- TreeElement **io_insert_handle,
- TreeElementInsertType *io_action)
-{
- /* Can't move master collection. */
- Collection *collection = outliner_collection_from_tree_element(insert_element);
- if (collection->flag & COLLECTION_IS_MASTER) {
- return false;
- }
-
- /* Can only move into collections. */
- Collection *collection_handle = outliner_collection_from_tree_element(*io_insert_handle);
- if (collection_handle == NULL) {
- return false;
- }
-
- /* We can't insert/before after master collection. */
- if (collection_handle->flag & COLLECTION_IS_MASTER) {
- 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 = (*io_insert_handle)->subtree.last;
- }
- }
-
- return true;
-}
-
static void outliner_add_layer_collection_objects(
SpaceOops *soops, ListBase *tree, ViewLayer *layer,
LayerCollection *lc, TreeElement *ten)
@@ -1487,8 +1312,6 @@ static void outliner_add_layer_collections_recursive(
ten->name = id->name + 2;
ten->directdata = lc;
- ten->reinsert = outliner_collections_reorder;
- ten->reinsert_poll = outliner_collections_reorder_poll;
const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
if (exclude ||
@@ -1530,8 +1353,6 @@ BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collec
}
te->directdata = collection;
- te->reinsert = outliner_collections_reorder;
- te->reinsert_poll = outliner_collections_reorder_poll;
}
BLI_INLINE void outliner_add_collection_objects(
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index e4e99f88bf4..b0d63aee7c0 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -93,196 +93,6 @@ static void outliner_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static bool outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- 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) {
- /* pass */
- }
- else if (te->idcode == ID_OB && tselem->type == 0) {
- Scene *scene;
- ID *te_id = tselem->id;
-
- /* check if dropping self or parent */
- if (te_id == id || (Object *)te_id == ((Object *)id)->parent)
- return 0;
-
- /* check that parent/child are both in the same scene */
- scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
-
- /* currently outliner organized in a way that if there's no parent scene
- * element for object it means that all displayed objects belong to
- * active scene and parenting them is allowed (sergey)
- */
- if (!scene) {
- return 1;
- }
- else {
- for (ViewLayer *view_layer = scene->view_layers.first;
- view_layer;
- view_layer = view_layer->next)
- {
- if (BKE_view_layer_base_find(view_layer, (Object *)id)) {
- return 1;
- }
- }
- }
- }
- }
- }
- return 0;
-}
-
-static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
-{
- ID *id = drag->poin;
-
- RNA_string_set(drop->ptr, "child", id->name + 2);
-}
-
-static bool outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = NULL;
- float fmval[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
- return false;
- }
-
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_OB) {
- if (((Object *)id)->parent) {
- if ((te = outliner_dropzone_find(soops, fmval, true))) {
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (te->idcode) {
- case ID_SCE:
- return (ELEM(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER));
- case ID_OB:
- return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
- /* Other codes to ignore? */
- }
- }
- return (te == NULL);
- }
- }
- }
- return 0;
-}
-
-static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
-{
- ID *id = drag->poin;
- RNA_string_set(drop->ptr, "dragged_obj", id->name + 2);
-
- /* Set to simple parent clear type. Avoid menus for drag and drop if possible.
- * If desired, user can toggle the different "Clear Parent" types in the operator
- * menu on tool shelf. */
- RNA_enum_set(drop->ptr, "type", 0);
-}
-
-static bool outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_OB) {
- /* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, false);
- return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0);
- }
- }
- return 0;
-}
-
-static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop)
-{
- ID *id = drag->poin;
-
- RNA_string_set(drop->ptr, "object", id->name + 2);
-}
-
-static bool outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_MA) {
- /* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0);
- }
- }
- return 0;
-}
-
-static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
-{
- ID *id = drag->poin;
-
- RNA_string_set(drop->ptr, "material", id->name + 2);
-}
-
-static bool outliner_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
-
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (ELEM(GS(id->name), ID_OB, ID_GR)) {
- /* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- return (te && outliner_is_collection_tree_element(te));
- }
- }
- return 0;
-}
-
-static void outliner_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
-{
- ID *id = drag->poin;
- RNA_string_set(drop->ptr, "child", id->name + 2);
-}
-
-/* region dropbox definition */
-static void outliner_dropboxes(void)
-{
- ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
-
- WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", outliner_parent_drop_poll, outliner_parent_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", outliner_collection_drop_poll, outliner_collection_drop_copy);
-}
-
static void outliner_main_region_draw(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 5d2ceced904..3cd5bfc3e58 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -627,7 +627,7 @@ static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
op->customdata = NULL;
}
-static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop, void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
@@ -693,7 +693,7 @@ static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index a10eda5c3e6..864609e4157 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -232,9 +232,9 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
BLI_spin_lock(sound->spinlock);
if (!sound->waveform) {
- if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
+ if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) {
/* prevent sounds from reloading */
- sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
+ sound->tags |= SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
sequencer_preview_add_sound(C, seq);
}
@@ -267,7 +267,7 @@ static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *s
GPU_blend(true);
- immBegin(GWN_PRIM_TRI_STRIP, length * 2);
+ immBegin(GPU_PRIM_TRI_STRIP, length * 2);
for (i = 0; i < length; i++) {
float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep;
@@ -343,7 +343,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
col[3] = 196; /* alpha, used for all meta children */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -457,7 +457,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
immUniformColor4ub(0, 0, 0, 50);
}
- immBegin(GWN_PRIM_TRIS, 3);
+ immBegin(GPU_PRIM_TRIS, 3);
immVertex2fv(pos, v1);
immVertex2fv(pos, v2);
immVertex2fv(pos, v3);
@@ -719,7 +719,7 @@ 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;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -781,7 +781,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
if (seq->flag & SEQ_LOCK) {
GPU_blend(true);
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.125f);
@@ -799,7 +799,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
if (!BKE_sequence_is_valid_check(seq)) {
GPU_blend(true);
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
immUniform4f("color1", 1.0f, 0.0f, 0.0f, 1.0f);
@@ -834,7 +834,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* TODO: add back stippled line for muted strips? */
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1040,7 +1040,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
GPU_line_width(1.0f);
/* border */
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -1230,9 +1230,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* Format needs to be created prior to any immBindProgram call.
* Do it here because OCIO binds it's own shader.
*/
- Gwn_VertFormat *imm_format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *imm_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (scope) {
IMB_freeImBuf(ibuf);
@@ -1308,8 +1308,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (draw_backdrop) {
/* XXX: need to load identity projection too? */
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
}
glGenTextures(1, (GLuint *)&texid);
@@ -1331,7 +1331,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
immUniform1i("image", 0);
}
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
if (draw_overlay) {
if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
@@ -1439,7 +1439,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
if (draw_backdrop) {
- gpuPopMatrix();
+ GPU_matrix_pop();
return;
}
@@ -1514,7 +1514,7 @@ static void draw_seq_backdrop(View2D *v2d)
{
int i;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* darker gray overlay over the view backdrop */
@@ -1541,7 +1541,7 @@ static void draw_seq_backdrop(View2D *v2d)
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
int line_len = (int)v2d->cur.ymax - i + 1;
immUniformThemeColor(TH_GRID);
- immBegin(GWN_PRIM_LINES, line_len * 2);
+ immBegin(GPU_PRIM_LINES, line_len * 2);
while (line_len--) {
immVertex2f(pos, v2d->cur.xmax, i);
immVertex2f(pos, v2d->cur.xmin, i);
@@ -1593,7 +1593,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
const Sequence *seq = special_seq_update;
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(255, 255, 255, 48);
@@ -1613,7 +1613,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* draw darkened area outside of active timeline
@@ -1631,7 +1631,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, frame_sta, v2d->cur.ymin);
immVertex2f(pos, frame_sta, v2d->cur.ymax);
@@ -1649,7 +1649,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -40);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin);
immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax);
@@ -1735,12 +1735,12 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
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;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3f(0.2f, 0.2f, 0.2f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, cfra_over, v2d->cur.ymin);
immVertex2f(pos, cfra_over, v2d->cur.ymax);
immEnd();
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index cefc6cdd814..199ff06cc8b 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -739,7 +739,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
if (!skip_dup) {
/* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
}
if (seqn) {
@@ -848,7 +848,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
if (!skip_dup) {
/* Duplicate AFTER the first change */
- seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
+ seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
}
if (seqn) {
@@ -2091,6 +2091,7 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
SEQP_BEGIN (ed, seq)
{
+ BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
if (seq->seq1 || seq->seq2 || seq->seq3) {
BKE_sequence_calc(scene, seq);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index c58c05b67c0..ae011e48538 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -96,7 +96,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
/* make sure we cleanup the loading flag! */
BLI_spin_lock(sound->spinlock);
- sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
BLI_mutex_lock(pj->mutex);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 8fb526bf502..11517d64d7a 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -366,7 +366,7 @@ static void sequencer_listener(
/* ************* dropboxes ************* */
-static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -380,7 +380,7 @@ static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
return 0;
}
-static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -393,7 +393,7 @@ static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
return 0;
}
-static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **UNUSED(tooltip))
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index ac43d7de408..f3c55aa3474 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -474,7 +474,7 @@ static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
/* ************* dropboxes ************* */
-static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
@@ -491,18 +491,15 @@ static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "filepath", drag->path);
}
-static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID)
- return true;
-
- return false;
+ return (drag->type == WM_DRAG_ID);
}
static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
{
char *text;
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
/* copy drag path to properties */
text = RNA_path_full_ID_py(id);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 748a5c05ef1..aa499d52589 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -913,7 +913,7 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
float rad;
/* background so highlights don't go behind the scrollbar */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_BACK);
immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
@@ -967,24 +967,24 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
/* Draw panel */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_BACK);
immRecti(pos, x, y, x + boxw, y - boxh);
immUniformThemeColor(TH_SHADE1);
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_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(GWN_PRIM_LINE_LOOP, 3);
+ immBegin(GPU_PRIM_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(GWN_PRIM_LINE_LOOP, 3);
+ immBegin(GPU_PRIM_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);
@@ -1066,7 +1066,7 @@ 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);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_SHADE1);
@@ -1089,7 +1089,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
w = st->cwidth * text_get_char_pos(st, str, len);
if (item == sel) {
- uint posi = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint posi = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_SHADE2);
@@ -1130,7 +1130,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
return;
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* Draw the selection */
@@ -1443,7 +1443,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->showlinenrs) {
x = TXT_OFFSET + TEXTXLOC;
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_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);
@@ -1502,7 +1502,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
margin_column_x = x + st->cwidth * (st->margin_column - st->left);
if (margin_column_x >= x) {
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -1515,7 +1515,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
immUniform1f("dash_width", 2.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2i(shdr_pos, margin_column_x, 0);
immVertex2i(shdr_pos, margin_column_x, ar->winy - 2);
immEnd();
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index e45159124e8..6113922c02e 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -168,6 +168,10 @@ static void topbar_main_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(s
if (wmn->data == ND_SPACE_VIEW3D)
ED_region_tag_redraw(ar);
break;
+ case NC_GPENCIL:
+ if (wmn->data == ND_DATA)
+ ED_region_tag_redraw(ar);
+ break;
}
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index beb323fb21c..3649c6f6dbb 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -80,6 +80,7 @@
#include "BKE_subsurf.h"
#include "BKE_unit.h"
#include "BKE_tracking.h"
+#include "BKE_gpencil.h"
#include "BKE_editmesh.h"
@@ -121,10 +122,10 @@
int view3d_effective_drawtype(const struct View3D *v3d)
{
- if (v3d->drawtype == OB_RENDER) {
- return v3d->prev_drawtype;
+ if (v3d->shading.type == OB_RENDER) {
+ return v3d->shading.prev_type;
}
- return v3d->drawtype;
+ return v3d->shading.type;
}
static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
@@ -139,10 +140,10 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
return true;
/* if its drawing textures with zbuf sel, then don't draw dots */
- if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
+ if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE)
return false;
- if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
+ if ((vd->shading.type >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
return false;
return true;
@@ -244,7 +245,7 @@ void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], un
circball_array_fill(verts, cent, rad, tmat);
- immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
for (int i = 0; i < CIRCLE_RESOL; ++i) {
immVertex3fv(pos, verts[i]);
}
@@ -285,15 +286,15 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
if (imm_len == 0) return;
- Gwn_VertFormat *format = immVertexFormat();
- data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat *format = immVertexFormat();
+ data.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ data.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
- immBeginAtMost(GWN_PRIM_POINTS, imm_len);
+ immBeginAtMost(GPU_PRIM_POINTS, imm_len);
dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
immEnd();
@@ -303,9 +304,9 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *UNUSED(dm), int offset)
{
Mesh *me = ob->data;
- Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPUBatch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
#endif
@@ -328,15 +329,15 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
drawBMOffset_userData data;
data.bm = em->bm;
data.offset = offset;
- Gwn_VertFormat *format = immVertexFormat();
- data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat *format = immVertexFormat();
+ data.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ data.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
- immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert);
+ immBeginAtMost(GPU_PRIM_POINTS, em->bm->totvert);
dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
immEnd();
@@ -348,9 +349,9 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
Mesh *me = em->ob->data;
- Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPUBatch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
#endif
@@ -375,20 +376,20 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
data.bm = em->bm;
data.offset = offset;
- Gwn_VertFormat *format = immVertexFormat();
+ GPUVertFormat *format = immVertexFormat();
const int imm_len = dm->getNumEdges(dm) * 2;
if (imm_len == 0) return;
- data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ data.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ data.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
GPU_line_width(1.0f);
- immBeginAtMost(GWN_PRIM_LINES, imm_len);
+ immBeginAtMost(GPU_PRIM_LINES, imm_len);
dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data);
immEnd();
@@ -400,9 +401,9 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
GPU_line_width(1.0f);
Mesh *me = em->ob->data;
- Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPUBatch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
#endif
@@ -420,13 +421,13 @@ static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select
if (imm_len == 0) return;
- Gwn_VertFormat *format = immVertexFormat();
- data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat *format = immVertexFormat();
+ data.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ data.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- immBeginAtMost(GWN_PRIM_TRIS, imm_len);
+ immBeginAtMost(GPU_PRIM_TRIS, imm_len);
if (use_select == false) {
int selcol;
@@ -463,20 +464,20 @@ static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select
static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select)
{
Mesh *me = em->ob->data;
- Gwn_Batch *batch;
+ GPUBatch *batch;
if (use_select) {
batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
else {
int selcol;
GPU_select_index_get(0, &selcol);
batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
- GWN_batch_uniform_1ui(batch, "color", selcol);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
+ GPU_batch_uniform_1ui(batch, "color", selcol);
+ GPU_batch_draw(batch);
}
}
#endif
@@ -499,15 +500,15 @@ static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm)
{
drawBMOffset_userData data; /* don't use offset */
data.bm = em->bm;
- Gwn_VertFormat *format = immVertexFormat();
- data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ GPUVertFormat *format = immVertexFormat();
+ data.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ data.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
GPU_point_size(UI_GetThemeValuef(TH_FACEDOT_SIZE));
- immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface);
+ immBeginAtMost(GPU_PRIM_POINTS, em->bm->totface);
dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP);
immEnd();
@@ -517,9 +518,9 @@ static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm)
static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm))
{
Mesh *me = em->ob->data;
- Gwn_Batch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPUBatch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
#endif
@@ -583,12 +584,12 @@ static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(sce
{
int selcol;
- Gwn_Batch *batch;
+ GPUBatch *batch;
GPU_select_index_get(0, &selcol);
batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
- GWN_batch_uniform_1ui(batch, "color", selcol);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
+ GPU_batch_uniform_1ui(batch, "color", selcol);
+ GPU_batch_draw(batch);
}
G.f |= (G_f_orig & G_BACKBUFSEL);
@@ -601,15 +602,15 @@ static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(sce
static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob)
{
Mesh *me = ob->data;
- Gwn_Batch *batch;
+ GPUBatch *batch;
if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1);
}
else {
batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1);
}
- GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
- GWN_batch_draw(batch);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GPU_batch_draw(batch);
}
void draw_object_backbufsel(
@@ -621,7 +622,7 @@ void draw_object_backbufsel(
select_mode = ts->selectmode;
}
- gpuMultMatrix(ob->obmat);
+ GPU_matrix_mul(ob->obmat);
glClearDepth(1.0); GPU_clear(GPU_DEPTH_BIT);
GPU_depth_test(true);
@@ -688,7 +689,7 @@ void draw_object_backbufsel(
break;
}
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_set(rv3d->viewmat);
}
@@ -747,8 +748,8 @@ void ED_draw_object_facemap(
Mesh *me = ob->data;
const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
if (facemap_data) {
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(col);
@@ -788,7 +789,7 @@ void ED_draw_object_facemap(
/* use gawain immediate mode fore now */
const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
- immBeginAtMost(GWN_PRIM_TRIS, looptris_len * 3);
+ immBeginAtMost(GPU_PRIM_TRIS, looptris_len * 3);
MPoly *mp;
int i;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6d4009e9d2b..98c5c4e604d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -36,6 +36,7 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
#include "MEM_guardedalloc.h"
@@ -251,7 +252,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 */
- gpuMultMatrix(ob->obmat);
+ GPU_matrix_mul(ob->obmat);
}
#ifdef DEBUG
@@ -293,7 +294,7 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
{
wmWindowManager *wm = bmain->wm.first;
- if (v3d->drawtype != OB_RENDER) {
+ if (v3d->shading.type != OB_RENDER) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
@@ -324,14 +325,7 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
v3d->grid = 1.0f;
v3d->gridlines = 16;
v3d->gridsubdiv = 10;
- v3d->drawtype = OB_SOLID;
- v3d->shading.flag = V3D_SHADING_SPECULAR_HIGHLIGHT;
- v3d->shading.light = V3D_LIGHTING_STUDIO;
- v3d->shading.shadow_intensity = 0.5f;
- v3d->shading.xray_alpha = 0.5f;
- v3d->shading.cavity_valley_factor = 1.0f;
- v3d->shading.cavity_ridge_factor = 1.0f;
- copy_v3_fl(v3d->shading.single_color, 0.8f);
+ BKE_screen_view3d_shading_init(&v3d->shading);
v3d->overlay.wireframe_threshold = 0.5f;
v3d->overlay.bone_select_alpha = 0.5f;
@@ -342,12 +336,18 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
v3d->flag = V3D_SELECT_OUTLINE;
- v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
+ v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_ANNOTATION;
v3d->lens = 50.0f;
v3d->near = 0.01f;
v3d->far = 1000.0f;
+ v3d->overlay.gpencil_grid_scale = 1.0; // Scales
+ v3d->overlay.gpencil_grid_lines = GP_DEFAULT_GRID_LINES; // NUmber of Lines
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ v3d->overlay.gpencil_grid_axis = V3D_GP_GRID_AXIS_Y;
+ v3d->overlay.gpencil_grid_opacity = 0.9f;
+
v3d->bundle_size = 0.2f;
v3d->bundle_drawtype = OB_PLAINAXES;
@@ -357,6 +357,10 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
v3d->stereo3d_convergence_alpha = 0.15f;
v3d->stereo3d_volume_alpha = 0.05f;
+ /* grease pencil settings */
+ v3d->vertex_opacity = 1.0f;
+ v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for view3d");
@@ -431,8 +435,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
v3dn->lay = v3do->localvd->lay & 0xFFFFFF;
}
- if (v3dn->drawtype == OB_RENDER)
- v3dn->drawtype = OB_SOLID;
+ if (v3dn->shading.type == OB_RENDER)
+ v3dn->shading.type = OB_SOLID;
/* copy or clear inside new stuff */
@@ -550,48 +554,29 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
}
}
-static bool view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_OB)
- return 1;
- }
- return 0;
+ return WM_drag_ID(drag, ID_OB) != NULL;
}
-static bool view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_GR)
- return 1;
- }
- return 0;
+ return WM_drag_ID(drag, ID_GR) != NULL;
}
-static bool view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_MA)
- return 1;
- }
- return 0;
+ return WM_drag_ID(drag, ID_MA) != NULL;
}
-static bool view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static bool view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip))
{
- if (drag->type == WM_DRAG_ID) {
- ID *id = drag->poin;
- if (GS(id->name) == ID_IM)
- return 1;
+ if (drag->type == WM_DRAG_PATH) {
+ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); /* rule might not work? */
}
- else if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)) /* rule might not work? */
- return 1;
+ else {
+ return WM_drag_ID(drag, ID_IM) != NULL;
}
- return 0;
}
static bool view3d_ima_bg_is_camera_view(bContext *C)
@@ -606,19 +591,19 @@ static bool view3d_ima_bg_is_camera_view(bContext *C)
return false;
}
-static bool view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
{
if (view3d_ima_bg_is_camera_view(C)) {
return true;
}
if (!ED_view3d_give_base_under_cursor(C, event->mval)) {
- return view3d_ima_drop_poll(C, drag, event);
+ return view3d_ima_drop_poll(C, drag, event, tooltip);
}
return 0;
}
-static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
{
if (!view3d_ima_bg_is_camera_view(C)) {
return true;
@@ -630,31 +615,31 @@ static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent
if ((base == NULL) ||
((base != NULL) && base->object->type == OB_EMPTY))
{
- return view3d_ima_drop_poll(C, drag, event);
+ return view3d_ima_drop_poll(C, drag, event, tooltip);
}
return 0;
}
-static bool view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static bool view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip)
{
Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
if (base && base->object->type == OB_MESH)
- return view3d_ima_drop_poll(C, drag, event);
+ return view3d_ima_drop_poll(C, drag, event, tooltip);
return 0;
}
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, ID_OB);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, ID_GR);
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -662,14 +647,14 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = drag->poin;
+ ID *id = WM_drag_ID(drag, 0);
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -716,26 +701,26 @@ static void view3d_dropboxes(void)
static void view3d_widgets(void)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
&(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_lamp_spot);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_lamp_area);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_lamp_target);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
- WM_gizmogrouptype_append(TRANSFORM_WGT_gizmo);
- WM_gizmogrouptype_append(VIEW3D_WGT_xform_cage);
+ WM_gizmogrouptype_append(TRANSFORM_GGT_gizmo);
+ WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
- WM_gizmogrouptype_append(VIEW3D_WGT_ruler);
- WM_gizmotype_append(VIEW3D_WT_ruler_item);
+ WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
+ WM_gizmotype_append(VIEW3D_GT_ruler_item);
- WM_gizmogrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
- WM_gizmotype_append(VIEW3D_WT_navigate_rotate);
+ WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
+ WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
}
@@ -815,13 +800,13 @@ static void view3d_main_region_listener(
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
- wmGizmoMap *mmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = ar->gizmo_map;
/* context changes */
switch (wmn->category) {
case NC_WM:
if (ELEM(wmn->data, ND_UNDO)) {
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_ANIMATION:
@@ -848,14 +833,14 @@ static void view3d_main_region_listener(
if (wmn->reference)
view3d_recalc_used_layers(ar, wmn, wmn->reference);
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
case ND_LAYER:
if (wmn->reference) {
BKE_screen_view3d_sync(v3d, wmn->reference);
}
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
case ND_OB_ACTIVE:
case ND_OB_SELECT:
@@ -867,7 +852,7 @@ static void view3d_main_region_listener(
case ND_MARKERS:
case ND_MODE:
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
case ND_WORLD:
/* handled by space_view3d_listener() for v3d access */
@@ -899,7 +884,7 @@ static void view3d_main_region_listener(
case ND_POINTCACHE:
case ND_LOD:
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
}
switch (wmn->action) {
@@ -912,7 +897,7 @@ static void view3d_main_region_listener(
switch (wmn->data) {
case ND_SELECT:
{
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
ATTR_FALLTHROUGH;
}
case ND_DATA:
@@ -993,7 +978,7 @@ static void view3d_main_region_listener(
break;
case ND_LIGHTING_DRAW:
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
break;
}
break;
@@ -1019,7 +1004,7 @@ static void view3d_main_region_listener(
rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
}
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_ID:
@@ -1035,7 +1020,7 @@ static void view3d_main_region_listener(
case ND_LAYOUTBROWSE:
case ND_LAYOUTDELETE:
case ND_LAYOUTSET:
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
ED_region_tag_redraw(ar);
break;
case ND_LAYER:
@@ -1413,7 +1398,7 @@ static void space_view3d_listener(
switch (wmn->data) {
case ND_WORLD_DRAW:
case ND_WORLD:
- if (v3d->flag3 & V3D_SHOW_WORLD)
+ if (v3d->shading.background_type & V3D_SHADING_BACKGROUND_WORLD)
ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
break;
}
@@ -1421,7 +1406,7 @@ static void space_view3d_listener(
case NC_MATERIAL:
switch (wmn->data) {
case ND_NODES:
- if (v3d->drawtype == OB_TEXTURE)
+ if (v3d->shading.type == OB_TEXTURE)
ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 8fa327d8782..38fac7cb37d 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -60,6 +60,7 @@
#include "BKE_deform.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
+#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -1223,10 +1224,14 @@ void VIEW3D_OT_properties(wmOperatorType *ot)
ot->flag = 0;
}
-static int view3d_object_mode_menu(bContext *C, wmOperator *UNUSED(op))
+static int view3d_object_mode_menu(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
- if (ob && ((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No active object found");
+ return OPERATOR_CANCELLED;
+ }
+ else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
ED_object_mode_toggle(C, OB_MODE_POSE);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index be79cef182d..46b53a369e3 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -184,8 +184,8 @@ static void view3d_main_region_setup_view(
ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
/* set for opengl */
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
}
static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
@@ -365,7 +365,7 @@ static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, fl
x4 = x1 + (1.0f - fac) * (x2 - x1);
y4 = y1 + (1.0f - fac) * (y2 - y1);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, x1, y3);
immVertex2f(shdr_pos, x2, y3);
@@ -390,7 +390,7 @@ static void drawviewborder_triangle(
float w = x2 - x1;
float h = y2 - y1;
- immBegin(GWN_PRIM_LINES, 6);
+ immBegin(GPU_PRIM_LINES, 6);
if (w > h) {
if (golden) {
@@ -467,7 +467,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
x2i = (int)(x2 + (1.0f - 0.0001f));
y2i = (int)(y2 + (1.0f - 0.0001f));
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* First, solid lines. */
{
@@ -559,7 +559,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
x3 = x1 + 0.5f * (x2 - x1);
y3 = y1 + 0.5f * (y2 - y1);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(shdr_pos, x1, y3);
immVertex2f(shdr_pos, x2, y3);
@@ -571,7 +571,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
}
if (ca->dtx & CAM_DTX_CENTER_DIAG) {
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
immVertex2f(shdr_pos, x1, y1);
immVertex2f(shdr_pos, x2, y2);
@@ -674,7 +674,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
static void drawrenderborder(ARegion *ar, View3D *v3d)
{
/* use the same program for everything */
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_line_width(1.0f);
@@ -814,12 +814,12 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_LINES, 6);
+ immBegin(GPU_PRIM_LINES, 6);
for (int axis_i = 0; axis_i < 3; axis_i++) {
int i = axis_order[axis_i];
@@ -859,9 +859,9 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE); /* don't overwrite zbuf */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
@@ -872,7 +872,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
color[3] = 0; /* more transparent toward the ends */
immAttrib4ubv(col, color);
add_v3_v3v3(end, o, scaled_axis);
@@ -911,7 +911,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
axis_angle_to_quat(q, vis_axis, vis_angle);
}
- immBegin(GWN_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
+ immBegin(GPU_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
color[3] = 63; /* somewhat faint */
immAttrib4ubv(col, color);
float angle = 0.0f;
@@ -940,7 +940,7 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
/* -- draw rotation center -- */
immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
GPU_point_size(5.0f);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immAttrib4ubv(col, color);
immVertex3fv(pos, o);
immEnd();
@@ -1207,7 +1207,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int UNUSED(of
if ((U.uiflag & USER_SHOW_GIZMO_AXIS) ||
(v3d->flag2 & V3D_RENDER_OVERRIDE) ||
/* No need to display gizmo and this info. */
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
{
/* pass */
}
@@ -1355,10 +1355,10 @@ void ED_view3d_draw_offscreen(
GPU_free_images_anim(G.main); /* XXX :((( */
}
- gpuPushProjectionMatrix();
- gpuLoadIdentity();
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_set();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
@@ -1375,8 +1375,8 @@ void ED_view3d_draw_offscreen(
ar->winy = bwiny;
ar->winrct = brect;
- gpuPopProjectionMatrix();
- gpuPopMatrix();
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
UI_Theme_Restore(&theme_state);
@@ -1412,6 +1412,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
ofs = NULL;
}
+ GPUFrameBuffer *old_fb = GPU_framebuffer_active_get();
+
+ if (old_fb) {
+ GPU_framebuffer_restore();
+ }
+
const bool own_ofs = (ofs == NULL);
DRW_opengl_context_enable();
@@ -1556,6 +1562,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
DRW_opengl_context_disable();
+ if (old_fb) {
+ GPU_framebuffer_bind(old_fb);
+ }
+
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
@@ -1589,17 +1599,17 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
v3d.camera = camera;
v3d.lay = scene->lay;
- v3d.drawtype = drawtype;
+ v3d.shading.type = drawtype;
v3d.flag2 = V3D_RENDER_OVERRIDE;
if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
- v3d.flag2 |= V3D_SHOW_GPENCIL;
+ v3d.flag2 |= V3D_SHOW_ANNOTATION;
}
if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) {
v3d.flag2 |= V3D_SOLID_TEX;
}
- v3d.flag3 |= V3D_SHOW_WORLD;
+ v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
if (camera->type == OB_CAMERA) {
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index cfeb199de15..45e4c4b4676 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -179,7 +179,7 @@ static void backdrawview3d(
}
/* texture paint mode sampling */
else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->drawtype > OB_WIRE))
+ (v3d->shading.type > OB_WIRE))
{
/* do nothing */
}
@@ -211,7 +211,7 @@ static void backdrawview3d(
#endif
#if 0 /* v3d->zbuf deprecated */
- if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
+ if (v3d->shading.type > OB_WIRE) v3d->zbuf = true;
#endif
/* dithering and AA break color coding, so disable */
@@ -685,13 +685,13 @@ static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph,
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- gpuPushProjectionMatrix();
- gpuPushMatrix();
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
ED_region_pixelspace(ar);
- gpuTranslate2f(centx, centy);
- gpuScaleUniform(bgpic->scale);
- gpuRotate2D(RAD2DEGF(-bgpic->rotation));
+ GPU_matrix_translate_2f(centx, centy);
+ GPU_matrix_scale_1f(bgpic->scale);
+ GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation));
if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
zoomx *= -1.0f;
@@ -707,8 +707,8 @@ static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph,
immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect,
zoomx, zoomy, col);
- gpuPopProjectionMatrix();
- gpuPopMatrix();
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
GPU_blend(false);
@@ -881,7 +881,7 @@ void ED_view3d_draw_depth_gpencil(
GPU_depth_test(true);
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ if (v3d->flag2 & V3D_SHOW_ANNOTATION) {
ED_gpencil_draw_view3d(NULL, scene, view_layer, depsgraph, v3d, ar, true);
}
@@ -1033,7 +1033,7 @@ bool ED_view3d_calc_render_border(const Scene *scene, Depsgraph *depsgraph, View
bool use_border;
/* test if there is a 3d view rendering */
- if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
+ if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene))
return false;
/* test if there is a border render */
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 792a341fba4..468b33ea9a6 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -52,6 +52,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
+#include "BKE_gpencil.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -77,7 +78,6 @@
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_mesh.h"
-#include "ED_gpencil.h"
#include "ED_view3d.h"
#include "ED_transform_snap_object_context.h"
@@ -2811,7 +2811,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
bGPdata *gpd = CTX_data_gpencil_data(C);
- const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+ const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map &&
WM_gizmomap_is_any_selected(ar->gizmo_map));
Object *ob_eval = OBACT(view_layer_eval);
@@ -2850,9 +2850,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
{
/* we're only interested in selected points here... */
if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
- if (ED_gpencil_stroke_minmax(gps, true, min, max)) {
- ok = true;
- }
+ ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
}
}
CTX_DATA_END;
@@ -4625,7 +4623,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* cursor position in vec, result in vec, mval in region coords */
/* note: cannot use event->mval here (called by object_add() */
-void ED_view3d_cursor3d_position(bContext *C, const int mval[2], bool use_depth, float cursor_co[3])
+void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, float cursor_co[3])
{
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4873,7 +4871,7 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
if (type == OB_SOLID) {
- if (v3d->drawtype == OB_SOLID) {
+ if (v3d->shading.type == OB_SOLID) {
/* Toggle X-Ray if already in solid mode. */
if (ED_operator_posemode(C) || ED_operator_editmesh(C)) {
v3d->flag ^= V3D_ZBUF_SELECT;
@@ -4884,24 +4882,24 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
}
else {
/* Go to solid mode. */
- v3d->drawtype = OB_SOLID;
+ v3d->shading.type = OB_SOLID;
}
}
else if (type == OB_MATERIAL) {
- if (v3d->drawtype == OB_MATERIAL) {
- v3d->drawtype = OB_SOLID;
+ if (v3d->shading.type == OB_MATERIAL) {
+ v3d->shading.type = OB_SOLID;
}
else {
- v3d->drawtype = OB_MATERIAL;
+ v3d->shading.type = OB_MATERIAL;
}
}
else if (type == OB_RENDER) {
- if (v3d->drawtype == OB_RENDER) {
- v3d->drawtype = v3d->prev_drawtype;
+ if (v3d->shading.type == OB_RENDER) {
+ v3d->shading.type = v3d->shading.prev_type;
}
else {
- v3d->prev_drawtype = v3d->drawtype;
- v3d->drawtype = OB_RENDER;
+ v3d->shading.prev_type = v3d->shading.type;
+ v3d->shading.type = OB_RENDER;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index d1b9f95ca2a..3cf036e1ce1 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -263,14 +263,14 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
x2 = xoff + 0.55f * fly->width;
y2 = yoff + 0.55f * fly->height;
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_VIEW_OVERLAY);
- immBegin(GWN_PRIM_LINES, 16);
+ immBegin(GPU_PRIM_LINES, 16);
/* bottom left */
immVertex2f(pos, x1, y1);
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index c7b12529798..88a95e89bd8 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -80,14 +80,14 @@ struct BoneSplineWidgetGroup {
};
static void gizmo_bbone_offset_get(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
- struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data;
+ struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
bPoseChannel *pchan = bh->pchan;
float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 3);
+ BLI_assert(gz_prop->type->array_length == 3);
if (bh->index == 0) {
bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y;
@@ -103,15 +103,15 @@ static void gizmo_bbone_offset_get(
}
static void gizmo_bbone_offset_set(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
const void *value_p)
{
- struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data;
+ struct BoneSplineHandle *bh = gz_prop->custom_func.user_data;
bPoseChannel *pchan = bh->pchan;
const float *value = value_p;
- BLI_assert(mpr_prop->type->array_length == 3);
+ BLI_assert(gz_prop->type->array_length == 3);
copy_v3_v3(bh->co, value);
if (bh->index == 0) {
@@ -127,7 +127,7 @@ static void gizmo_bbone_offset_set(
}
-static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
if (ob != NULL) {
@@ -136,7 +136,7 @@ static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType
if (arm->act_bone && arm->act_bone->segments > 1) {
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
/* pass */
}
@@ -150,59 +150,59 @@ static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType
}
-static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bPoseChannel *pchan = BKE_pose_channel_active(ob);
- const wmGizmoType *wt_grab = WM_gizmotype_find("GIZMO_WT_grab_3d", true);
+ const wmGizmoType *gzt_grab = WM_gizmotype_find("GIZMO_GT_grab_3d", true);
struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__);
- mgroup->customdata = bspline_group;
+ gzgroup->customdata = bspline_group;
/* Handles */
for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
- wmGizmo *mpr;
- mpr = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(wt_grab, mgroup, NULL);
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_RING_2D);
- RNA_enum_set(mpr->ptr, "draw_options",
+ wmGizmo *gz;
+ gz = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(gzt_grab, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_GRAB_STYLE_RING_2D);
+ RNA_enum_set(gz->ptr, "draw_options",
ED_GIZMO_GRAB_DRAW_FLAG_FILL | ED_GIZMO_GRAB_DRAW_FLAG_ALIGN_VIEW);
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- mpr->scale_basis = 0.06f;
+ gz->scale_basis = 0.06f;
if (i == 0) {
- copy_v3_v3(mpr->matrix_basis[3], pchan->loc);
+ copy_v3_v3(gz->matrix_basis[3], pchan->loc);
}
}
}
-static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- if (!mgroup->customdata)
+ if (!gzgroup->customdata)
return;
- struct BoneSplineWidgetGroup *bspline_group = mgroup->customdata;
+ struct BoneSplineWidgetGroup *bspline_group = gzgroup->customdata;
bPoseChannel *pchan = BKE_pose_channel_active(ob);
/* Handles */
for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
- wmGizmo *mpr = bspline_group->handles[i].gizmo;
+ wmGizmo *gz = bspline_group->handles[i].gizmo;
bspline_group->handles[i].pchan = pchan;
bspline_group->handles[i].index = i;
float mat[4][4];
mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
- copy_m4_m4(mpr->matrix_space, mat);
+ copy_m4_m4(gz->matrix_space, mat);
/* need to set property here for undo. TODO would prefer to do this in _init */
WM_gizmo_target_property_def_func(
- mpr, "offset",
+ gz, "offset",
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = gizmo_bbone_offset_get,
.value_set_fn = gizmo_bbone_offset_set,
@@ -212,17 +212,17 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup
}
}
-void VIEW3D_WGT_armature_spline(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_armature_spline(wmGizmoGroupType *gzgt)
{
- wgt->name = "Armature Spline Widgets";
- wgt->idname = "VIEW3D_WGT_armature_spline";
+ gzgt->name = "Armature Spline Widgets";
+ gzgt->idname = "VIEW3D_GGT_armature_spline";
- wgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D);
- wgt->poll = WIDGETGROUP_armature_spline_poll;
- wgt->setup = WIDGETGROUP_armature_spline_setup;
- wgt->refresh = WIDGETGROUP_armature_spline_refresh;
+ gzgt->poll = WIDGETGROUP_armature_spline_poll;
+ gzgt->setup = WIDGETGROUP_armature_spline_setup;
+ gzgt->refresh = WIDGETGROUP_armature_spline_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index b011e6e2e21..87b11f5d7a3 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -61,11 +61,11 @@ struct CameraWidgetGroup {
wmGizmo *ortho_scale;
};
-static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
return false;
}
@@ -81,57 +81,57 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(
return false;
}
-static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
Object *ob = CTX_data_active_object(C);
float dir[3];
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- struct CameraWidgetGroup *camgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
- mgroup->customdata = camgroup;
+ struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
+ gzgroup->customdata = cagzgroup;
negate_v3_v3(dir, ob->obmat[2]);
/* dof distance */
{
- wmGizmo *mpr;
- mpr = camgroup->dop_dist = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS);
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_HOVER, true);
+ wmGizmo *gz;
+ gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
- UI_GetThemeColor3fv(TH_GIZMO_A, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_A, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
/* focal length
* - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */
{
- wmGizmo *mpr;
- mpr = camgroup->focal_len = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- mpr->flag |= WM_GIZMO_DRAW_NO_SCALE;
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
-
- mpr = camgroup->ortho_scale = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- mpr->flag |= WM_GIZMO_DRAW_NO_SCALE;
- RNA_enum_set(mpr->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ wmGizmo *gz;
+ gz = cagzgroup->focal_len = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+
+ gz = cagzgroup->ortho_scale = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ gz->flag |= WM_GIZMO_DRAW_NO_SCALE;
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE);
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
}
-static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- if (!mgroup->customdata)
+ if (!gzgroup->customdata)
return;
- struct CameraWidgetGroup *camgroup = mgroup->customdata;
+ struct CameraWidgetGroup *cagzgroup = gzgroup->customdata;
Object *ob = CTX_data_active_object(C);
Camera *ca = ob->data;
PointerRNA camera_ptr;
@@ -149,16 +149,16 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *mgroup)
negate_v3_v3(dir, ob->obmat[2]);
if (ca->flag & CAM_SHOWLIMITS) {
- WM_gizmo_set_matrix_location(camgroup->dop_dist, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob->obmat[1], dir);
- WM_gizmo_set_scale(camgroup->dop_dist, ca->drawsize);
- WM_gizmo_set_flag(camgroup->dop_dist, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir);
+ WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize);
+ WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false);
/* need to set property here for undo. TODO would prefer to do this in _init */
- WM_gizmo_target_property_def_rna(camgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
+ WM_gizmo_target_property_def_rna(cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
}
else {
- WM_gizmo_set_flag(camgroup->dop_dist, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
}
/* TODO - make focal length/ortho ob_scale_inv widget optional */
@@ -167,14 +167,14 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *mgroup)
const float aspy = (float)scene->r.ysch * scene->r.yasp;
const bool is_ortho = (ca->type == CAM_ORTHO);
const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy);
- wmGizmo *widget = is_ortho ? camgroup->ortho_scale : camgroup->focal_len;
+ wmGizmo *widget = is_ortho ? cagzgroup->ortho_scale : cagzgroup->focal_len;
float scale_matrix;
if (true) {
float offset[3];
float aspect[2];
WM_gizmo_set_flag(widget, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(is_ortho ? camgroup->focal_len : camgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(is_ortho ? cagzgroup->focal_len : cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true);
/* account for lens shifting */
@@ -208,9 +208,9 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *mgroup)
{
const char *propname = is_ortho ? "ortho_scale" : "lens";
PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname);
- const wmGizmoPropertyType *mpr_prop_type = WM_gizmotype_target_property_find(widget->type, "offset");
+ const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(widget->type, "offset");
- WM_gizmo_target_property_clear_rna_ptr(widget, mpr_prop_type);
+ WM_gizmo_target_property_clear_rna_ptr(widget, gz_prop_type);
float min, max, range;
float step, precision;
@@ -226,21 +226,21 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *mgroup)
/* Half sensor, intentionally use sensor from camera and not calculated above. */
(0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_HOR) ? ca->sensor_x : ca->sensor_x))));
- WM_gizmo_target_property_def_rna_ptr(widget, mpr_prop_type, &camera_ptr, prop, -1);
+ WM_gizmo_target_property_def_rna_ptr(widget, gz_prop_type, &camera_ptr, prop, -1);
}
}
static void WIDGETGROUP_camera_message_subscribe(
- const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus)
+ const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
{
ARegion *ar = CTX_wm_region(C);
Object *ob = CTX_data_active_object(C);
Camera *ca = ob->data;
- wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
.owner = ar,
- .user_data = mgroup->parent_mmap,
+ .user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
@@ -270,32 +270,32 @@ static void WIDGETGROUP_camera_message_subscribe(
RNA_id_pointer_create(&ca->id, &idptr);
for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
}
}
/* Subscribe to render settings */
{
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_mpr_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_mpr_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_mpr_tag_refresh);
- WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_gz_tag_refresh);
}
}
-void VIEW3D_WGT_camera(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_camera(wmGizmoGroupType *gzgt)
{
- wgt->name = "Camera Widgets";
- wgt->idname = "VIEW3D_WGT_camera";
+ gzgt->name = "Camera Widgets";
+ gzgt->idname = "VIEW3D_GGT_camera";
- wgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D |
WM_GIZMOGROUPTYPE_DEPTH_3D);
- wgt->poll = WIDGETGROUP_camera_poll;
- wgt->setup = WIDGETGROUP_camera_setup;
- wgt->refresh = WIDGETGROUP_camera_refresh;
- wgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
+ gzgt->poll = WIDGETGROUP_camera_poll;
+ gzgt->setup = WIDGETGROUP_camera_setup;
+ gzgt->refresh = WIDGETGROUP_camera_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
}
/** \} */
@@ -316,12 +316,12 @@ struct CameraViewWidgetGroup {
/* scale callbacks */
static void gizmo_render_border_prop_matrix_get(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
const rctf *border = viewgroup->state.edit_border;
unit_m4(matrix);
@@ -332,20 +332,20 @@ static void gizmo_render_border_prop_matrix_get(
}
static void gizmo_render_border_prop_matrix_set(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
const void *value_p)
{
const float (*matrix)[4] = value_p;
- struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data;
+ struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data;
rctf *border = viewgroup->state.edit_border;
- BLI_assert(mpr_prop->type->array_length == 16);
+ BLI_assert(gz_prop->type->array_length == 16);
BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1]));
BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]);
BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, border, border);
}
-static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
Scene *scene = CTX_data_scene(C);
@@ -361,7 +361,7 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
return false;
}
@@ -382,11 +382,11 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN
return false;
}
-static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__);
- viewgroup->border = WM_gizmo_new("GIZMO_WT_cage_2d", mgroup, NULL);
+ viewgroup->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
RNA_enum_set(viewgroup->border->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
@@ -394,12 +394,12 @@ static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGrou
RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX);
- mgroup->customdata = viewgroup;
+ gzgroup->customdata = viewgroup;
}
-static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct CameraViewWidgetGroup *viewgroup = mgroup->customdata;
+ struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
ARegion *ar = CTX_wm_region(C);
struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -413,17 +413,17 @@ static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup
viewgroup->state.view_border = (rctf){.xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy};
}
- wmGizmo *mpr = viewgroup->border;
- unit_m4(mpr->matrix_space);
- mul_v3_fl(mpr->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border));
- mul_v3_fl(mpr->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border));
- mpr->matrix_space[3][0] = viewgroup->state.view_border.xmin;
- mpr->matrix_space[3][1] = viewgroup->state.view_border.ymin;
+ wmGizmo *gz = viewgroup->border;
+ unit_m4(gz->matrix_space);
+ mul_v3_fl(gz->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border));
+ mul_v3_fl(gz->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border));
+ gz->matrix_space[3][0] = viewgroup->state.view_border.xmin;
+ gz->matrix_space[3][1] = viewgroup->state.view_border.ymin;
}
-static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct CameraViewWidgetGroup *viewgroup = mgroup->customdata;
+ struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
@@ -431,8 +431,8 @@ static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *mgr
Scene *scene = CTX_data_scene(C);
{
- wmGizmo *mpr = viewgroup->border;
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ wmGizmo *gz = viewgroup->border;
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
RNA_enum_set(viewgroup->border->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
@@ -445,7 +445,7 @@ static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *mgr
}
WM_gizmo_target_property_def_func(
- mpr, "matrix",
+ gz, "matrix",
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = gizmo_render_border_prop_matrix_get,
.value_set_fn = gizmo_render_border_prop_matrix_set,
@@ -456,18 +456,18 @@ static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *mgr
}
-void VIEW3D_WGT_camera_view(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_camera_view(wmGizmoGroupType *gzgt)
{
- wgt->name = "Camera View Widgets";
- wgt->idname = "VIEW3D_WGT_camera_view";
+ gzgt->name = "Camera View Widgets";
+ gzgt->idname = "VIEW3D_GGT_camera_view";
- wgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_SCALE);
- wgt->poll = WIDGETGROUP_camera_view_poll;
- wgt->setup = WIDGETGROUP_camera_view_setup;
- wgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare;
- wgt->refresh = WIDGETGROUP_camera_view_refresh;
+ gzgt->poll = WIDGETGROUP_camera_view_poll;
+ gzgt->setup = WIDGETGROUP_camera_view_setup;
+ gzgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare;
+ gzgt->refresh = WIDGETGROUP_camera_view_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index 3b51af5ca15..2913ba245e7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -63,20 +63,20 @@ struct EmptyImageWidgetGroup {
/* translate callbacks */
static void gizmo_empty_image_prop_matrix_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
void *value_p)
{
float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data;
- const Object *ob = imgroup->state.ob;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
+ const Object *ob = igzgroup->state.ob;
unit_m4(matrix);
matrix[0][0] = ob->empty_drawsize;
matrix[1][1] = ob->empty_drawsize;
float dims[2] = {0.0f, 0.0f};
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
dims[0] *= ob->empty_drawsize;
dims[1] *= ob->empty_drawsize;
@@ -85,18 +85,18 @@ static void gizmo_empty_image_prop_matrix_get(
}
static void gizmo_empty_image_prop_matrix_set(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
const void *value_p)
{
const float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data;
- Object *ob = imgroup->state.ob;
+ BLI_assert(gz_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data;
+ Object *ob = igzgroup->state.ob;
ob->empty_drawsize = matrix[0][0];
float dims[2];
- RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ RNA_float_get_array(gz->ptr, "dimensions", dims);
dims[0] *= ob->empty_drawsize;
dims[1] *= ob->empty_drawsize;
@@ -104,12 +104,12 @@ static void gizmo_empty_image_prop_matrix_set(
ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1];
}
-static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
return false;
}
@@ -122,36 +122,36 @@ static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UN
return false;
}
-static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct EmptyImageWidgetGroup *imgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__);
- imgroup->gizmo = WM_gizmo_new("GIZMO_WT_cage_2d", mgroup, NULL);
- wmGizmo *mpr = imgroup->gizmo;
- RNA_enum_set(mpr->ptr, "transform",
+ struct EmptyImageWidgetGroup *igzgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__);
+ igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wmGizmo *gz = igzgroup->gizmo;
+ RNA_enum_set(gz->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- mgroup->customdata = imgroup;
+ gzgroup->customdata = igzgroup;
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_HOVER, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
-static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct EmptyImageWidgetGroup *imgroup = mgroup->customdata;
+ struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata;
Object *ob = CTX_data_active_object(C);
- wmGizmo *mpr = imgroup->gizmo;
+ wmGizmo *gz = igzgroup->gizmo;
- copy_m4_m4(mpr->matrix_basis, ob->obmat);
+ copy_m4_m4(gz->matrix_basis, ob->obmat);
- RNA_enum_set(mpr->ptr, "transform",
+ RNA_enum_set(gz->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
- imgroup->state.ob = ob;
+ igzgroup->state.ob = ob;
/* Use dimensions for aspect. */
if (ob->data != NULL) {
@@ -169,36 +169,36 @@ static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *mgr
}
const float dims_max = max_ff(size[0], size[1]);
- imgroup->state.dims[0] = size[0] / dims_max;
- imgroup->state.dims[1] = size[1] / dims_max;
+ igzgroup->state.dims[0] = size[0] / dims_max;
+ igzgroup->state.dims[1] = size[1] / dims_max;
}
else {
- copy_v2_fl(imgroup->state.dims, 1.0f);
+ copy_v2_fl(igzgroup->state.dims, 1.0f);
}
- RNA_float_set_array(mpr->ptr, "dimensions", imgroup->state.dims);
+ RNA_float_set_array(gz->ptr, "dimensions", igzgroup->state.dims);
WM_gizmo_target_property_def_func(
- mpr, "matrix",
+ gz, "matrix",
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = gizmo_empty_image_prop_matrix_get,
.value_set_fn = gizmo_empty_image_prop_matrix_set,
.range_get_fn = NULL,
- .user_data = imgroup,
+ .user_data = igzgroup,
});
}
-void VIEW3D_WGT_empty_image(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_empty_image(wmGizmoGroupType *gzgt)
{
- wgt->name = "Area Light Widgets";
- wgt->idname = "VIEW3D_WGT_empty_image";
+ gzgt->name = "Area Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_empty_image";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D |
WM_GIZMOGROUPTYPE_DEPTH_3D);
- wgt->poll = WIDGETGROUP_empty_image_poll;
- wgt->setup = WIDGETGROUP_empty_image_setup;
- wgt->refresh = WIDGETGROUP_empty_image_refresh;
+ gzgt->poll = WIDGETGROUP_empty_image_poll;
+ gzgt->setup = WIDGETGROUP_empty_image_setup;
+ gzgt->refresh = WIDGETGROUP_empty_image_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index d4605bb0c7d..e2a8d2802e7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -52,12 +52,12 @@
/** \name Force Field Gizmos
* \{ */
-static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
return false;
}
@@ -67,26 +67,26 @@ static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNU
return (ob && ob->pd && ob->pd->forcefield);
}
-static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
/* only wind effector for now */
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- mgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- wwrapper->gizmo = WM_gizmo_new("GIZMO_WT_arrow_3d", mgroup, NULL);
- wmGizmo *mpr = wwrapper->gizmo;
- RNA_enum_set(mpr->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
- ED_gizmo_arrow3d_set_ui_range(mpr, -200.0f, 200.0f);
- ED_gizmo_arrow3d_set_range_fac(mpr, 6.0f);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED);
+ ED_gizmo_arrow3d_set_ui_range(gz, -200.0f, 200.0f);
+ ED_gizmo_arrow3d_set_range_fac(gz, 6.0f);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
-static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = mgroup->customdata;
- wmGizmo *mpr = wwrapper->gizmo;
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ wmGizmo *gz = wwrapper->gizmo;
Object *ob = CTX_data_active_object(C);
PartDeflect *pd = ob->pd;
@@ -96,30 +96,30 @@ static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *mgro
PointerRNA field_ptr;
RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
- WM_gizmo_set_matrix_location(mpr, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_z_axis(mpr, ob->obmat[2]);
- WM_gizmo_set_matrix_offset_location(mpr, ofs);
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
- WM_gizmo_target_property_def_rna(mpr, "offset", &field_ptr, "strength", -1);
+ WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]);
+ WM_gizmo_set_matrix_offset_location(gz, ofs);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1);
}
else {
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
-void VIEW3D_WGT_force_field(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_force_field(wmGizmoGroupType *gzgt)
{
- wgt->name = "Force Field Widgets";
- wgt->idname = "VIEW3D_WGT_force_field";
+ gzgt->name = "Force Field Widgets";
+ gzgt->idname = "VIEW3D_GGT_force_field";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D |
WM_GIZMOGROUPTYPE_SCALE |
WM_GIZMOGROUPTYPE_DEPTH_3D);
- wgt->poll = WIDGETGROUP_forcefield_poll;
- wgt->setup = WIDGETGROUP_forcefield_setup;
- wgt->refresh = WIDGETGROUP_forcefield_refresh;
+ gzgt->poll = WIDGETGROUP_forcefield_poll;
+ gzgt->setup = WIDGETGROUP_forcefield_setup;
+ gzgt->refresh = WIDGETGROUP_forcefield_refresh;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_lamp.c b/source/blender/editors/space_view3d/view3d_gizmo_lamp.c
index a872cc96172..057c085b69d 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_lamp.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_lamp.c
@@ -52,11 +52,11 @@
/** \name Spot Lamp Gizmos
* \{ */
-static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)))
{
return false;
}
@@ -70,53 +70,53 @@ static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmGizmoGroupType *UNUS
return false;
}
-static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_WT_arrow_3d", mgroup, NULL);
- wmGizmo *mpr = wwrapper->gizmo;
- RNA_enum_set(mpr->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED);
- mgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- ED_gizmo_arrow3d_set_range_fac(mpr, 4.0f);
+ ED_gizmo_arrow3d_set_range_fac(gz, 4.0f);
- UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, mpr->color);
+ UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color);
}
-static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = mgroup->customdata;
- wmGizmo *mpr = wwrapper->gizmo;
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
+ wmGizmo *gz = wwrapper->gizmo;
Object *ob = CTX_data_active_object(C);
Lamp *la = ob->data;
float dir[3];
negate_v3_v3(dir, ob->obmat[2]);
- WM_gizmo_set_matrix_rotation_from_z_axis(mpr, dir);
- WM_gizmo_set_matrix_location(mpr, ob->obmat[3]);
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir);
+ WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
/* need to set property here for undo. TODO would prefer to do this in _init */
PointerRNA lamp_ptr;
const char *propname = "spot_size";
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
- WM_gizmo_target_property_def_rna(mpr, "offset", &lamp_ptr, propname, -1);
+ WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1);
}
-void VIEW3D_WGT_lamp_spot(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_lamp_spot(wmGizmoGroupType *gzgt)
{
- wgt->name = "Spot Light Widgets";
- wgt->idname = "VIEW3D_WGT_lamp_spot";
+ gzgt->name = "Spot Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_lamp_spot";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D |
WM_GIZMOGROUPTYPE_DEPTH_3D);
- wgt->poll = WIDGETGROUP_lamp_spot_poll;
- wgt->setup = WIDGETGROUP_lamp_spot_setup;
- wgt->refresh = WIDGETGROUP_lamp_spot_refresh;
+ gzgt->poll = WIDGETGROUP_lamp_spot_poll;
+ gzgt->setup = WIDGETGROUP_lamp_spot_setup;
+ gzgt->refresh = WIDGETGROUP_lamp_spot_refresh;
}
/** \} */
@@ -128,24 +128,24 @@ void VIEW3D_WGT_lamp_spot(wmGizmoGroupType *wgt)
/* scale callbacks */
static void gizmo_area_lamp_prop_matrix_get(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
- BLI_assert(mpr_prop->type->array_length == 16);
+ BLI_assert(gz_prop->type->array_length == 16);
float (*matrix)[4] = value_p;
- const Lamp *la = mpr_prop->custom_func.user_data;
+ const Lamp *la = gz_prop->custom_func.user_data;
matrix[0][0] = la->area_size;
matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size;
}
static void gizmo_area_lamp_prop_matrix_set(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
const void *value_p)
{
const float (*matrix)[4] = value_p;
- BLI_assert(mpr_prop->type->array_length == 16);
- Lamp *la = mpr_prop->custom_func.user_data;
+ BLI_assert(gz_prop->type->array_length == 16);
+ Lamp *la = gz_prop->custom_func.user_data;
if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) {
la->area_size = len_v3(matrix[0]);
@@ -156,7 +156,7 @@ static void gizmo_area_lamp_prop_matrix_set(
}
}
-static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
@@ -171,40 +171,40 @@ static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmGizmoGroupType *UNUS
return false;
}
-static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_WT_cage_2d", mgroup, NULL);
- wmGizmo *mpr = wwrapper->gizmo;
- RNA_enum_set(mpr->ptr, "transform",
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
+ RNA_enum_set(gz->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
- mgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_HOVER, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
}
-static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = mgroup->customdata;
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
Object *ob = CTX_data_active_object(C);
Lamp *la = ob->data;
- wmGizmo *mpr = wwrapper->gizmo;
+ wmGizmo *gz = wwrapper->gizmo;
- copy_m4_m4(mpr->matrix_basis, ob->obmat);
+ copy_m4_m4(gz->matrix_basis, ob->obmat);
int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE;
if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
}
- RNA_enum_set(mpr->ptr, "transform", flag);
+ RNA_enum_set(gz->ptr, "transform", flag);
/* need to set property here for undo. TODO would prefer to do this in _init */
WM_gizmo_target_property_def_func(
- mpr, "matrix",
+ gz, "matrix",
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = gizmo_area_lamp_prop_matrix_get,
.value_set_fn = gizmo_area_lamp_prop_matrix_set,
@@ -213,18 +213,18 @@ static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmGizmoGroup *mgrou
});
}
-void VIEW3D_WGT_lamp_area(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_lamp_area(wmGizmoGroupType *gzgt)
{
- wgt->name = "Area Light Widgets";
- wgt->idname = "VIEW3D_WGT_lamp_area";
+ gzgt->name = "Area Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_lamp_area";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D |
WM_GIZMOGROUPTYPE_DEPTH_3D);
- wgt->poll = WIDGETGROUP_lamp_area_poll;
- wgt->setup = WIDGETGROUP_lamp_area_setup;
- wgt->refresh = WIDGETGROUP_lamp_area_refresh;
+ gzgt->poll = WIDGETGROUP_lamp_area_poll;
+ gzgt->setup = WIDGETGROUP_lamp_area_setup;
+ gzgt->refresh = WIDGETGROUP_lamp_area_refresh;
}
/** \} */
@@ -235,7 +235,7 @@ void VIEW3D_WGT_lamp_area(wmGizmoGroupType *wgt)
/** \name Lamp Target Gizmo
* \{ */
-static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
@@ -258,50 +258,50 @@ static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmGizmoGroupType *UN
return false;
}
-static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_WT_grab_3d", mgroup, NULL);
- wmGizmo *mpr = wwrapper->gizmo;
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_grab_3d", gzgroup, NULL);
+ wmGizmo *gz = wwrapper->gizmo;
- mgroup->customdata = wwrapper;
+ gzgroup->customdata = wwrapper;
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, mpr->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, mpr->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- mpr->scale_basis = 0.06f;
+ gz->scale_basis = 0.06f;
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true);
- RNA_enum_set(mpr->ptr, "draw_options",
+ RNA_enum_set(gz->ptr, "draw_options",
ED_GIZMO_GRAB_DRAW_FLAG_FILL | ED_GIZMO_GRAB_DRAW_FLAG_ALIGN_VIEW);
- WM_gizmo_operator_set(mpr, 0, ot, NULL);
+ WM_gizmo_operator_set(gz, 0, ot, NULL);
}
-static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = mgroup->customdata;
+ wmGizmoWrapper *wwrapper = gzgroup->customdata;
Object *ob = CTX_data_active_object(C);
- wmGizmo *mpr = wwrapper->gizmo;
+ wmGizmo *gz = wwrapper->gizmo;
- copy_m4_m4(mpr->matrix_basis, ob->obmat);
- unit_m4(mpr->matrix_offset);
- mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis;
- WM_gizmo_set_flag(mpr, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ copy_m4_m4(gz->matrix_basis, ob->obmat);
+ unit_m4(gz->matrix_offset);
+ gz->matrix_offset[3][2] = -2.4f / gz->scale_basis;
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true);
}
-void VIEW3D_WGT_lamp_target(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_lamp_target(wmGizmoGroupType *gzgt)
{
- wgt->name = "Target Light Widgets";
- wgt->idname = "VIEW3D_WGT_lamp_target";
+ gzgt->name = "Target Light Widgets";
+ gzgt->idname = "VIEW3D_GGT_lamp_target";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_3D);
- wgt->poll = WIDGETGROUP_lamp_target_poll;
- wgt->setup = WIDGETGROUP_lamp_target_setup;
- wgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare;
+ gzgt->poll = WIDGETGROUP_lamp_target_poll;
+ gzgt->setup = WIDGETGROUP_lamp_target_setup;
+ gzgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index f4a8bad7e30..5778f85a99c 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -131,31 +131,31 @@ struct NavigateGizmoInfo {
#define SHAPE_VARS(shape_id) shape = shape_id, .shape_size = ARRAY_SIZE(shape_id)
-struct NavigateGizmoInfo g_navigate_params[MPR_TOTAL] = {
+static struct NavigateGizmoInfo g_navigate_params[MPR_TOTAL] = {
{
.opname = "VIEW3D_OT_move",
- .gizmo = "GIZMO_WT_button_2d",
+ .gizmo = "GIZMO_GT_button_2d",
.SHAPE_VARS(shape_pan),
}, {
.opname = "VIEW3D_OT_rotate",
- .gizmo = "VIEW3D_WT_navigate_rotate",
+ .gizmo = "VIEW3D_GT_navigate_rotate",
.shape = NULL,
.shape_size = 0,
}, {
.opname = "VIEW3D_OT_zoom",
- .gizmo = "GIZMO_WT_button_2d",
+ .gizmo = "GIZMO_GT_button_2d",
.SHAPE_VARS(shape_zoom),
}, {
.opname = "VIEW3D_OT_view_persportho",
- .gizmo = "GIZMO_WT_button_2d",
+ .gizmo = "GIZMO_GT_button_2d",
.SHAPE_VARS(shape_persp),
}, {
.opname = "VIEW3D_OT_view_persportho",
- .gizmo = "GIZMO_WT_button_2d",
+ .gizmo = "GIZMO_GT_button_2d",
.SHAPE_VARS(shape_ortho),
}, {
.opname = "VIEW3D_OT_view_camera",
- .gizmo = "GIZMO_WT_button_2d",
+ .gizmo = "GIZMO_GT_button_2d",
.SHAPE_VARS(shape_camera),
},
};
@@ -163,7 +163,7 @@ struct NavigateGizmoInfo g_navigate_params[MPR_TOTAL] = {
#undef SHAPE_VARS
struct NavigateWidgetGroup {
- wmGizmo *mpr_array[MPR_TOTAL];
+ wmGizmo *gz_array[MPR_TOTAL];
/* Store the view state to check for changes. */
struct {
rcti rect_visible;
@@ -176,12 +176,12 @@ struct NavigateWidgetGroup {
int region_size[2];
};
-static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
if (((U.uiflag & USER_SHOW_GIZMO_AXIS) == 0) ||
(v3d->flag2 & V3D_RENDER_OVERRIDE) ||
- (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
+ (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE)))
{
return false;
}
@@ -189,7 +189,7 @@ static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSE
}
-static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
@@ -201,53 +201,53 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *
for (int i = 0; i < MPR_TOTAL; i++) {
const struct NavigateGizmoInfo *info = &g_navigate_params[i];
- navgroup->mpr_array[i] = WM_gizmo_new(info->gizmo, mgroup, NULL);
- wmGizmo *mpr = navgroup->mpr_array[i];
- mpr->flag |= WM_GIZMO_GRAB_CURSOR | WM_GIZMO_DRAW_MODAL;
- mpr->color[3] = 0.2f;
- mpr->color_hi[3] = 0.4f;
+ navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL);
+ wmGizmo *gz = navgroup->gz_array[i];
+ gz->flag |= WM_GIZMO_GRAB_CURSOR | WM_GIZMO_DRAW_MODAL;
+ gz->color[3] = 0.2f;
+ gz->color_hi[3] = 0.4f;
/* may be overwritten later */
- mpr->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2;
+ gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2;
if (info->shape != NULL) {
- PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "shape");
+ PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "shape");
RNA_property_string_set_bytes(
- mpr->ptr, prop,
+ gz->ptr, prop,
(const char *)info->shape, info->shape_size);
- RNA_enum_set(mpr->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE);
+ RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE);
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
- WM_gizmo_operator_set(mpr, 0, ot, NULL);
+ WM_gizmo_operator_set(gz, 0, ot, NULL);
}
{
- wmGizmo *mpr = navgroup->mpr_array[MPR_CAMERA];
- WM_gizmo_operator_set(mpr, 0, ot_view_camera, NULL);
+ wmGizmo *gz = navgroup->gz_array[MPR_CAMERA];
+ WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL);
}
/* Click only buttons (not modal). */
{
- int mpr_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA};
- for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
- wmGizmo *mpr = navgroup->mpr_array[mpr_ids[i]];
- RNA_boolean_set(mpr->ptr, "show_drag", false);
+ int gz_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA};
+ for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
+ wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
+ RNA_boolean_set(gz->ptr, "show_drag", false);
}
}
/* Modal operators, don't use initial mouse location since we're clicking on a button. */
{
- int mpr_ids[] = {MPR_MOVE, MPR_ROTATE, MPR_ZOOM};
- for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
- wmGizmo *mpr = navgroup->mpr_array[mpr_ids[i]];
- wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, 0);
+ int gz_ids[] = {MPR_MOVE, MPR_ROTATE, MPR_ZOOM};
+ for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
+ wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
+ wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, 0);
RNA_boolean_set(&mpop->ptr, "use_mouse_init", false);
}
}
{
- wmGizmo *mpr = navgroup->mpr_array[MPR_ROTATE];
- mpr->scale_basis = GIZMO_SIZE / 2;
+ wmGizmo *gz = navgroup->gz_array[MPR_ROTATE];
+ gz->scale_basis = GIZMO_SIZE / 2;
char mapping[6] = {
RV3D_VIEW_LEFT,
RV3D_VIEW_RIGHT,
@@ -258,25 +258,25 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *
};
for (int part_index = 0; part_index < 6; part_index += 1) {
- PointerRNA *ptr = WM_gizmo_operator_set(mpr, part_index + 1, ot_view_axis, NULL);
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL);
RNA_enum_set(ptr, "type", mapping[part_index]);
}
/* When dragging an axis, use this instead. */
- mpr->drag_part = 0;
+ gz->drag_part = 0;
}
- mgroup->customdata = navgroup;
+ gzgroup->customdata = navgroup;
}
-static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NavigateWidgetGroup *navgroup = mgroup->customdata;
+ struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
ARegion *ar = CTX_wm_region(C);
const RegionView3D *rv3d = ar->regiondata;
for (int i = 0; i < 3; i++) {
- copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
+ copy_v3_v3(navgroup->gz_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
}
rcti rect_visible;
@@ -312,60 +312,60 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *m
rect_visible.ymax - icon_offset_mini * 0.75f,
};
- wmGizmo *mpr;
+ wmGizmo *gz;
- for (uint i = 0; i < ARRAY_SIZE(navgroup->mpr_array); i++) {
- mpr = navgroup->mpr_array[i];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
+ gz = navgroup->gz_array[i];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
/* RV3D_LOCKED or Camera: only show supported buttons. */
if (show_rotate) {
- mpr = navgroup->mpr_array[MPR_ROTATE];
- mpr->matrix_basis[3][0] = co_rotate[0];
- mpr->matrix_basis[3][1] = co_rotate[1];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ gz = navgroup->gz_array[MPR_ROTATE];
+ gz->matrix_basis[3][0] = co_rotate[0];
+ gz->matrix_basis[3][1] = co_rotate[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
int icon_mini_slot = 0;
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- mpr->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ gz = navgroup->gz_array[MPR_ZOOM];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- mpr->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ gz = navgroup->gz_array[MPR_MOVE];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- mpr = navgroup->mpr_array[MPR_CAMERA];
- mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- mpr->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ gz = navgroup->gz_array[MPR_CAMERA];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
if (navgroup->state.rv3d.is_camera == false) {
- mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO];
- mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
- mpr->matrix_basis[3][1] = co[1];
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
+ gz = navgroup->gz_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO];
+ gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][1] = co[1];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
}
-void VIEW3D_WGT_navigate(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_navigate(wmGizmoGroupType *gzgt)
{
- wgt->name = "View3D Navigate";
- wgt->idname = "VIEW3D_WGT_navigate";
+ gzgt->name = "View3D Navigate";
+ gzgt->idname = "VIEW3D_GGT_navigate";
- wgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
+ gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT |
WM_GIZMOGROUPTYPE_SCALE |
WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL);
- wgt->poll = WIDGETGROUP_navigate_poll;
- wgt->setup = WIDGETGROUP_navigate_setup;
- wgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
+ gzgt->poll = WIDGETGROUP_navigate_poll;
+ gzgt->setup = WIDGETGROUP_navigate_setup;
+ gzgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
index 041fe343526..5a4f910955e 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -84,7 +84,7 @@ static void draw_xyz_wire(
switch (axis) {
case 0: /* x axis */
- line_type = GWN_PRIM_LINES;
+ line_type = GPU_PRIM_LINES;
/* bottom left to top right */
negate_v3_v3(v1, dx);
@@ -105,7 +105,7 @@ static void draw_xyz_wire(
break;
case 1: /* y axis */
- line_type = GWN_PRIM_LINES;
+ line_type = GPU_PRIM_LINES;
/* bottom left to top right */
mul_v3_fl(dx, 0.75f);
@@ -127,7 +127,7 @@ static void draw_xyz_wire(
break;
case 2: /* z axis */
- line_type = GWN_PRIM_LINE_STRIP;
+ line_type = GPU_PRIM_LINE_STRIP;
/* start at top left */
negate_v3_v3(v1, dx);
@@ -168,12 +168,12 @@ static void draw_xyz_wire(
immEnd();
}
-static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool UNUSED(select))
+static void axis_geom_draw(const wmGizmo *gz, const float color[4], const bool UNUSED(select))
{
- GPU_line_width(mpr->line_width);
+ GPU_line_width(gz->line_width);
- Gwn_VertFormat *format = immVertexFormat();
- const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
struct {
@@ -182,12 +182,12 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
char axis;
char is_pos;
} axis_order[6] = {
- {-mpr->matrix_offset[0][2], 0, 0, false},
- {+mpr->matrix_offset[0][2], 1, 0, true},
- {-mpr->matrix_offset[1][2], 2, 1, false},
- {+mpr->matrix_offset[1][2], 3, 1, true},
- {-mpr->matrix_offset[2][2], 4, 2, false},
- {+mpr->matrix_offset[2][2], 5, 2, true},
+ {-gz->matrix_offset[0][2], 0, 0, false},
+ {+gz->matrix_offset[0][2], 1, 0, true},
+ {-gz->matrix_offset[1][2], 2, 1, false},
+ {+gz->matrix_offset[1][2], 3, 1, true},
+ {-gz->matrix_offset[2][2], 4, 2, false},
+ {+gz->matrix_offset[2][2], 5, 2, true},
};
qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
@@ -195,14 +195,14 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
static const float axis_highlight[4] = {1, 1, 1, 1};
static const float axis_black[4] = {0, 0, 0, 1};
static float axis_color[3][4];
- gpuPushMatrix();
- gpuMultMatrix(mpr->matrix_offset);
+ GPU_matrix_push();
+ GPU_matrix_mul(gz->matrix_offset);
bool draw_center_done = false;
int axis_align = -1;
for (int axis = 0; axis < 3; axis++) {
- if (len_squared_v2(mpr->matrix_offset[axis]) < 1e-6f) {
+ if (len_squared_v2(gz->matrix_offset[axis]) < 1e-6f) {
axis_align = axis;
break;
}
@@ -212,18 +212,18 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
const int index = axis_order[axis_index].index;
const int axis = axis_order[axis_index].axis;
const bool is_pos = axis_order[axis_index].is_pos;
- const bool is_highlight = index + 1 == mpr->highlight_part;
+ const bool is_highlight = index + 1 == gz->highlight_part;
/* Draw slightly before, so axis aligned arrows draw ontop. */
if ((draw_center_done == false) && (axis_order[axis_index].depth > -0.01f)) {
/* Circle defining active area (revert back to 2D space). */
{
- gpuPopMatrix();
+ GPU_matrix_pop();
immUniformColor4fv(color);
imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
- gpuPushMatrix();
- gpuMultMatrix(mpr->matrix_offset);
+ GPU_matrix_push();
+ GPU_matrix_mul(gz->matrix_offset);
}
draw_center_done = true;
}
@@ -237,10 +237,13 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
bool ok = true;
/* skip view align axis */
- if ((axis_align == axis) && (mpr->matrix_offset[axis][2] > 0.0f) == is_pos) {
+ if ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos) {
ok = false;
}
if (ok) {
+ /* Check aligned, since the front axis won't display in this case,
+ * and we want to make sure all 3 axes have a character at all times. */
+ const bool show_axis_char = (is_pos || (axis == axis_align));
const float v[3] = {0, 0, 3 * (is_pos ? 1 : -1)};
const float v_final[3] = {
v[index_x] * scale_axis,
@@ -257,7 +260,7 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
float v_start[3];
GPU_line_width(2.0f);
immUniformColor4fv(color_current);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
if (axis_align == -1) {
zero_v3(v_start);
}
@@ -276,75 +279,75 @@ static void axis_geom_draw(const wmGizmo *mpr, const float color[4], const bool
/* Axis Ball. */
{
- gpuPushMatrix();
- gpuTranslate3fv(v_final);
- gpuScaleUniform(is_pos ? 0.22f : 0.18f);
-
- Gwn_Batch *sphere = GPU_batch_preset_sphere(0);
- GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
- GWN_batch_uniform_4fv(sphere, "color", is_pos ? color_current : color_current_fade);
- GWN_batch_draw(sphere);
- gpuPopMatrix();
+ GPU_matrix_push();
+ GPU_matrix_translate_3fv(v_final);
+ GPU_matrix_scale_1f(show_axis_char ? 0.22f : 0.18f);
+
+ GPUBatch *sphere = GPU_batch_preset_sphere(0);
+ GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(sphere, "color", is_pos ? color_current : color_current_fade);
+ GPU_batch_draw(sphere);
+ GPU_matrix_pop();
}
/* Axis XYZ Character. */
- if (is_pos) {
+ if (show_axis_char) {
GPU_line_width(1.0f);
float m3[3][3];
- copy_m3_m4(m3, mpr->matrix_offset);
+ copy_m3_m4(m3, gz->matrix_offset);
immUniformColor4fv(is_highlight ? axis_black : axis_highlight);
draw_xyz_wire(pos_id, m3, v_final, 1.0, axis);
}
}
}
- gpuPopMatrix();
+ GPU_matrix_pop();
immUnbindProgram();
}
static void axis3d_draw_intern(
- const bContext *UNUSED(C), wmGizmo *mpr,
+ const bContext *UNUSED(C), wmGizmo *gz,
const bool select, const bool highlight)
{
- const float *color = highlight ? mpr->color_hi : mpr->color;
+ const float *color = highlight ? gz->color_hi : gz->color;
float matrix_final[4][4];
float matrix_unit[4][4];
unit_m4(matrix_unit);
WM_gizmo_calc_matrix_final_params(
- mpr,
+ gz,
&((struct WM_GizmoMatrixParams) {
.matrix_offset = matrix_unit,
}), matrix_final);
- gpuPushMatrix();
- gpuMultMatrix(matrix_final);
+ GPU_matrix_push();
+ GPU_matrix_mul(matrix_final);
GPU_blend(true);
- axis_geom_draw(mpr, color, select);
+ axis_geom_draw(gz, color, select);
GPU_blend(false);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
-static void gizmo_axis_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_axis_draw(const bContext *C, wmGizmo *gz)
{
- const bool is_modal = mpr->state & WM_GIZMO_STATE_MODAL;
- const bool is_highlight = (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
+ const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
+ const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
(void)is_modal;
GPU_blend(true);
- axis3d_draw_intern(C, mpr, false, is_highlight);
+ axis3d_draw_intern(C, gz, false, is_highlight);
GPU_blend(false);
}
static int gizmo_axis_test_select(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- float point_local[2] = {UNPACK2(event->mval)};
- sub_v2_v2(point_local, mpr->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * UI_DPI_FAC));
+ float point_local[2] = {UNPACK2(mval)};
+ sub_v2_v2(point_local, gz->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC));
const float len_sq = len_squared_v2(point_local);
if (len_sq > 1.0) {
@@ -358,14 +361,14 @@ static int gizmo_axis_test_select(
for (int i = 0; i < 3; i++) {
for (int is_pos = 0; is_pos < 2; is_pos++) {
float co[2] = {
- mpr->matrix_offset[i][0] * (is_pos ? 1 : -1),
- mpr->matrix_offset[i][1] * (is_pos ? 1 : -1),
+ gz->matrix_offset[i][0] * (is_pos ? 1 : -1),
+ gz->matrix_offset[i][1] * (is_pos ? 1 : -1),
};
bool ok = true;
/* Check if we're viewing on an axis, there is no point to clicking on the current axis so show the reverse. */
- if (len_squared_v2(co) < 1e-6f && (mpr->matrix_offset[i][2] > 0.0f) == is_pos) {
+ if (len_squared_v2(co) < 1e-6f && (gz->matrix_offset[i][2] > 0.0f) == is_pos) {
ok = false;
}
@@ -384,7 +387,7 @@ static int gizmo_axis_test_select(
return part_best;
}
- /* The 'mpr->scale_final' is already applied when projecting. */
+ /* The 'gz->scale_final' is already applied when projecting. */
if (len_sq < 1.0f) {
return 0;
}
@@ -392,23 +395,23 @@ static int gizmo_axis_test_select(
return -1;
}
-static int gizmo_axis_cursor_get(wmGizmo *mpr)
+static int gizmo_axis_cursor_get(wmGizmo *gz)
{
- if (mpr->highlight_part > 0) {
+ if (gz->highlight_part > 0) {
return CURSOR_EDIT;
}
return BC_NSEW_SCROLLCURSOR;
}
-void VIEW3D_WT_navigate_rotate(wmGizmoType *wt)
+void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "VIEW3D_WT_navigate_rotate";
+ gzt->idname = "VIEW3D_GT_navigate_rotate";
/* api callbacks */
- wt->draw = gizmo_axis_draw;
- wt->test_select = gizmo_axis_test_select;
- wt->cursor_get = gizmo_axis_cursor_get;
+ gzt->draw = gizmo_axis_draw;
+ gzt->test_select = gizmo_axis_test_select;
+ gzt->cursor_get = gizmo_axis_cursor_get;
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index ac6a984bea5..5853fa6e3b3 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -36,13 +36,16 @@
#include "BKE_object.h"
#include "BKE_unit.h"
+#include "BKE_material.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
#include "BIF_gl.h"
+#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
@@ -68,7 +71,7 @@
#include "BLF_api.h"
-static const char *view3d_wgt_ruler_id = "VIEW3D_WGT_ruler";
+static const char *view3d_gzgt_ruler_id = "VIEW3D_GGT_ruler";
#define MVAL_MAX_PX_DIST 12.0f
@@ -123,7 +126,7 @@ typedef struct RulerInfo {
/* Ruler Item (two or three points) */
typedef struct RulerItem {
- wmGizmo mpr;
+ wmGizmo gz;
/* worldspace coords, middle being optional */
float co[3][3];
@@ -143,18 +146,18 @@ typedef struct RulerInteraction {
/** \name Internal Ruler Utilities
* \{ */
-static RulerItem *ruler_item_add(wmGizmoGroup *mgroup)
+static RulerItem *ruler_item_add(wmGizmoGroup *gzgroup)
{
/* could pass this as an arg */
- const wmGizmoType *wt_ruler = WM_gizmotype_find("VIEW3D_WT_ruler_item", true);
- RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(wt_ruler, mgroup, NULL);
- WM_gizmo_set_flag(&ruler_item->mpr, WM_GIZMO_DRAW_MODAL, true);
+ const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true);
+ RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL);
+ WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true);
return ruler_item;
}
-static void ruler_item_remove(bContext *C, wmGizmoGroup *mgroup, RulerItem *ruler_item)
+static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *ruler_item)
{
- WM_gizmo_unlink(&mgroup->gizmos, mgroup->parent_mmap, &ruler_item->mpr, C);
+ WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C);
}
static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
@@ -192,10 +195,10 @@ static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
}
static bool view3d_ruler_pick(
- wmGizmoGroup *mgroup, RulerItem *ruler_item, const float mval[2],
+ wmGizmoGroup *gzgroup, RulerItem *ruler_item, const float mval[2],
int *r_co_index)
{
- RulerInfo *ruler_info = mgroup->customdata;
+ RulerInfo *ruler_info = gzgroup->customdata;
ARegion *ar = ruler_info->ar;
bool found = false;
@@ -304,7 +307,7 @@ static bool view3d_ruler_item_mousemove(
RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2],
const bool do_thickness, const bool do_snap)
{
- RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
const float eps_bias = 0.0002f;
float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
@@ -380,46 +383,37 @@ static bool view3d_ruler_item_mousemove(
* \{ */
#define RULER_ID "RulerData3D"
-static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *mgroup)
+static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
- // RulerInfo *ruler_info = mgroup->customdata;
+ // RulerInfo *ruler_info = gzgroup->customdata;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+
+ bGPdata *gpd;
bGPDlayer *gpl;
bGPDframe *gpf;
bGPDstroke *gps;
- bGPDpalette *palette;
- bGPDpalettecolor *palcolor;
RulerItem *ruler_item;
const char *ruler_name = RULER_ID;
bool changed = false;
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
}
+ gpd = scene->gpd;
- gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false);
+ gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
+ copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
gpl->thickness = 1;
gpl->flag |= GP_LAYER_HIDE;
}
- /* try to get active palette or create a new one */
- palette = BKE_gpencil_palette_getactive(scene->gpd);
- if (palette == NULL) {
- palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true);
- }
- /* try to get color with the ruler name or create a new one */
- palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name);
- if (palcolor == NULL) {
- palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true);
- }
-
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
BKE_gpencil_free_strokes(gpf);
- for (ruler_item = mgroup->gizmos.first; ruler_item; ruler_item = (RulerItem *)ruler_item->mpr.next) {
+ for (ruler_item = gzgroup->gizmos.first; ruler_item; ruler_item = (RulerItem *)ruler_item->gz.next) {
bGPDspoint *pt;
int j;
@@ -428,6 +422,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *mgroup)
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
gps->totpoints = 3;
pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
for (j = 0; j < 3; j++) {
copy_v3_v3(&pt->x, ruler_item->co[j]);
pt->pressure = 1.0f;
@@ -438,6 +433,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *mgroup)
else {
gps->totpoints = 2;
pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
for (j = 0; j < 3; j += 2) {
copy_v3_v3(&pt->x, ruler_item->co[j]);
pt->pressure = 1.0f;
@@ -447,9 +443,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *mgroup)
}
gps->flag = GP_STROKE_3DSPACE;
gps->thickness = 3;
- /* assign color to stroke */
- BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
- gps->palcolor = palcolor;
+
BLI_addtail(&gpf->strokes, gps);
changed = true;
}
@@ -457,7 +451,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *mgroup)
return changed;
}
-static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *mgroup)
+static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
{
Scene *scene = CTX_data_scene(C);
bool changed = false;
@@ -476,7 +470,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *mgroup)
int j;
RulerItem *ruler_item = NULL;
if (gps->totpoints == 3) {
- ruler_item = ruler_item_add(mgroup);
+ ruler_item = ruler_item_add(gzgroup);
for (j = 0; j < 3; j++) {
copy_v3_v3(ruler_item->co[j], &pt->x);
pt++;
@@ -485,7 +479,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *mgroup)
changed = true;
}
else if (gps->totpoints == 2) {
- ruler_item = ruler_item_add(mgroup);
+ ruler_item = ruler_item_add(gzgroup);
for (j = 0; j < 3; j += 2) {
copy_v3_v3(ruler_item->co[j], &pt->x);
pt++;
@@ -506,12 +500,12 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *mgroup)
/** \name Ruler Item Gizmo Type
* \{ */
-static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
+static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
{
Scene *scene = CTX_data_scene(C);
UnitSettings *unit = &scene->unit;
- RulerInfo *ruler_info = mpr->parent_mgroup->customdata;
- RulerItem *ruler_item = (RulerItem *)mpr;
+ RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)gz;
ARegion *ar = ruler_info->ar;
RegionView3D *rv3d = ar->regiondata;
const float cap_size = 4.0f;
@@ -536,7 +530,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
UI_GetThemeColor3ubv(TH_TEXT, color_text);
UI_GetThemeColor3ubv(TH_WIRE, color_wire);
- const bool is_act = (mpr->flag & WM_GIZMO_DRAW_HOVER);
+ const bool is_act = (gz->flag & WM_GIZMO_DRAW_HOVER);
float dir_ruler[2];
float co_ss[3][2];
int j;
@@ -548,7 +542,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
GPU_blend(true);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -562,7 +556,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
immUniform1f("dash_width", 6.0f);
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2fv(shdr_pos, co_ss[0]);
immVertex2fv(shdr_pos, co_ss[1]);
@@ -604,7 +598,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
for (j = 0; j <= arc_steps; j++) {
madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
@@ -637,7 +631,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
immVertex2fv(shdr_pos, cap);
@@ -702,7 +696,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
immUniform1f("dash_width", 6.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(shdr_pos, co_ss[0]);
immVertex2fv(shdr_pos, co_ss[2]);
@@ -726,7 +720,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
immVertex2fv(shdr_pos, cap);
@@ -785,15 +779,15 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
/* draw snap */
if ((ruler_info->snap_flag & RULER_SNAP_OK) &&
(ruler_info->state == RULER_STATE_DRAG) &&
- (ruler_item->mpr.interaction_data != NULL))
+ (ruler_item->gz.interaction_data != NULL))
{
- RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
/* size from drawSnapping */
const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
float co_ss_snap[3];
ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color_act);
@@ -805,14 +799,14 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *mpr)
}
static int gizmo_ruler_test_select(
- bContext *UNUSED(C), wmGizmo *mpr, const wmEvent *event)
+ bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
- RulerItem *ruler_item_pick = (RulerItem *)mpr;
- float mval_fl[2] = {UNPACK2(event->mval)};
+ RulerItem *ruler_item_pick = (RulerItem *)gz;
+ float mval_fl[2] = {UNPACK2(mval)};
int co_index;
/* select and drag */
- if (view3d_ruler_pick(mpr->parent_mgroup, ruler_item_pick, mval_fl, &co_index)) {
+ if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) {
if (co_index == -1) {
if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
return PART_LINE;
@@ -826,14 +820,14 @@ static int gizmo_ruler_test_select(
}
static int gizmo_ruler_modal(
- bContext *C, wmGizmo *mpr, const wmEvent *event,
+ bContext *C, wmGizmo *gz, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
bool do_draw = false;
int exit_code = OPERATOR_RUNNING_MODAL;
- RulerInfo *ruler_info = mpr->parent_mgroup->customdata;
- RulerItem *ruler_item = (RulerItem *)mpr;
- RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)gz;
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
ARegion *ar = CTX_wm_region(C);
ruler_info->ar = ar;
@@ -860,20 +854,20 @@ static int gizmo_ruler_modal(
}
static int gizmo_ruler_invoke(
- bContext *C, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmo *gz, const wmEvent *event)
{
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- RulerInfo *ruler_info = mgroup->customdata;
- RulerItem *ruler_item_pick = (RulerItem *)mpr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ RulerInfo *ruler_info = gzgroup->customdata;
+ RulerItem *ruler_item_pick = (RulerItem *)gz;
RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
- mpr->interaction_data = inter;
+ gz->interaction_data = inter;
ARegion *ar = ruler_info->ar;
const float mval_fl[2] = {UNPACK2(event->mval)};
/* select and drag */
- if (mpr->highlight_part == PART_LINE) {
+ if (gz->highlight_part == PART_LINE) {
if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
/* Add Center Point */
ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
@@ -903,7 +897,7 @@ static int gizmo_ruler_invoke(
}
}
else {
- inter->co_index = mpr->highlight_part;
+ inter->co_index = gz->highlight_part;
ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
/* store the initial depth */
@@ -913,15 +907,15 @@ static int gizmo_ruler_invoke(
return OPERATOR_RUNNING_MODAL;
}
-static void gizmo_ruler_exit(bContext *C, wmGizmo *mpr, const bool cancel)
+static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
{
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- RulerInfo *ruler_info = mgroup->customdata;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ RulerInfo *ruler_info = gzgroup->customdata;
if (!cancel) {
if (ruler_info->state == RULER_STATE_DRAG) {
- RulerItem *ruler_item = (RulerItem *)mpr;
- RulerInteraction *inter = mpr->interaction_data;
+ RulerItem *ruler_item = (RulerItem *)gz;
+ RulerInteraction *inter = gz->interaction_data;
/* rubber-band angle removal */
if (!inter->inside_region) {
if ((inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
@@ -930,9 +924,9 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *mpr, const bool cancel)
else {
/* Not ideal, since the ruler isn't a mode and we don't want to override delete key
* use dragging out of the view for removal. */
- ruler_item_remove(C, mgroup, ruler_item);
+ ruler_item_remove(C, gzgroup, ruler_item);
ruler_item = NULL;
- mpr = NULL;
+ gz = NULL;
inter = NULL;
}
}
@@ -942,38 +936,38 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *mpr, const bool cancel)
ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
}
/* We could convert only the current gizmo, for now just re-generate. */
- view3d_ruler_to_gpencil(C, mgroup);
+ view3d_ruler_to_gpencil(C, gzgroup);
}
- if (mpr) {
- MEM_SAFE_FREE(mpr->interaction_data);
+ if (gz) {
+ MEM_SAFE_FREE(gz->interaction_data);
}
ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
}
-static int gizmo_ruler_cursor_get(wmGizmo *mpr)
+static int gizmo_ruler_cursor_get(wmGizmo *gz)
{
- if (mpr->highlight_part == PART_LINE) {
+ if (gz->highlight_part == PART_LINE) {
return BC_CROSSCURSOR;
}
return BC_NSEW_SCROLLCURSOR;
}
-void VIEW3D_WT_ruler_item(wmGizmoType *wt)
+void VIEW3D_GT_ruler_item(wmGizmoType *gzt)
{
/* identifiers */
- wt->idname = "VIEW3D_WT_ruler_item";
+ gzt->idname = "VIEW3D_GT_ruler_item";
/* api callbacks */
- wt->draw = gizmo_ruler_draw;
- wt->test_select = gizmo_ruler_test_select;
- wt->modal = gizmo_ruler_modal;
- wt->invoke = gizmo_ruler_invoke;
- wt->exit = gizmo_ruler_exit;
- wt->cursor_get = gizmo_ruler_cursor_get;
-
- wt->struct_size = sizeof(RulerItem);
+ gzt->draw = gizmo_ruler_draw;
+ gzt->test_select = gizmo_ruler_test_select;
+ gzt->modal = gizmo_ruler_modal;
+ gzt->invoke = gizmo_ruler_invoke;
+ gzt->exit = gizmo_ruler_exit;
+ gzt->cursor_get = gizmo_ruler_cursor_get;
+
+ gzt->struct_size = sizeof(RulerItem);
}
/** \} */
@@ -982,23 +976,23 @@ void VIEW3D_WT_ruler_item(wmGizmoType *wt)
/** \name Ruler Gizmo Group
* \{ */
-static bool WIDGETGROUP_ruler_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool WIDGETGROUP_ruler_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
if ((tref_rt == NULL) ||
- !STREQ(wgt->idname, tref_rt->gizmo_group))
+ !STREQ(gzgt->idname, tref_rt->gizmo_group))
{
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
-static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
- if (view3d_ruler_from_gpencil(C, mgroup)) {
+ if (view3d_ruler_from_gpencil(C, gzgroup)) {
/* nop */
}
@@ -1009,21 +1003,21 @@ static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *mgroup)
ruler_info->sa = sa;
ruler_info->ar = ar;
- mgroup->customdata = ruler_info;
+ gzgroup->customdata = ruler_info;
}
-void VIEW3D_WGT_ruler(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
{
- wgt->name = "Ruler Widgets";
- wgt->idname = view3d_wgt_ruler_id;
+ gzgt->name = "Ruler Widgets";
+ gzgt->idname = view3d_gzgt_ruler_id;
- wgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = WIDGETGROUP_ruler_poll;
- wgt->setup = WIDGETGROUP_ruler_setup;
+ gzgt->poll = WIDGETGROUP_ruler_poll;
+ gzgt->setup = WIDGETGROUP_ruler_setup;
}
/** \} */
@@ -1036,7 +1030,7 @@ static bool view3d_ruler_poll(bContext *C)
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
if ((tref_rt == NULL) ||
- !STREQ(view3d_wgt_ruler_id, tref_rt->gizmo_group) ||
+ !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) ||
CTX_wm_region_view3d(C) == NULL)
{
return false;
@@ -1050,22 +1044,22 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *UNUSED(op), const wm
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
- wmGizmoMap *mmap = ar->gizmo_map;
- wmGizmoGroup *mgroup = WM_gizmomap_group_find(mmap, view3d_wgt_ruler_id);
- const bool use_depth = (v3d->drawtype >= OB_SOLID);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
+ const bool use_depth = (v3d->shading.type >= OB_SOLID);
/* Create new line */
RulerItem *ruler_item;
- ruler_item = ruler_item_add(mgroup);
+ ruler_item = ruler_item_add(gzgroup);
/* This is a little weak, but there is no real good way to tweak directly. */
- WM_gizmo_highlight_set(mmap, &ruler_item->mpr);
+ WM_gizmo_highlight_set(gzmap, &ruler_item->gz);
if (WM_operator_name_call(
C, "GIZMOGROUP_OT_gizmo_tweak",
WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL)
{
- RulerInfo *ruler_info = mgroup->customdata;
- RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ RulerInfo *ruler_info = gzgroup->customdata;
+ RulerInteraction *inter = ruler_item->gz.interaction_data;
if (use_depth) {
/* snap the first point added, not essential but handy */
inter->co_index = 0;
@@ -1079,7 +1073,7 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *UNUSED(op), const wm
}
copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
- ruler_item->mpr.highlight_part = inter->co_index = 2;
+ ruler_item->gz.highlight_part = inter->co_index = 2;
}
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index c9277235d50..83cabd2a60e 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -245,6 +245,7 @@ void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot)
/* api callbacks */
ot->exec = toggle_matcap_flip;
+ ot->poll = ED_operator_view3d_active;
}
/** \} */
@@ -320,7 +321,9 @@ static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C)
else {
uiLayout *row = uiLayoutRow(layout, true);
uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 89dd254c130..855ee7bb9fc 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -39,7 +39,7 @@ struct ARegion;
struct ARegionType;
struct Base;
struct BoundBox;
-struct Gwn_Batch;
+struct GPUBatch;
struct Depsgraph;
struct Object;
struct SmokeDomainSettings;
@@ -254,21 +254,21 @@ ARegion *view3d_has_tools_region(ScrArea *sa);
extern const char *view3d_context_dir[]; /* doc access */
/* view3d_widgets.c */
-void VIEW3D_WGT_lamp_spot(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_lamp_area(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_lamp_target(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_camera(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_camera_view(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_force_field(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_empty_image(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_armature_spline(struct wmGizmoGroupType *wgt);
-void VIEW3D_WGT_navigate(struct wmGizmoGroupType *wgt);
-
-void VIEW3D_WGT_ruler(struct wmGizmoGroupType *wgt);
-void VIEW3D_WT_ruler_item(struct wmGizmoType *wt);
+void VIEW3D_GGT_lamp_spot(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_lamp_area(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_lamp_target(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_camera(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_camera_view(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_force_field(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_empty_image(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_armature_spline(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GGT_navigate(struct wmGizmoGroupType *gzgt);
+
+void VIEW3D_GGT_ruler(struct wmGizmoGroupType *gzgt);
+void VIEW3D_GT_ruler_item(struct wmGizmoType *gzt);
void VIEW3D_OT_ruler_add(struct wmOperatorType *ot);
-void VIEW3D_WT_navigate_rotate(struct wmGizmoType *wt);
+void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt);
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index eae0cf8e459..74071e77901 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -380,7 +380,7 @@ void lattice_foreachScreenVert(
Object *obedit = vc->obedit;
Lattice *lt = obedit->data;
BPoint *bp = lt->editlatt->latt->def;
- DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL;
+ DispList *dl = obedit->runtime.curve_cache ? BKE_displist_find(&obedit->runtime.curve_cache->disp, DL_VERTS) : NULL;
const float *co = dl ? dl->verts : NULL;
int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 30b91c1a8ee..91e255aec82 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -677,7 +677,7 @@ void ED_view3d_project(const struct ARegion *ar, const float world[3], float reg
RegionView3D *rv3d = ar->regiondata;
int viewport[4] = {0, 0, ar->winx, ar->winy};
- gpuProject(world, rv3d->viewmat, rv3d->winmat, viewport, region);
+ GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region);
}
bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3])
@@ -686,5 +686,5 @@ bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony,
int viewport[4] = {0, 0, ar->winx, ar->winy};
float region[3] = {regionx, regiony, regionz};
- return gpuUnProject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
+ return GPU_matrix_unproject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
}
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 4617b92c780..0475159712b 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -26,9 +26,11 @@
/* defines VIEW3D_OT_ruler modal operator */
+#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_brush_types.h"
#include "MEM_guardedalloc.h"
@@ -40,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_unit.h"
#include "BIF_gl.h"
@@ -51,6 +54,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_transform_snap_object_context.h"
@@ -300,37 +304,28 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+
bGPDlayer *gpl;
bGPDframe *gpf;
bGPDstroke *gps;
- bGPDpalette *palette;
- bGPDpalettecolor *palcolor;
RulerItem *ruler_item;
const char *ruler_name = RULER_ID;
bool changed = false;
+ /* FIXME: This needs to be reviewed. Should it keep being done like this? */
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
}
+ bGPdata *gpd = scene->gpd;
- gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false);
+ gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
+ copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
gpl->thickness = 1;
gpl->flag |= GP_LAYER_HIDE;
}
- /* try to get active palette or create a new one */
- palette = BKE_gpencil_palette_getactive(scene->gpd);
- if (palette == NULL) {
- palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true);
- }
- /* try to get color with the ruler name or create a new one */
- palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name);
- if (palcolor == NULL) {
- palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true);
- }
-
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
BKE_gpencil_free_strokes(gpf);
@@ -343,6 +338,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
gps->totpoints = 3;
pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
for (j = 0; j < 3; j++) {
copy_v3_v3(&pt->x, ruler_item->co[j]);
pt->pressure = 1.0f;
@@ -353,6 +349,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
else {
gps->totpoints = 2;
pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
for (j = 0; j < 3; j += 2) {
copy_v3_v3(&pt->x, ruler_item->co[j]);
pt->pressure = 1.0f;
@@ -362,9 +359,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
}
gps->flag = GP_STROKE_3DSPACE;
gps->thickness = 3;
- /* assign color to stroke */
- BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
- gps->palcolor = palcolor;
+
BLI_addtail(&gpf->strokes, gps);
changed = true;
}
@@ -461,7 +456,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
GPU_blend(true);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -475,7 +470,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
immUniform1f("dash_width", 6.0f);
- immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immBegin(GPU_PRIM_LINE_STRIP, 3);
immVertex2fv(shdr_pos, co_ss[0]);
immVertex2fv(shdr_pos, co_ss[1]);
@@ -517,7 +512,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
for (j = 0; j <= arc_steps; j++) {
madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
@@ -550,7 +545,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
immVertex2fv(shdr_pos, cap);
@@ -614,7 +609,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
immUniform1f("dash_width", 6.0f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(shdr_pos, co_ss[0]);
immVertex2fv(shdr_pos, co_ss[2]);
@@ -638,7 +633,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
immUniformColor3ubv(color_wire);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
immVertex2fv(shdr_pos, cap);
@@ -703,7 +698,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
float co_ss[3];
ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color_act);
@@ -911,7 +906,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
BLI_listbase_is_empty(&ruler_info->items))
{
View3D *v3d = CTX_wm_view3d(C);
- const bool use_depth = (v3d->drawtype >= OB_SOLID);
+ const bool use_depth = (v3d->shading.type >= OB_SOLID);
/* Create new line */
RulerItem *ruler_item_prev = ruler_item_active_get(ruler_info);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 0f82dfa775c..2f65ad1fde4 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_tracking_types.h"
+#include "DNA_gpencil_types.h"
#include "MEM_guardedalloc.h"
@@ -76,6 +77,7 @@
#include "BKE_editmesh.h"
#include "BKE_scene.h"
#include "BKE_tracking.h"
+#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
@@ -95,6 +97,7 @@
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_mball.h"
+#include "ED_gpencil.h"
#include "UI_interface.h"
@@ -510,7 +513,7 @@ static void do_lasso_select_mesh(
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- gpuLoadMatrix(vc->rv3d->viewmat);
+ GPU_matrix_set(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) {
@@ -1189,7 +1192,7 @@ static int mixed_bones_object_selectbuffer(
/* define if we use solid nearest select or not */
if (use_cycle) {
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
do_nearest = true;
if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
do_nearest = false;
@@ -1198,7 +1201,7 @@ static int mixed_bones_object_selectbuffer(
copy_v2_v2_int(last_mval, mval);
}
else {
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
do_nearest = true;
}
}
@@ -1675,6 +1678,28 @@ static bool ed_object_select_pick(
if ((oldbasact != basact) && (is_obedit == false)) {
ED_object_base_activate(C, basact); /* adds notifier */
}
+
+ /* Set special modes for grease pencil
+ The grease pencil modes are not real modes, but a hack to make the interface
+ consistent, so need some tricks to keep UI synchronized */
+ // XXX: This stuff neeeds reviewing (Aligorith)
+ if (false &&
+ (((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
+ (basact->object->type == OB_GPENCIL)))
+ {
+ /* set cursor */
+ if (ELEM(basact->object->mode,
+ OB_MODE_GPENCIL_PAINT,
+ OB_MODE_GPENCIL_SCULPT,
+ OB_MODE_GPENCIL_WEIGHT))
+ {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ else {
+ /* TODO: maybe is better use restore */
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ }
}
DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
@@ -1936,7 +1961,7 @@ static int do_mesh_box_select(
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- gpuLoadMatrix(vc->rv3d->viewmat);
+ GPU_matrix_set(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 7799854db49..15be77ff6ab 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -72,6 +72,7 @@ static bool snap_calc_active_center(bContext *C, const bool select_only, float r
/* *********************** operators ******************** */
+/** Snaps every individual object center to its nearest point on the grid. **/
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -212,7 +213,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Selection to Grid";
- ot->description = "Snap selected item(s) to nearest grid division";
+ ot->description = "Snap selected item(s) to their nearest grid division";
ot->idname = "VIEW3D_OT_snap_selected_to_grid";
/* api callbacks */
@@ -220,11 +221,17 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
ot->poll = ED_operator_region_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* *************************************************** */
+/** Snaps the selection as a whole (use_offset=true) or each selected object to the given location.
+ *
+ * \param snap_target_global: a location in global space to snap to (eg. 3D cursor or active object).
+ * \param use_offset: if the selected objects should maintain their relative offsets and be snapped by the selection
+ * pivot point (median, active), or if every object origin should be snapped to the given location.
+**/
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -434,7 +441,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Selection to Cursor";
- ot->description = "Snap selected item(s) to cursor";
+ ot->description = "Snap selected item(s) to the 3D cursor";
ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
/* api callbacks */
@@ -442,12 +449,16 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* rna */
- RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", "");
+ RNA_def_boolean(ot->srna, "use_offset", 1, "Offset",
+ "If the selection should be snapped as a whole or by each object center");
}
+/* *************************************************** */
+
+/** Snaps each selected object to the location of the active selected object. **/
static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
{
float snap_target_global[3];
@@ -472,12 +483,13 @@ void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* *************************************************** */
+/** Snaps the 3D cursor location to its nearest point on the grid. **/
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -502,7 +514,7 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Cursor to Grid";
- ot->description = "Snap cursor to nearest grid division";
+ ot->description = "Snap 3D cursor to the nearest grid division";
ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
/* api callbacks */
@@ -515,7 +527,8 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
/* **************************************************** */
-static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float vec[3])
+/** Returns the center position of a tracking marker visible on the viewport (useful to snap to). **/
+static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float r_vec[3])
{
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
MovieTracking *tracking;
@@ -563,10 +576,11 @@ static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, floa
}
if (ok) {
- mid_v3_v3v3(vec, min, max);
+ mid_v3_v3v3(r_vec, min, max);
}
}
+/** Snaps the 3D cursor location to the median point of the selection. **/
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -690,7 +704,7 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Cursor to Selected";
- ot->description = "Snap cursor to center of selected item(s)";
+ ot->description = "Snap 3D cursor to the middle of the selected item(s)";
ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
/* api callbacks */
@@ -698,14 +712,16 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* ********************************************** */
-/* this could be exported to be a generic function
- * see: calculateCenterActive */
-
+/** Calculates the center position of the active object in global space.
+ *
+ * Note: this could be exported to be a generic function.
+ * see: calculateCenterActive
+**/
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
{
const Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -770,7 +786,7 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Cursor to Active";
- ot->description = "Snap cursor to active item";
+ ot->description = "Snap 3D cursor to the active item";
ot->idname = "VIEW3D_OT_snap_cursor_to_active";
/* api callbacks */
@@ -778,11 +794,12 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
}
/* **************************************************** */
-/*New Code - Snap Cursor to Center -*/
+
+/** Snaps the 3D cursor location to the origin. **/
static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -802,7 +819,7 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Snap Cursor to Center";
- ot->description = "Snap cursor to world origin";
+ ot->description = "Snap 3D cursor to the world origin";
ot->idname = "VIEW3D_OT_snap_cursor_to_center";
/* api callbacks */
@@ -815,23 +832,22 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
/* **************************************************** */
-
-bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
+/** Calculates the bounding box corners (min and max) for \a obedit. The returned values are in global space. **/
+bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
{
TransVertStore tvs = {NULL};
TransVert *tv;
float centroid[3], vec[3], bmat[3][3];
- int a;
- /* metaballs are an exception */
+ /* Metaballs are an exception. */
if (obedit->type == OB_MBALL) {
float ob_min[3], ob_max[3];
bool changed;
changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
if (changed) {
- minmax_v3v3_v3(min, max, ob_min);
- minmax_v3v3_v3(min, max, ob_max);
+ minmax_v3v3_v3(r_min, r_max, ob_min);
+ minmax_v3v3_v3(r_min, r_max, ob_max);
}
return changed;
}
@@ -845,12 +861,12 @@ bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
copy_m3_m4(bmat, obedit->obmat);
tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
mul_m3_v3(bmat, vec);
add_v3_v3(vec, obedit->obmat[3]);
add_v3_v3(centroid, vec);
- minmax_v3v3_v3(min, max, vec);
+ minmax_v3v3_v3(r_min, r_max, vec);
}
ED_transverts_free(&tvs);
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index ca5375b6b54..9b006bf4d9b 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -189,8 +189,8 @@ void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
RegionView3D *rv3d = ar->regiondata;
wmViewport(&ar->winrct); // TODO: bad
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index c9e915a6415..8a4a0efad2a 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -184,7 +184,7 @@ void ED_view3d_smooth_view_ex(
}
/* skip smooth viewing for render engine draw */
- if (smooth_viewtx && v3d->drawtype != OB_RENDER) {
+ if (smooth_viewtx && v3d->shading.type != OB_RENDER) {
bool changed = false; /* zero means no difference */
if (sview->camera_old != sview->camera)
@@ -721,14 +721,14 @@ void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d,
}
if (is_ortho) {
- gpuOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ GPU_matrix_ortho_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
else {
- gpuFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ GPU_matrix_frustum_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
/* update matrix in 3d view region */
- gpuGetProjectionMatrix(rv3d->winmat);
+ GPU_matrix_projection_get(rv3d->winmat);
}
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
@@ -1003,7 +1003,7 @@ int view3d_opengl_select(
* the object & bone view locking takes 'rect' into account, see: T51629. */
ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
GPU_depth_test(true);
}
@@ -1048,7 +1048,7 @@ int view3d_opengl_select(
G.f &= ~G_PICKSEL;
ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
GPU_depth_test(false);
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 4c5150fabdd..e4e12cc3686 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -343,14 +343,14 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
yoff = walk->ar->winy / 2;
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_VIEW_OVERLAY);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
/* North */
immVertex2i(pos, xoff, yoff + inner_length);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ad7b5d55ba5..142460bb7fa 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -41,9 +41,11 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_mask_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h" /* PET modes */
#include "DNA_workspace_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_alloca.h"
#include "BLI_utildefines.h"
@@ -64,6 +66,7 @@
#include "BKE_unit.h"
#include "BKE_scene.h"
#include "BKE_mask.h"
+#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_workspace.h"
@@ -85,6 +88,7 @@
#include "ED_mesh.h"
#include "ED_clip.h"
#include "ED_node.h"
+#include "ED_gpencil.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -95,6 +99,7 @@
#include "UI_resources.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -115,6 +120,7 @@ static void postInputRotation(TransInfo *t, float values[3]);
static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
static void initSnapSpatial(TransInfo *t, float r_snap[3]);
+static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm);
/* Transform Callbacks */
static void initBend(TransInfo *t);
@@ -140,6 +146,9 @@ static void applyToSphere(TransInfo *t, const int mval[2]);
static void initRotation(TransInfo *t);
static void applyRotation(TransInfo *t, const int mval[2]);
+static void initNormalRotation(TransInfo *t);
+static void applyNormalRotation(TransInfo *t, const int mval[2]);
+
static void initShrinkFatten(TransInfo *t);
static void applyShrinkFatten(TransInfo *t, const int mval[2]);
@@ -571,6 +580,10 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
if (t->options & CTX_GPENCIL_STROKES) {
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, OB_RECALC_DATA);
+ }
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
else if (t->spacetype == SPACE_VIEW3D) {
@@ -1546,6 +1559,18 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
+ case NKEY:
+ if (ELEM(t->mode, TFM_ROTATION)) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initNormalRotation(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
default:
break;
}
@@ -1689,13 +1714,13 @@ typedef enum {
} ArrowDirection;
#define POS_INDEX 0
-/* NOTE: this --^ is a bit hackish, but simplifies Gwn_VertFormat usage among functions
+/* NOTE: this --^ is a bit hackish, but simplifies GPUVertFormat usage among functions
* private to this file - merwin
*/
static void drawArrow(ArrowDirection d, short offset, short length, short size)
{
- immBegin(GWN_PRIM_LINES, 6);
+ immBegin(GPU_PRIM_LINES, 6);
switch (d) {
case LEFT:
@@ -1732,7 +1757,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
static void drawArrowHead(ArrowDirection d, short size)
{
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
switch (d) {
case LEFT:
@@ -1765,7 +1790,7 @@ static void drawArc(float size, float angle_start, float angle_end, int segments
float angle;
int a;
- immBegin(GWN_PRIM_LINE_STRIP, segments + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
@@ -1784,7 +1809,7 @@ static bool helpline_poll(bContext *C)
return 0;
}
-static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
+static void drawHelpline(bContext *C, int x, int y, void *customdata)
{
TransInfo *t = (TransInfo *)customdata;
@@ -1800,7 +1825,31 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
(float)t->mval[1],
};
- projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ /* grease pencil only can edit one object at time because GP has
+ * multiframe edition that replaces multiobject edition.
+ * If multiobject edition is added, maybe this code will need
+ * an update
+ */
+ if ((t->flag & T_POINTS) && (t->options & CTX_GPENCIL_STROKES) &&
+ (t->around != V3D_AROUND_ACTIVE))
+ {
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc) {
+ float vecrot[3];
+ copy_v3_v3(vecrot, t->center_global);
+ mul_m4_v3(ob->obmat, vecrot);
+ projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ }
+ }
+ else {
+ /* normally, never must be used */
+ projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ }
+ }
+ else {
+ projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ }
/* Offset the values for the area region. */
const float offset[2] = {
@@ -1813,11 +1862,11 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
tmval[i] += offset[i];
}
- gpuPushMatrix();
+ GPU_matrix_push();
/* Dashed lines first. */
if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
BLI_assert(shdr_pos == POS_INDEX);
@@ -1835,7 +1884,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(POS_INDEX, cent);
immVertex2f(POS_INDEX, tmval[0], tmval[1]);
immEnd();
@@ -1844,7 +1893,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
}
/* And now, solid lines. */
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
UNUSED_VARS_NDEBUG(pos); /* silence warning */
BLI_assert(pos == POS_INDEX);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1853,8 +1902,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_SPRING:
immUniformThemeColor(TH_VIEW_OVERLAY);
- gpuTranslate3fv(mval);
- gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
+ GPU_matrix_translate_3fv(mval);
+ GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
GPU_line_width(3.0f);
drawArrow(UP, 5, 10, 5);
@@ -1862,7 +1911,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
break;
case HLP_HARROW:
immUniformThemeColor(TH_VIEW_OVERLAY);
- gpuTranslate3fv(mval);
+ GPU_matrix_translate_3fv(mval);
GPU_line_width(3.0f);
drawArrow(RIGHT, 5, 10, 5);
@@ -1871,7 +1920,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_VARROW:
immUniformThemeColor(TH_VIEW_OVERLAY);
- gpuTranslate3fv(mval);
+ GPU_matrix_translate_3fv(mval);
GPU_line_width(3.0f);
drawArrow(UP, 5, 10, 5);
@@ -1887,23 +1936,23 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
immUniformThemeColor(TH_VIEW_OVERLAY);
- gpuTranslate3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
+ GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
GPU_line_width(3.0f);
drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
- gpuPushMatrix();
+ GPU_matrix_push();
- gpuTranslate3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
- gpuRotateAxis(RAD2DEGF(angle - delta_angle), 'Z');
+ GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z');
drawArrowHead(DOWN, 5);
- gpuPopMatrix();
+ GPU_matrix_pop();
- gpuTranslate3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
- gpuRotateAxis(RAD2DEGF(angle + delta_angle), 'Z');
+ GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z');
drawArrowHead(UP, 5);
break;
@@ -1913,7 +1962,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
unsigned char col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
- gpuTranslate3fv(mval);
+ GPU_matrix_translate_3fv(mval);
GPU_line_width(3.0f);
@@ -1933,7 +1982,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
}
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
@@ -2153,7 +2202,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
- RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ /* Only set if needed, so we can hide in the UI when nothing is set.
+ * See 'transform_poll_property'. */
+ if (ELEM(true, UNPACK3(constraint_axis))) {
+ RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ }
}
{
@@ -2501,6 +2554,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
case TFM_SEQ_SLIDE:
initSeqSlide(t);
break;
+ case TFM_NORMAL_ROTATION:
+ initNormalRotation(t);
+ break;
}
if (t->state == TRANS_CANCEL) {
@@ -2508,6 +2564,39 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
return 0;
}
+ if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc) {
+ if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) {
+ BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit);
+ bool do_skip = false;
+
+ /* Currently only used for two of three most frequent transform ops, can include more ops.
+ * Note that scaling cannot be included here, non-uniform scaling will affect normals. */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) {
+ if (em->bm->totvertsel == em->bm->totvert) {
+ /* No need to invalidate if whole mesh is selected. */
+ do_skip = true;
+ }
+ }
+
+ if (t->flag & T_MODAL) {
+ RNA_property_boolean_set(op->ptr, prop, false);
+ }
+ else if (!do_skip) {
+ const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
+ if (preserve_clnor) {
+ BKE_editmesh_lnorspace_update(em);
+ t->flag |= T_CLNOR_REBUILD;
+ }
+ BM_lnorspace_invalidate(em->bm, true);
+ }
+ }
+ }
+ }
+ }
+
t->context = NULL;
return 1;
@@ -2568,6 +2657,12 @@ int transformEnd(bContext *C, TransInfo *t)
restoreTransObjects(t); // calls recalcData()
}
else {
+ if (t->flag & T_CLNOR_REBUILD) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BM_lnorspace_rebuild(em->bm, true);
+ }
+ }
exit_code = OPERATOR_FINISHED;
}
@@ -3547,7 +3642,25 @@ static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, f
else
sub_v3_v3(vec, td->center);
- mul_v3_fl(vec, td->factor);
+ /* grease pencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+
+ /* scale stroke thickness */
+ if (td->val) {
+ snapGridIncrement(t, t->values);
+ applyNumInput(&t->num, t->values);
+
+ float ratio = t->values[0];
+ *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
+ CLAMP_MIN(*td->val, 0.001f);
+ }
+
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
if (t->flag & (T_OBJECT | T_POSE)) {
mul_m3_v3(td->smtx, vec);
@@ -3886,6 +3999,28 @@ static void initRotation(TransInfo *t)
copy_v3_v3(t->axis_orig, t->axis);
}
+/* Used by Transform Rotation and Transform Normal Rotation */
+static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
+{
+ size_t ofs = 0;
+
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"),
+ RAD2DEGF(final), t->con.text, t->proptext);
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
+}
+
/**
* Applies values of rotation to `td->loc` and `td->ext->quat`
* based on a rotation matrix (mat) and a pivot (center).
@@ -3901,6 +4036,20 @@ static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData *
mul_m3_m3m3(totmat, mat, td->mtx);
mul_m3_m3m3(smat, td->smtx, totmat);
+ /* apply gpencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ float sx = smat[0][0];
+ float sy = smat[1][1];
+ float sz = smat[2][2];
+
+ mul_m3_fl(smat, gps->runtime.multi_frame_falloff);
+ /* fix scale */
+ smat[0][0] = sx;
+ smat[1][1] = sy;
+ smat[2][2] = sz;
+ }
+
sub_v3_v3v3(vec, td->iloc, center);
mul_m3_v3(smat, vec);
@@ -4149,7 +4298,6 @@ static void applyRotationValue(TransInfo *t, float angle, float axis[3])
static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
{
char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
float final;
@@ -4172,21 +4320,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
t->values[0] = final;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %.2f%s %s"),
- RAD2DEGF(final), t->con.text, t->proptext);
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ headerRotation(t, str, final);
applyRotationValue(t, final, t->axis);
@@ -4315,6 +4449,127 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
/* -------------------------------------------------------------------- */
+/* Transform (Normal Rotation) */
+
+/** \name Transform Normal Rotation
+* \{ */
+
+static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ tc->custom.mode.data = lnors_ed_arr;
+ tc->custom.mode.free_cb = freeCustomNormalArray;
+}
+
+void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data;
+
+ if (t->state == TRANS_CANCEL) {
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { /* Restore custom loop normal on cancel */
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data);
+ }
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+
+ tc->custom.mode.data = NULL;
+ tc->custom.mode.free_cb = NULL;
+}
+
+static void initNormalRotation(TransInfo *t)
+{
+ t->mode = TFM_NORMAL_ROTATION;
+ t->transform = applyNormalRotation;
+
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ BKE_editmesh_lnorspace_update(em);
+
+ storeCustomLNorValue(tc, bm);
+ }
+
+ negate_v3_v3(t->axis, t->viewinv[2]);
+ normalize_v3(t->axis);
+
+ copy_v3_v3(t->axis_orig, t->axis);
+}
+
+/* Works by getting custom normal from clnor_data, transform, then store */
+static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, t->axis, NULL);
+ }
+ else {
+ /* reset axis if constraint is not set */
+ copy_v3_v3(t->axis, t->axis_orig);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data;
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ float axis[3];
+ float mat[3][3];
+ float angle = t->values[0];
+ copy_v3_v3(axis, t->axis);
+
+ snapGridIncrement(t, &angle);
+
+ applySnapping(t, &angle);
+
+ applyNumInput(&t->num, &angle);
+
+ headerRotation(t, str, angle);
+
+ axis_angle_normalized_to_mat3(mat, axis, angle);
+
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc);
+
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
/* Transform (Translation) */
static void initSnapSpatial(TransInfo *t, float r_snap[3])
@@ -4574,7 +4829,21 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
}
mul_m3_v3(td->smtx, tvec);
- mul_v3_fl(tvec, td->factor);
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(tvec, td->factor);
+ }
+ }
+ else {
+ /* proportional editing falloff */
+ mul_v3_fl(tvec, td->factor);
+ }
protectedTransBits(td->protectflag, tvec);
@@ -6654,7 +6923,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t
if (t->spacetype == SPACE_VIEW3D) {
v3d = t->sa ? t->sa->spacedata.first : NULL;
rv3d = t->ar ? t->ar->regiondata : NULL;
- use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
+ use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE);
}
calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
@@ -6849,7 +7118,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *t
if (t->spacetype == SPACE_VIEW3D) {
v3d = t->sa ? t->sa->spacedata.first : NULL;
rv3d = t->ar ? t->ar->regiondata : NULL;
- use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
+ use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE);
}
calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false);
@@ -7049,10 +7318,10 @@ static void drawEdgeSlide(TransInfo *t)
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- gpuPushMatrix();
- gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -7069,7 +7338,7 @@ static void drawEdgeSlide(TransInfo *t)
GPU_line_width(line_size);
immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBeginAtMost(GWN_PRIM_LINES, 4);
+ immBeginAtMost(GPU_PRIM_LINES, 4);
if (curr_sv->v_side[0]) {
immVertex3fv(pos, curr_sv->v_side[0]->co);
immVertex3fv(pos, curr_sv->v_co_orig);
@@ -7082,7 +7351,7 @@ static void drawEdgeSlide(TransInfo *t)
immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
GPU_point_size(ctrl_size);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
if (slp->flipped) {
if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
}
@@ -7093,7 +7362,7 @@ static void drawEdgeSlide(TransInfo *t)
immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
GPU_point_size(guide_size);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
immVertex3fv(pos, co_mark);
immEnd();
@@ -7107,7 +7376,7 @@ static void drawEdgeSlide(TransInfo *t)
GPU_line_width(line_size);
immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBegin(GWN_PRIM_LINES, sld->totsv * 2);
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
/* TODO(campbell): Loop over all verts */
sv = sld->sv;
@@ -7138,7 +7407,7 @@ static void drawEdgeSlide(TransInfo *t)
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
GPU_blend(false);
@@ -7682,17 +7951,17 @@ static void drawVertSlide(TransInfo *t)
GPU_blend(true);
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- gpuPushMatrix();
- gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
GPU_line_width(line_size);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBegin(GWN_PRIM_LINES, sld->totsv * 2);
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
if (is_clamp) {
sv = sld->sv;
for (i = 0; i < sld->totsv; i++, sv++) {
@@ -7718,7 +7987,7 @@ static void drawVertSlide(TransInfo *t)
GPU_point_size(ctrl_size);
- immBegin(GWN_PRIM_POINTS, 1);
+ immBegin(GPU_PRIM_POINTS, 1);
immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ?
curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
curr_sv->co_orig_3d);
@@ -7761,7 +8030,7 @@ static void drawVertSlide(TransInfo *t)
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
immVertex3fv(shdr_pos, co_dest_3d);
immEnd();
@@ -7769,7 +8038,7 @@ static void drawVertSlide(TransInfo *t)
immUnbindProgram();
}
- gpuPopMatrix();
+ GPU_matrix_pop();
GPU_depth_test(true);
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 2006bd830b4..dfcd3e4cfd6 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -505,7 +505,7 @@ typedef struct TransInfo {
short current_orientation;
TransformOrientation *custom_orientation; /* this gets used when current_orientation is V3D_MANIP_CUSTOM */
- short mpr_flag; /* backup from view3d, to restore on end */
+ short gizmo_flag; /* backup from view3d, to restore on end */
short prop_mode;
@@ -609,6 +609,8 @@ typedef struct TransInfo {
#define T_MODAL_CURSOR_SET (1 << 26)
+#define T_CLNOR_REBUILD (1 << 27)
+
/* TransInfo->modifiers */
#define MOD_CONSTRAINT_SELECT 0x01
#define MOD_PRECISION 0x02
@@ -877,6 +879,8 @@ bool applyTransformOrientation(const struct TransformOrientation *ts, float r_ma
int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around);
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
+void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
+
void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
void projectEdgeSlideData(TransInfo *t, bool is_final);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index d40602f8d43..b24ef4e0ba2 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -560,7 +560,9 @@ static void applyObjectConstraintRot(
/* on setup call, use first object */
if (td == NULL) {
- td = TRANS_DATA_CONTAINER_FIRST_OK(t)->data;
+ BLI_assert(tc == NULL);
+ tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ td = tc->data;
}
if (t->flag & T_EDIT) {
@@ -747,7 +749,7 @@ void drawConstraint(TransInfo *t)
if (depth_test_enabled)
GPU_depth_test(false);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
@@ -760,7 +762,7 @@ void drawConstraint(TransInfo *t)
immUniform1f("dash_width", 2.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(shdr_pos, t->center_global);
immVertex3fv(shdr_pos, vec);
immEnd();
@@ -800,13 +802,13 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
unit_m4(imat);
}
- gpuPushMatrix();
+ GPU_matrix_push();
if (t->spacetype == SPACE_VIEW3D) {
/* pass */
}
else if (t->spacetype == SPACE_IMAGE) {
- gpuScale2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
+ GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
}
else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) {
/* only scale y */
@@ -816,14 +818,14 @@ 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);
- gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask));
+ GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask));
}
depth_test_enabled = GPU_depth_test_enabled();
if (depth_test_enabled)
GPU_depth_test(false);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor(TH_GRID);
@@ -837,7 +839,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
if (depth_test_enabled)
GPU_depth_test(true);
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index a5706f4a003..d3b7417c4dd 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -90,6 +90,7 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
+#include "BKE_colortools.h"
#include "BIK_api.h"
@@ -747,7 +748,7 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
/* sets transform flags in the bones
* returns total number of bones with BONE_TRANSFORM */
-int count_set_pose_transflags(Object *ob, const int mode, short around, bool has_translate_rotate[2])
+int count_set_pose_transflags(Object *ob, const int mode, const short around, bool has_translate_rotate[2])
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
@@ -3609,6 +3610,8 @@ static void posttrans_gpd_clean(bGPdata *gpd)
}
#endif
}
+ /* set cache flag to dirty */
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
}
static void posttrans_mask_clean(Mask *mask)
@@ -8086,7 +8089,14 @@ void flushTransPaintCurve(TransInfo *t)
static void createTransGPencil(bContext *C, TransInfo *t)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C); \
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_FRAME_FALLOFF) != 0;
+
+ Object *obact = CTX_data_active_object(C);
bGPDlayer *gpl;
TransData *td = NULL;
float mtx[3][3], smtx[3][3];
@@ -8110,50 +8120,67 @@ static void createTransGPencil(bContext *C, TransInfo *t)
if (gpd == NULL)
return;
+ /* initialize falloff curve */
+ if (is_multiedit) {
+ curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
/* First Pass: Count the number of datapoints required for the strokes,
* (and additional info about the configuration - e.g. 2D/3D?)
*/
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
- bGPDframe *gpf = gpl->actframe;
+ bGPDframe *gpf;
bGPDstroke *gps;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* 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;
- }
+ for (gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* 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(obact, gpl, gps) == false) {
+ continue;
+ }
- if (is_prop_edit) {
- /* Proportional Editing... */
- if (is_prop_edit_connected) {
- /* connected only - so only if selected */
- if (gps->flag & GP_STROKE_SELECT)
- tc->data_len += gps->totpoints;
- }
- else {
- /* everything goes - connection status doesn't matter */
- tc->data_len += gps->totpoints;
- }
- }
- else {
- /* only selected stroke points are considered */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- // TODO: 2D vs 3D?
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT)
- tc->data_len++;
+ if (is_prop_edit) {
+ /* Proportional Editing... */
+ if (is_prop_edit_connected) {
+ /* connected only - so only if selected */
+ if (gps->flag & GP_STROKE_SELECT)
+ tc->data_len += gps->totpoints;
+ }
+ else {
+ /* everything goes - connection status doesn't matter */
+ tc->data_len += gps->totpoints;
+ }
+ }
+ else {
+ /* only selected stroke points are considered */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ // TODO: 2D vs 3D?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT)
+ tc->data_len++;
+ }
+ }
}
}
}
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
}
}
}
@@ -8180,153 +8207,166 @@ static void createTransGPencil(bContext *C, TransInfo *t)
float diff_mat[4][4];
float inverse_diff_mat[4][4];
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- /* undo matrix */
- invert_m4_m4(inverse_diff_mat, diff_mat);
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
}
+ /* init multiframe falloff options */
+ int f_init = 0;
+ int f_end = 0;
+
+ if (use_multiframe_falloff) {
+ BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ }
+
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
/* Make a new frame to work on if the layer's frame and the current scene frame don't match up
* - This is useful when animating as it saves that "uh-oh" moment when you realize you've
* spent too much time editing the wrong frame...
*/
- if (gpf->framenum != cfra) {
+ // XXX: should this be allowed when framelock is enabled?
+ if ((gpf->framenum != cfra) && (!is_multiedit)) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
/* in some weird situations (framelock enabled) return NULL */
if (gpf == NULL) {
continue;
}
+ if (!is_multiedit) {
+ init_gpf = gpf;
+ }
}
/* Loop over strokes, adding TransData for points as needed... */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- TransData *head = td;
- TransData *tail = td;
- bool stroke_ok;
-
- /* 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;
- }
- /* What we need to include depends on proportional editing settings... */
- if (is_prop_edit) {
- if (is_prop_edit_connected) {
- /* A) "Connected" - Only those in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
- else {
- /* B) All points, always */
- stroke_ok = true;
- }
- }
- else {
- /* C) Only selected points in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
-
- /* Do stroke... */
- if (stroke_ok && gps->totpoints) {
- bGPDspoint *pt;
- int i;
-
-#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */
- const float ninv = 1.0f / gps->totpoints;
- float center[3] = {0.0f};
-
- /* compute midpoint of stroke */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- madd_v3_v3v3fl(center, center, &pt->x, ninv);
+ for (gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+
+ /* if multiframe and falloff, recalculate and save value */
+ float falloff = 1.0f; /* by default no falloff */
+ if ((is_multiedit) && (use_multiframe_falloff)) {
+ /* Faloff depends on distance to active frame (relative to the overall frame range) */
+ falloff = BKE_gpencil_multiframe_falloff_calc(gpf, gpl->actframe->framenum,
+ f_init, f_end, ts->gp_sculpt.cur_falloff);
}
-#endif
- /* add all necessary points... */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- bool point_ok;
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ TransData *head = td;
+ TransData *tail = td;
+ bool stroke_ok;
- /* include point? */
+ /* 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(obact, gpl, gps) == false) {
+ continue;
+ }
+ /* What we need to include depends on proportional editing settings... */
if (is_prop_edit) {
- /* Always all points in strokes that get included */
- point_ok = true;
+ if (is_prop_edit_connected) {
+ /* A) "Connected" - Only those in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+ else {
+ /* B) All points, always */
+ stroke_ok = true;
+ }
}
else {
- /* Only selected points in selected strokes */
- point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
+ /* C) Only selected points in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
}
- /* do point... */
- if (point_ok) {
- copy_v3_v3(td->iloc, &pt->x);
- copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local?
-
- td->loc = &pt->x;
-
- td->flag = 0;
+ /* Do stroke... */
+ if (stroke_ok && gps->totpoints) {
+ bGPDspoint *pt;
+ int i;
- if (pt->flag & GP_SPOINT_SELECT)
- td->flag |= TD_SELECTED;
-
- /* for other transform modes (e.g. shrink-fatten), need to additional data */
- if (t->mode == TFM_GPENCIL_SHRINKFATTEN) {
- td->val = &pt->pressure;
- td->ival = pt->pressure;
- }
+ /* save falloff factor */
+ gps->runtime.multi_frame_falloff = falloff;
- /* screenspace needs special matrices... */
- if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) {
- /* screenspace */
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ /* add all necessary points... */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bool point_ok;
- /* apply parent transformations */
- if (gpl->parent == NULL) {
- copy_m3_m4(td->smtx, t->persmat);
- copy_m3_m4(td->mtx, t->persinv);
- unit_m3(td->axismtx);
+ /* include point? */
+ if (is_prop_edit) {
+ /* Always all points in strokes that get included */
+ point_ok = true;
}
else {
- /* apply matrix transformation relative to parent */
- copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
- copy_m3_m4(td->mtx, diff_mat); /* display position */
- copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
- }
- }
- else {
- /* configure 2D dataspace points so that they don't play up... */
- if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
- // XXX: matrices may need to be different?
+ /* Only selected points in selected strokes */
+ point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
}
- /* apply parent transformations */
- if (gpl->parent == NULL) {
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- unit_m3(td->axismtx); // XXX?
- }
- else {
- /* apply matrix transformation relative to parent */
- copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
- copy_m3_m4(td->mtx, diff_mat); /* display position */
- copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
+ /* do point... */
+ if (point_ok) {
+ copy_v3_v3(td->iloc, &pt->x);
+ copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local?
+
+ td->loc = &pt->x;
+
+ td->flag = 0;
+
+ if (pt->flag & GP_SPOINT_SELECT)
+ td->flag |= TD_SELECTED;
+
+ /* for other transform modes (e.g. shrink-fatten), need to additional data
+ * but never for scale or mirror
+ */
+ if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
+ td->val = &pt->pressure;
+ td->ival = pt->pressure;
+ }
+
+ /* screenspace needs special matrices... */
+ if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) {
+ /* screenspace */
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+
+ /* apply matrix transformation relative to parent */
+ copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
+ copy_m3_m4(td->mtx, diff_mat); /* display position */
+ copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
+ }
+ else {
+ /* configure 2D dataspace points so that they don't play up... */
+ if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ // XXX: matrices may need to be different?
+ }
+
+ /* apply parent transformations */
+ copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
+ copy_m3_m4(td->mtx, diff_mat); /* display position */
+ copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
+ }
+ /* Triangulation must be calculated again, so save the stroke for recalc function */
+ td->extra = gps;
+
+ /* save pointer to object */
+ td->ob = obact;
+
+ td++;
+ tail++;
}
}
- /* Triangulation must be calculated again, so save the stroke for recalc function */
- td->extra = gps;
- td++;
- tail++;
+ /* March over these points, and calculate the proportional editing distances */
+ if (is_prop_edit && (head != tail)) {
+ /* XXX: for now, we are similar enough that this works... */
+ calc_distanceCurveVerts(head, tail - 1);
+ }
}
}
-
- /* March over these points, and calculate the proportional editing distances */
- if (is_prop_edit && (head != tail)) {
- /* XXX: for now, we are similar enough that this works... */
- calc_distanceCurveVerts(head, tail - 1);
- }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
}
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index e32bef72cf6..a2377166dff 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -74,6 +74,7 @@
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -105,6 +106,7 @@
#include "ED_curve.h" /* for curve_editnurbs */
#include "ED_clip.h"
#include "ED_screen.h"
+#include "ED_gpencil.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -379,7 +381,8 @@ static void recalcData_actedit(TransInfo *t)
/* flush transform values back to actual coordinates */
flushTransIntFrameActionData(t);
}
- else {
+
+ if (ac.datatype != ANIMCONT_MASK) {
/* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@@ -1116,7 +1119,7 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->view;
- gpuPushMatrix();
+ GPU_matrix_push();
copy_v3_v3(v3, dir);
mul_v3_fl(v3, v3d->far);
@@ -1132,19 +1135,19 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
}
UI_make_axis_color(col, col2, axis);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3ubv(col2);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3fv(pos, v1);
immVertex3fv(pos, v2);
immEnd();
immUnbindProgram();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
@@ -1311,7 +1314,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
/* GPencil editing context */
- if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
+ if (GPENCIL_ANY_MODE(gpd)) {
t->options |= CTX_GPENCIL_STROKES;
}
@@ -1350,8 +1353,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* turn gizmo off during transform */
if (t->flag & T_MODAL) {
- t->mpr_flag = v3d->mpr_flag;
- v3d->mpr_flag = V3D_GIZMO_HIDE;
+ t->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
}
if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
@@ -1690,7 +1693,7 @@ void postTrans(bContext *C, TransInfo *t)
View3D *v3d = t->sa->spacedata.first;
/* restore gizmo */
if (t->flag & T_MODAL) {
- v3d->mpr_flag = t->mpr_flag;
+ v3d->gizmo_flag = t->gizmo_flag;
}
}
@@ -1823,6 +1826,21 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
}
r_center[2] = 0.0f;
}
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ /* move cursor in local space */
+ TransData *td = NULL;
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ float mat[3][3], imat[3][3];
+
+ td = tc->data;
+ Object *ob = td->ob;
+
+ sub_v3_v3v3(r_center, r_center, ob->obmat[3]);
+ copy_m3_m4(mat, ob->obmat);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, r_center);
+ }
+ }
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index 995faae8333..ff69c2859fc 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -128,16 +128,16 @@ static void gizmo2d_get_axis_color(const int axis_idx, float *r_col, float *r_co
r_col_hi[3] *= alpha_hi;
}
-static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *mgroup)
+static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
{
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_2d", true);
- const wmGizmoType *wt_cage = WM_gizmotype_find("GIZMO_WT_cage_2d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true);
GizmoGroup2D *man = MEM_callocN(sizeof(GizmoGroup2D), __func__);
- man->translate_x = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- man->translate_y = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL);
- man->cage = WM_gizmo_new_ptr(wt_cage, mgroup, NULL);
+ man->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ man->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ man->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
RNA_enum_set(man->cage->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
@@ -197,11 +197,11 @@ static int gizmo2d_modal(
return OPERATOR_RUNNING_MODAL;
}
-void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
- GizmoGroup2D *man = gizmogroup2d_init(mgroup);
- mgroup->customdata = man;
+ GizmoGroup2D *man = gizmogroup2d_init(gzgroup);
+ gzgroup->customdata = man;
MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
{
@@ -271,9 +271,9 @@ void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *mgrou
}
}
-void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *mgroup)
+void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup2D *man = mgroup->customdata;
+ GizmoGroup2D *man = gzgroup->customdata;
float origin[3];
gizmo2d_calc_bounds(C, origin, man->min, man->max);
copy_v2_v2(man->origin, origin);
@@ -321,10 +321,10 @@ void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *mgroup)
}
}
-void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
ARegion *ar = CTX_wm_region(C);
- GizmoGroup2D *man = mgroup->customdata;
+ GizmoGroup2D *man = gzgroup->customdata;
float origin[3] = {UNPACK2(man->origin), 0.0f};
float origin_aa[3] = {UNPACK2(man->origin), 0.0f};
@@ -346,7 +346,7 @@ void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *mgroup
* - Called on every redraw, better to do a more simple poll and check for selection in _refresh
* - UV editing only, could be expanded for other things.
*/
-bool ED_widgetgroup_gizmo2d_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt))
+bool ED_widgetgroup_gizmo2d_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
return false;
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 7d608c433c3..5fe7bbbf45e 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -107,7 +107,7 @@
#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
/* threshold for testing view aligned gizmo axis */
-struct {
+static struct {
float min, max;
} g_tw_axis_range[2] = {
/* Regular range */
@@ -148,7 +148,9 @@ enum {
#define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X
#define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1)
- MAN_AXIS_LAST = MAN_AXIS_RANGE_SCALE_END,
+ MAN_AXIS_APRON_C,
+
+ MAN_AXIS_LAST = MAN_AXIS_APRON_C + 1,
};
/* axis types */
@@ -162,6 +164,7 @@ enum {
typedef struct GizmoGroup {
bool all_hidden;
int twtype;
+ int axis_type_default;
/* Users may change the twtype, detect changes to re-setup gizmo options. */
int twtype_init;
@@ -193,7 +196,7 @@ static wmGizmo *gizmo_get_axis_from_index(const GizmoGroup *man, const short axi
return man->gizmos[axis_idx];
}
-static short gizmo_get_axis_type(const int axis_idx)
+static short gizmo_get_axis_type(const int axis_idx, const int axis_type_default)
{
if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
return MAN_AXES_TRANSLATE;
@@ -204,6 +207,9 @@ static short gizmo_get_axis_type(const int axis_idx)
if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
return MAN_AXES_SCALE;
}
+ if (axis_idx == MAN_AXIS_APRON_C) {
+ return axis_type_default;
+ }
BLI_assert(0);
return -1;
}
@@ -326,6 +332,8 @@ static bool gizmo_is_axis_visible(
rv3d->twdrawflag & MAN_SCALE_X &&
(twtype & SCE_MANIP_TRANSLATE) == 0 &&
(twtype & SCE_MANIP_ROTATE) == 0);
+ case MAN_AXIS_APRON_C:
+ return true;
}
return false;
}
@@ -604,6 +612,7 @@ int ED_transform_calc_gizmo_stats(
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
View3D *v3d = sa->spacedata.first;
@@ -611,7 +620,7 @@ int ED_transform_calc_gizmo_stats(
Base *base;
Object *ob = OBACT(view_layer);
bGPdata *gpd = CTX_data_gpencil_data(C);
- const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
+ const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
int a, totsel = 0;
const int pivot_point = scene->toolsettings->transform_pivot_point;
@@ -728,10 +737,8 @@ int ED_transform_calc_gizmo_stats(
/* only editable and visible layers are considered */
if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
- /* calculate difference matrix if parent object */
- if (gpl->parent != NULL) {
- ED_gpencil_parent_location(gpl, diff_mat);
- }
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
/* skip strokes that are invalid for current view */
@@ -1137,13 +1144,13 @@ static void gizmo_line_range(const int twtype, const short axis_type, float *r_s
}
static void gizmo_xform_message_subscribe(
- wmGizmoGroup *mgroup, struct wmMsgBus *mbus,
+ wmGizmoGroup *gzgroup, struct wmMsgBus *mbus,
Scene *scene, bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar, const void *type_fn)
{
/* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
.owner = ar,
- .user_data = mgroup->parent_mmap,
+ .user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
@@ -1159,7 +1166,7 @@ static void gizmo_xform_message_subscribe(
};
for (int i = 0; i < ARRAY_SIZE(props); i++) {
if (props[i]) {
- WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
}
}
}
@@ -1167,25 +1174,27 @@ static void gizmo_xform_message_subscribe(
PointerRNA toolsettings_ptr;
RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
- if (type_fn == TRANSFORM_WGT_gizmo) {
+ if (type_fn == TRANSFORM_GGT_gizmo) {
extern PropertyRNA rna_ToolSettings_transform_pivot_point;
extern PropertyRNA rna_ToolSettings_use_gizmo_mode;
+ extern PropertyRNA rna_ToolSettings_use_gizmo_apron;
const PropertyRNA *props[] = {
&rna_ToolSettings_transform_pivot_point,
&rna_ToolSettings_use_gizmo_mode,
+ &rna_ToolSettings_use_gizmo_apron,
};
for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
}
}
- else if (type_fn == VIEW3D_WGT_xform_cage) {
+ else if (type_fn == VIEW3D_GGT_xform_cage) {
/* pass */
}
else {
BLI_assert(0);
}
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
}
/** \} */
@@ -1195,26 +1204,32 @@ static void gizmo_xform_message_subscribe(
/** \name Transform Gizmo
* \{ */
-static GizmoGroup *gizmogroup_init(wmGizmoGroup *mgroup)
+static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
{
GizmoGroup *man;
man = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
- const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true);
- const wmGizmoType *wt_dial = WM_gizmotype_find("GIZMO_WT_dial_3d", true);
- const wmGizmoType *wt_prim = WM_gizmotype_find("GIZMO_WT_primitive_3d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+ const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
+
+ /* Fallback action. */
+ {
+ const wmGizmoType *gzt_mask = WM_gizmotype_find("GIZMO_GT_blank_3d", true);
+ man->gizmos[MAN_AXIS_APRON_C] = WM_gizmo_new_ptr(gzt_mask, gzgroup, NULL);
+ }
#define GIZMO_NEW_ARROW(v, draw_style) { \
- man->gizmos[v] = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL); \
+ man->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
RNA_enum_set(man->gizmos[v]->ptr, "draw_style", draw_style); \
} ((void)0)
#define GIZMO_NEW_DIAL(v, draw_options) { \
- man->gizmos[v] = WM_gizmo_new_ptr(wt_dial, mgroup, NULL); \
+ man->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
RNA_enum_set(man->gizmos[v]->ptr, "draw_options", draw_options); \
} ((void)0)
#define GIZMO_NEW_PRIM(v, draw_style) { \
- man->gizmos[v] = WM_gizmo_new_ptr(wt_prim, mgroup, NULL); \
+ man->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
RNA_enum_set(man->gizmos[v]->ptr, "draw_style", draw_style); \
} ((void)0)
@@ -1286,15 +1301,29 @@ static int gizmo_modal(
return OPERATOR_RUNNING_MODAL;
}
-static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup)
+static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
{
struct {
wmOperatorType *translate, *rotate, *trackball, *resize;
} ot_store = {NULL};
- GizmoGroup *man = mgroup->customdata;
+ GizmoGroup *man = gzgroup->customdata;
+
+ if (man->twtype & SCE_MANIP_TRANSLATE) {
+ man->axis_type_default = MAN_AXES_TRANSLATE;
+ }
+ else if (man->twtype & SCE_MANIP_ROTATE) {
+ man->axis_type_default = MAN_AXES_ROTATE;
+ }
+ else if (man->twtype & SCE_MANIP_SCALE) {
+ man->axis_type_default = MAN_AXES_SCALE;
+ }
+ else {
+ man->axis_type_default = 0;
+ }
+
MAN_ITER_AXES_BEGIN(axis, axis_idx)
{
- const short axis_type = gizmo_get_axis_type(axis_idx);
+ const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default);
bool constraint_axis[3] = {1, 0, 0};
PointerRNA *ptr;
@@ -1357,6 +1386,9 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup)
WM_gizmo_set_scale(axis, 0.2f);
}
break;
+ case MAN_AXIS_APRON_C:
+ WM_gizmo_set_scale(axis, 1.2f);
+ break;
}
switch (axis_type) {
@@ -1406,11 +1438,11 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup)
MAN_ITER_AXES_END;
}
-static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *man = gizmogroup_init(mgroup);
+ GizmoGroup *man = gizmogroup_init(gzgroup);
- mgroup->customdata = man;
+ gzgroup->customdata = man;
{
man->twtype = 0;
@@ -1436,12 +1468,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *mgroup)
}
/* *** set properties for axes *** */
- gizmogroup_init_properties_from_twtype(mgroup);
+ gizmogroup_init_properties_from_twtype(gzgroup);
}
-static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *man = mgroup->customdata;
+ GizmoGroup *man = gzgroup->customdata;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = sa->spacedata.first;
@@ -1453,7 +1485,7 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup)
man->twtype = scene->toolsettings->gizmo_flag & man->twtype_init;
if (man->twtype != man->twtype_prev) {
man->twtype_prev = man->twtype;
- gizmogroup_init_properties_from_twtype(mgroup);
+ gizmogroup_init_properties_from_twtype(gzgroup);
}
}
@@ -1473,7 +1505,7 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup)
MAN_ITER_AXES_BEGIN(axis, axis_idx)
{
- const short axis_type = gizmo_get_axis_type(axis_idx);
+ const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default);
const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]);
@@ -1527,18 +1559,19 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup)
}
static void WIDGETGROUP_gizmo_message_subscribe(
- const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus)
+ const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(mgroup, mbus, scene, screen, sa, ar, TRANSFORM_WGT_gizmo);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, TRANSFORM_GGT_gizmo);
}
-static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *man = mgroup->customdata;
+ const Scene *scene = CTX_data_scene(C);
+ GizmoGroup *man = gzgroup->customdata;
// ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
// View3D *v3d = sa->spacedata.first;
@@ -1561,9 +1594,13 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro
MAN_ITER_AXES_BEGIN(axis, axis_idx)
{
- const short axis_type = gizmo_get_axis_type(axis_idx);
+ const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default);
/* XXX maybe unset _HIDDEN flag on redraw? */
- if (gizmo_is_axis_visible(rv3d, man->twtype, idot, axis_type, axis_idx)) {
+
+ if (axis_idx == MAN_AXIS_APRON_C) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, (scene->toolsettings->gizmo_flag & SCE_MANIP_DISABLE_APRON) != 0);
+ }
+ else if (gizmo_is_axis_visible(rv3d, man->twtype, idot, axis_type, axis_idx)) {
WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
}
else {
@@ -1581,6 +1618,7 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro
case MAN_AXIS_ROT_C:
case MAN_AXIS_SCALE_C:
case MAN_AXIS_ROT_T:
+ case MAN_AXIS_APRON_C:
WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
break;
}
@@ -1588,39 +1626,39 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro
MAN_ITER_AXES_END;
}
-static bool WIDGETGROUP_gizmo_poll(const struct bContext *C, struct wmGizmoGroupType *wgt)
+static bool WIDGETGROUP_gizmo_poll(const struct bContext *C, struct wmGizmoGroupType *gzgt)
{
/* it's a given we only use this in 3D view */
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
if ((tref_rt == NULL) ||
- !STREQ(wgt->idname, tref_rt->gizmo_group))
+ !STREQ(gzgt->idname, tref_rt->gizmo_group))
{
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
View3D *v3d = CTX_wm_view3d(C);
- if (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
return false;
}
return true;
}
-void TRANSFORM_WGT_gizmo(wmGizmoGroupType *wgt)
+void TRANSFORM_GGT_gizmo(wmGizmoGroupType *gzgt)
{
- wgt->name = "Transform Gizmo";
- wgt->idname = "TRANSFORM_WGT_gizmo";
+ gzgt->name = "Transform Gizmo";
+ gzgt->idname = "TRANSFORM_GGT_gizmo";
- wgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = WIDGETGROUP_gizmo_poll;
- wgt->setup = WIDGETGROUP_gizmo_setup;
- wgt->refresh = WIDGETGROUP_gizmo_refresh;
- wgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
- wgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
+ gzgt->poll = WIDGETGROUP_gizmo_poll;
+ gzgt->setup = WIDGETGROUP_gizmo_setup;
+ gzgt->refresh = WIDGETGROUP_gizmo_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
}
/** \} */
@@ -1634,31 +1672,31 @@ struct XFormCageWidgetGroup {
wmGizmo *gizmo;
};
-static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *wgt)
+static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
- if (!STREQ(wgt->idname, tref_rt->gizmo_group)) {
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ if (!STREQ(gzgt->idname, tref_rt->gizmo_group)) {
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
return false;
}
return true;
}
-static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup)
+static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xmgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__);
- const wmGizmoType *wt_cage = WM_gizmotype_find("GIZMO_WT_cage_3d", true);
- xmgroup->gizmo = WM_gizmo_new_ptr(wt_cage, mgroup, NULL);
- wmGizmo *mpr = xmgroup->gizmo;
+ struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
+ xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ wmGizmo *gz = xgzgroup->gizmo;
- RNA_enum_set(mpr->ptr, "transform",
+ RNA_enum_set(gz->ptr, "transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
- mpr->color[0] = 1;
- mpr->color_hi[0] = 1;
+ gz->color[0] = 1;
+ gz->color_hi[0] = 1;
- mgroup->customdata = xmgroup;
+ gzgroup->customdata = xgzgroup;
{
wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
@@ -1673,7 +1711,7 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup
for (int y = 0; y < 3; y++) {
for (int z = 0; z < 3; z++) {
bool constraint[3] = {x != 1, y != 1, z != 1};
- ptr = WM_gizmo_operator_set(mpr, i, ot_resize, NULL);
+ ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
if (prop_release_confirm == NULL) {
prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
@@ -1687,15 +1725,15 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup
}
}
-static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
- struct XFormCageWidgetGroup *xmgroup = mgroup->customdata;
- wmGizmo *mpr = xmgroup->gizmo;
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
struct TransformBounds tbounds;
@@ -1705,22 +1743,22 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro
}, &tbounds) == 0) ||
equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max))
{
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
else {
gizmo_prepare_mat(C, v3d, rv3d, &tbounds);
- WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(mpr, WM_GIZMO_GRAB_CURSOR, true);
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(gz, WM_GIZMO_GRAB_CURSOR, true);
float dims[3];
sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
- RNA_float_set_array(mpr->ptr, "dimensions", dims);
+ RNA_float_set_array(gz->ptr, "dimensions", dims);
mul_v3_fl(dims, 0.5f);
- copy_m4_m3(mpr->matrix_offset, rv3d->tw_axis_matrix);
- mid_v3_v3v3(mpr->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
- mul_m3_v3(rv3d->tw_axis_matrix, mpr->matrix_offset[3]);
+ copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
+ mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
+ mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
PropertyRNA *prop_center_override = NULL;
float center[3];
@@ -1732,11 +1770,11 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro
center[1] = (float)(1 - y) * dims[1];
for (int z = 0; z < 3; z++) {
center[2] = (float)(1 - z) * dims[2];
- struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, i);
+ struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, i);
if (prop_center_override == NULL) {
prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override");
}
- mul_v3_m4v3(center_global, mpr->matrix_offset, center);
+ mul_v3_m4v3(center_global, gz->matrix_offset, center);
RNA_property_float_set_array(&mpop->ptr, prop_center_override, center_global);
i++;
}
@@ -1746,45 +1784,45 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro
}
static void WIDGETGROUP_xform_cage_message_subscribe(
- const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus)
+ const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(mgroup, mbus, scene, screen, sa, ar, VIEW3D_WGT_xform_cage);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_cage);
}
-static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *mgroup)
+static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xmgroup = mgroup->customdata;
- wmGizmo *mpr = xmgroup->gizmo;
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
if (ob && ob->mode & OB_MODE_EDIT) {
- copy_m4_m4(mpr->matrix_space, ob->obmat);
+ copy_m4_m4(gz->matrix_space, ob->obmat);
}
else {
- unit_m4(mpr->matrix_space);
+ unit_m4(gz->matrix_space);
}
}
-void VIEW3D_WGT_xform_cage(wmGizmoGroupType *wgt)
+void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
{
- wgt->name = "Transform Cage";
- wgt->idname = "VIEW3D_WGT_xform_cage";
+ gzgt->name = "Transform Cage";
+ gzgt->idname = "VIEW3D_GGT_xform_cage";
- wgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- wgt->mmap_params.spaceid = SPACE_VIEW3D;
- wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- wgt->poll = WIDGETGROUP_xform_cage_poll;
- wgt->setup = WIDGETGROUP_xform_cage_setup;
- wgt->refresh = WIDGETGROUP_xform_cage_refresh;
- wgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
- wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
+ gzgt->poll = WIDGETGROUP_xform_cage_poll;
+ gzgt->setup = WIDGETGROUP_xform_cage_setup;
+ gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index c9a97c8530c..1f1cc646f20 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -82,6 +82,7 @@ static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
+static const char OP_NORMAL_ROTATION[] = "TRANSFORM_OT_rotate_normal";
static void TRANSFORM_OT_translate(struct wmOperatorType *ot);
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot);
@@ -100,6 +101,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot);
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot);
+static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot);
static TransformModeItem transform_modes[] =
{
@@ -120,6 +122,7 @@ static TransformModeItem transform_modes[] =
{OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
{OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
{OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
+ {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal},
{NULL, 0}
};
@@ -507,6 +510,36 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
+static bool transform_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Orientation/Constraints. */
+ {
+ /* Hide orientation axis if no constraints are set, since it wont be used. */
+ PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "constraint_axis");
+ if (prop_con && !RNA_property_is_set(op->ptr, prop_con)) {
+ if (STRPREFIX(prop_id, "constraint")) {
+ return false;
+ }
+ }
+ }
+
+ /* Proportional Editing. */
+ {
+ PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional");
+ if (prop_pet && (prop_pet != prop) &&
+ (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF))
+ {
+ if (STRPREFIX(prop_id, "proportional")) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
void Transform_Properties(struct wmOperatorType *ot, int flags)
{
PropertyRNA *prop;
@@ -615,6 +648,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
@@ -640,6 +674,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
@@ -673,6 +708,7 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = skin_resize_poll;
+ ot->poll_property = transform_poll_property;
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
@@ -695,6 +731,7 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
/* Maybe we could use float_vector_xyz here too? */
RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
@@ -718,6 +755,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
@@ -744,6 +782,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editcurve_3d;
+ ot->poll_property = transform_poll_property;
RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
@@ -766,6 +805,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_region_view3d_active;
+ ot->poll_property = transform_poll_property;
RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
@@ -788,6 +828,7 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
@@ -811,6 +852,7 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
@@ -833,6 +875,7 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editmesh;
+ ot->poll_property = transform_poll_property;
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
@@ -858,6 +901,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
@@ -880,6 +924,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
}
@@ -900,6 +945,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
@@ -932,6 +978,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_even", false, "Even",
@@ -961,6 +1008,7 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_editmesh;
+ ot->poll_property = transform_poll_property;
RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
@@ -1034,6 +1082,27 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
Transform_Properties(ot, P_SNAP);
}
+static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Normal Rotate";
+ ot->description = "Rotate split normal of selected items";
+ ot->idname = OP_NORMAL_ROTATION;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_MIRROR);
+}
+
+
static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1050,6 +1119,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
RNA_def_property_flag(prop, PROP_HIDDEN);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index dc922b5c9ba..54253e36351 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -165,7 +165,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
invert_m4_m4(imat, rv3d->viewmat);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -190,7 +190,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
if (usingSnappingNormal(t) && validSnappingNormal(t)) {
immUniformColor4ubv(activeCol);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
@@ -219,7 +219,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
GPU_blend(true);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1462,7 +1462,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2])
float xmouse, ymouse;
int frame;
int mframe;
- TransSeq *ts = t->custom.type.data;
+ TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
if (!(t->modifiers & MOD_SNAP_INVERT))
return;
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index e19320fa220..6dfcfe11af2 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -111,6 +111,10 @@ typedef struct SnapObjectData_EditMesh {
SnapObjectData sd;
BVHTreeFromEditMesh *bvh_trees[3];
+ /* It's like a boundbox. It is tested first to avoid
+ * to create a bvhtree for all the edited objects. */
+ float min[3], max[3];
+
} SnapObjectData_EditMesh;
struct SnapObjectContext {
@@ -156,6 +160,39 @@ struct SnapObjectContext {
typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+static void min_max_from_bmesh(
+ BMesh *bm, float r_min[3], float r_max[3])
+{
+ BMIter iter;
+ BMVert *eve;
+
+ INIT_MINMAX(r_min, r_max);
+ BM_ITER_MESH(eve, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(r_min, r_max, eve->co);
+ }
+}
+
+static SnapObjectData_Mesh *snap_object_data_mesh_create(SnapObjectContext *sctx)
+{
+ SnapObjectData_Mesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ /* start assuming that it has each of these element types */
+ sod->has_looptris = true;
+ sod->has_loose_edge = true;
+ sod->has_loose_vert = true;
+
+ return sod;
+}
+
+static SnapObjectData_EditMesh *snap_object_data_editmesh_create(SnapObjectContext *sctx, BMesh *bm)
+{
+ SnapObjectData_EditMesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ min_max_from_bmesh(bm, sod->min, sod->max);
+
+ return sod;
+}
+
/**
* Walks through all objects in the scene to create the list of objets to snap.
*
@@ -169,9 +206,9 @@ static void iter_snap_objects(
IterSnapObjsCallback sob_callback,
void *data)
{
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph);
- Object *obedit = params->use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
+ ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
const eSnapSelect snap_select = params->snap_select;
+ const bool use_object_edit_cage = params->use_object_edit_cage;
Base *base_act = view_layer->basact;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
@@ -179,20 +216,17 @@ static void iter_snap_objects(
!((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
(snap_select == SNAP_NOT_ACTIVE && base == base_act)))
{
- bool use_obedit;
- Object *obj = base->object;
- if (obj->transflag & OB_DUPLI) {
+ Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
+ if (obj_eval->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj);
+ ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- use_obedit = obedit && dupli_ob->ob->data == obedit->data;
- sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data);
+ sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
}
free_object_duplilist(lb);
}
- use_obedit = obedit && obj->data == obedit->data;
- sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data);
+ sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
}
}
}
@@ -372,13 +406,12 @@ static bool raycastMesh(
sod = *sod_p;
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
+ sod = *sod_p = snap_object_data_mesh_create(sctx);
}
BVHTreeFromMesh *treedata = &sod->treedata;
- /* The tree is owned by the DM and may have been freed since we last used. */
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
if (treedata->tree) {
BLI_assert(treedata->cached);
if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
@@ -502,14 +535,30 @@ static bool raycastEditMesh(
SnapObjectData_EditMesh *sod = NULL;
BVHTreeFromEditMesh *treedata = NULL;
+ Object *em_ob = em->ob;
+
+ BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob));
void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ /* Use `em->ob` as the key in ghash since the editmesh is used
+ * to create bvhtree and is the same for each linked object. */
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) {
sod = *sod_p;
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
+ sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm);
+ }
+
+ {
+ float min[3], max[3];
+ mul_v3_m4v3(min, obmat, sod->min);
+ mul_v3_m4v3(max, obmat, sod->max);
+
+ if (!isect_ray_aabb_v3_simple(
+ ray_start, ray_dir, min, max, NULL, NULL))
+ {
+ return retval;
+ }
}
if (sod->bvh_trees[2] == NULL) {
@@ -517,7 +566,17 @@ static bool raycastEditMesh(
}
treedata = sod->bvh_trees[2];
+ BVHCache *em_bvh_cache = ((Mesh *)em_ob->data)->runtime.bvh_cache;
+
+ if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
+ free_bvhtree_from_editmesh(treedata);
+ }
+ }
+
if (treedata->tree == NULL) {
+ BVHCache **bvh_cache = NULL;
BLI_bitmap *elem_mask = NULL;
int looptri_num_active = -1;
@@ -527,7 +586,15 @@ static bool raycastEditMesh(
em->bm, elem_mask,
sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
}
- bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
+ else {
+ /* Only cache if bvhtree is created without a mask.
+ * This helps keep a standardized bvhtree in cache. */
+ bvh_cache = &em_bvh_cache;
+ }
+
+ bvhtree_from_editmesh_looptri_ex(
+ treedata, em, elem_mask, looptri_num_active,
+ 0.0f, 4, 6, bvh_cache);
if (elem_mask) {
MEM_freeN(elem_mask);
@@ -669,7 +736,7 @@ static bool raycastObj(
switch (ob->type) {
case OB_MESH:
- if (use_obedit) {
+ if (use_obedit && BKE_object_is_in_editmode(ob)) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
retval = raycastEditMesh(
sctx,
@@ -718,7 +785,7 @@ struct RaycastObjUserData {
bool ret;
};
-static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
{
struct RaycastObjUserData *dt = data;
@@ -726,7 +793,7 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob,
sctx,
dt->ray_start, dt->ray_dir,
ob, obmat, dt->ob_index++,
- is_obedit, dt->use_occlusion_test,
+ use_obedit, dt->use_occlusion_test,
dt->ray_depth,
dt->r_loc, dt->r_no, dt->r_index,
dt->r_ob, dt->r_obmat,
@@ -1118,6 +1185,13 @@ static short snap_mesh_polygon(
};
SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ if (sod == NULL) {
+ /* The object is in edit mode, and the key used
+ * was the object referenced in BMEditMesh */
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
+ }
+
BLI_assert(sod != NULL);
if (sod->type == SNAP_MESH) {
@@ -1335,6 +1409,8 @@ static short snapArmature(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
if (use_obedit == false) {
/* Test BoundBox */
BoundBox *bb = BKE_armature_boundbox_get(ob);
@@ -1469,6 +1545,8 @@ static short snapCurve(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
if (use_obedit == false) {
/* Test BoundBox */
BoundBox *bb = BKE_curve_boundbox_get(ob);
@@ -1779,12 +1857,7 @@ static short snapMesh(
sod = *sod_p;
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
- /* start assuming that it has each of these element types */
- sod->has_looptris = true;
- sod->has_loose_edge = true;
- sod->has_loose_vert = true;
+ sod = *sod_p = snap_object_data_mesh_create(sctx);
}
BVHTreeFromMesh *treedata, dummy_treedata;
@@ -1792,7 +1865,7 @@ static short snapMesh(
treedata = &sod->treedata;
bvhtree = sod->bvhtree;
- /* the tree is owned by the DM and may have been freed since we last used! */
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
if ((sod->has_looptris && treedata->tree && !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
(sod->has_loose_edge && bvhtree[0] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
(sod->has_loose_vert && bvhtree[1] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])))
@@ -1982,21 +2055,57 @@ static short snapEditMesh(
SnapObjectData_EditMesh *sod = NULL;
BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
+ Object *em_ob = em->ob;
+
+ BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob));
+ UNUSED_VARS_NDEBUG(ob);
void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ /* Use `em->ob` as the key in ghash since the editmesh is used
+ * to create bvhtree and is the same for each linked object. */
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) {
sod = *sod_p;
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
+ sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm);
}
+ float dist_px_sq = SQUARE(*dist_px);
+
+ {
+ float min[3], max[3];
+ mul_v3_m4v3(min, obmat, sod->min);
+ mul_v3_m4v3(max, obmat, sod->max);
+
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &data_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &data_precalc, min, max, dummy);
+
+ if (bb_dist_px_sq > dist_px_sq) {
+ return 0;
+ }
+ }
+
+ BVHCache *em_bvh_cache = ((Mesh *)em_ob->data)->runtime.bvh_cache;
+
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->bvh_trees[0] == NULL) {
sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
treedata_vert = sod->bvh_trees[0];
+
+ if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
+ free_bvhtree_from_editmesh(treedata_vert);
+ }
+ }
+
if (treedata_vert->tree == NULL) {
BLI_bitmap *verts_mask = NULL;
int verts_num_active = -1;
@@ -2006,9 +2115,13 @@ static short snapEditMesh(
BM_VERTS_OF_MESH, em->bm, verts_mask,
(bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ MEM_freeN(verts_mask);
+ }
+ else {
+ bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
}
- bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- MEM_SAFE_FREE(verts_mask);
}
}
@@ -2017,6 +2130,14 @@ static short snapEditMesh(
sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
treedata_edge = sod->bvh_trees[1];
+
+ if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
+ free_bvhtree_from_editmesh(treedata_edge);
+ }
+ }
+
if (treedata_edge->tree == NULL) {
BLI_bitmap *edges_mask = NULL;
int edges_num_active = -1;
@@ -2027,9 +2148,12 @@ static short snapEditMesh(
(bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
sctx->callbacks.edit_mesh.user_data);
+ bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
+ MEM_freeN(edges_mask);
+ }
+ else {
+ bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
}
- bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- MEM_SAFE_FREE(edges_mask);
}
}
@@ -2043,7 +2167,7 @@ static short snapEditMesh(
BVHTreeNearest nearest = {
.index = -1,
- .dist_sq = SQUARE(*dist_px),
+ .dist_sq = dist_px_sq,
};
int last_index = nearest.index;
short elem = SCE_SNAP_MODE_VERTEX;
@@ -2119,7 +2243,7 @@ static short snapObject(
switch (ob->type) {
case OB_MESH:
- if (use_obedit) {
+ if (use_obedit && BKE_object_is_in_editmode(ob)) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, snapdata, ob, em, obmat,
@@ -2156,7 +2280,12 @@ static short snapObject(
dist_px,
r_loc, r_no, r_index);
break;
-
+ case OB_GPENCIL:
+ retval = snapEmpty(
+ snapdata, ob, obmat,
+ dist_px,
+ r_loc, r_no, r_index);
+ break;
case OB_CAMERA:
retval = snapCamera(
sctx, snapdata, ob, obmat,
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 14592149579..ffe4008f7d6 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -48,12 +48,16 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_layer.h"
#include "BKE_undo_system.h"
+#include "BKE_workspace.h"
+#include "BKE_paint.h"
#include "ED_gpencil.h"
#include "ED_render.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_undo.h"
@@ -110,6 +114,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
/* undo during jobs are running can easily lead to freeing data using by jobs,
* or they can just lead to freezing job in some other cases */
@@ -122,6 +127,12 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
if (ED_gpencil_session_active()) {
return ED_undo_gpencil_step(C, step, undoname);
}
+ if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ Object *obact = CTX_data_active_object(C);
+ if (obact && (obact->type == OB_GPENCIL)) {
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ }
UndoStep *step_data_from_name = NULL;
int step_for_callback = step;
@@ -156,6 +167,23 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
else {
BKE_undosys_step_undo_compat_only(wm->undo_stack, C, step);
}
+
+ /* Set special modes for grease pencil */
+ if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ Object *obact = CTX_data_active_object(C);
+ if (obact && (obact->type == OB_GPENCIL)) {
+ /* set cursor */
+ if (ELEM(obact->mode, OB_MODE_GPENCIL_PAINT, OB_MODE_GPENCIL_SCULPT, OB_MODE_GPENCIL_WEIGHT)) {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ else {
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
+ /* set workspace mode */
+ Base *basact = CTX_data_active_base(C);
+ ED_object_base_activate(C, basact);
+ }
+ }
}
/* App-Handlers (post). */
@@ -387,6 +415,15 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
}
}
+ if (op->type->flag & OPTYPE_USE_EVAL_DATA) {
+ /* We need to force refresh of depsgraph after undo step,
+ * redoing the operator *may* rely on some valid evaluated data. */
+ Main *bmain = CTX_data_main(C);
+ scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
+ }
+
retval = WM_operator_repeat(C, op);
if ((retval & OPERATOR_FINISHED) == 0) {
if (G.debug & G_DEBUG)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 65147d53b5d..35a77fcd4c0 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -342,7 +342,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
const float mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
win->eventstate->y - ar->winrct.ymin};
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -355,7 +355,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(shdr_pos, mval_src);
immVertex2fv(shdr_pos, mval_dst);
immEnd();
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index f0d6b5c2a71..616f4eac2ad 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -90,9 +90,9 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
GPU_line_width(1.0f);
- gpuTranslate2fv(cursor);
+ GPU_matrix_translate_2fv(cursor);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -104,7 +104,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
immUniform1f("dash_width", 8.0f);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
@@ -123,7 +123,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
immUniform1f("dash_width", 2.0f);
- immBegin(GWN_PRIM_LINES, 8);
+ immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
@@ -141,7 +141,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
immUnbindProgram();
- gpuTranslate2f(-cursor[0], -cursor[1]);
+ GPU_matrix_translate_2f(-cursor[0], -cursor[1]);
}
static int draw_uvs_face_check(Scene *scene)
@@ -168,7 +168,7 @@ static void draw_uvs_shadow(Object *obedit)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -229,7 +229,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
}
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -241,7 +241,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- immBegin(GWN_PRIM_TRI_FAN, efa->len);
+ immBegin(GPU_PRIM_TRI_FAN, efa->len);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -281,7 +281,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
immUniformColor3fv(col);
/* TODO: use editmesh tessface */
- immBegin(GWN_PRIM_TRI_FAN, efa->len);
+ immBegin(GPU_PRIM_TRI_FAN, efa->len);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -308,9 +308,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
col[3] = 0.5f; /* hard coded alpha, not that nice */
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
@@ -353,7 +353,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, Object *obedit, BME
}
/* TODO: use editmesh tessface */
- immBegin(GWN_PRIM_TRI_FAN, efa->len);
+ immBegin(GPU_PRIM_TRI_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);
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
@@ -393,7 +393,7 @@ static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, co
MLoopUV *luv;
/* For more efficiency first transfer the entire buffer to vram. */
- Gwn_Batch *loop_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
+ GPUBatch *loop_batch = immBeginBatchAtMost(GPU_PRIM_LINE_LOOP, bm->totloop);
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
@@ -407,17 +407,17 @@ static void draw_uvs_lineloop_bmfaces(BMesh *bm, const int cd_loop_uv_offset, co
immEnd();
/* Then draw each face contour separately. */
- GWN_batch_program_use_begin(loop_batch);
+ GPU_batch_program_use_begin(loop_batch);
unsigned int index = 0;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+ GPU_batch_draw_range_ex(loop_batch, index, efa->len, false);
index += efa->len;
}
- GWN_batch_program_use_end(loop_batch);
- GWN_batch_discard(loop_batch);
+ GPU_batch_program_use_end(loop_batch);
+ GPU_batch_discard(loop_batch);
}
static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos)
@@ -425,7 +425,7 @@ static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos)
MLoopUV *mloopuv;
int i;
- immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop);
+ immBegin(GPU_PRIM_LINE_LOOP, mpoly->totloop);
mloopuv = &me->mloopuv[mpoly->loopstart];
for (i = mpoly->totloop; i != 0; i--, mloopuv++) {
@@ -495,7 +495,7 @@ static void draw_uvs_other_mesh(Object *ob, const Image *curimage,
static void draw_uvs_other(ViewLayer *view_layer, Object *obedit, const Image *curimage,
const int other_uv_filter)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -536,7 +536,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, ViewLayer *view_la
mloopuv = me->mloopuv;
}
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -548,7 +548,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, ViewLayer *view_la
if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1)
continue;
- immBegin(GWN_PRIM_LINE_LOOP, mpoly->totloop);
+ immBegin(GPU_PRIM_LINE_LOOP, mpoly->totloop);
mloopuv = mloopuv_base + mpoly->loopstart;
for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
@@ -658,13 +658,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- Gwn_Batch *face_batch = immBeginBatch(GWN_PRIM_TRIS, tri_count * 3);
+ GPUBatch *face_batch = immBeginBatch(GPU_PRIM_TRIS, tri_count * 3);
for (unsigned int i = 0; i < em->tottri; i++) {
efa = em->looptris[i][0]->f;
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
@@ -686,9 +686,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immEnd();
/* XXX performance: we should not create and throw away result. */
- GWN_batch_draw(face_batch);
- GWN_batch_program_use_end(face_batch);
- GWN_batch_discard(face_batch);
+ GPU_batch_draw(face_batch);
+ GPU_batch_program_use_end(face_batch);
+ GPU_batch_discard(face_batch);
immUnbindProgram();
@@ -712,7 +712,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
switch (sima->dt_uv) {
case SI_UVDT_DASH:
@@ -751,8 +751,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
/* For more efficiency first transfer the entire buffer to vram. */
- Gwn_Batch *loop_batch = immBeginBatchAtMost(GWN_PRIM_LINE_LOOP, bm->totloop);
- Gwn_VertBuf *loop_vbo = loop_batch->verts[0];
+ GPUBatch *loop_batch = immBeginBatchAtMost(GPU_PRIM_LINE_LOOP, bm->totloop);
+ GPUVertBuf *loop_vbo = loop_batch->verts[0];
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -766,17 +766,17 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* Then draw each face contour separately. */
if (loop_vbo->vertex_len != 0) {
- GWN_batch_program_use_begin(loop_batch);
+ GPU_batch_program_use_begin(loop_batch);
unsigned int index = 0, loop_vbo_count;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+ GPU_batch_draw_range_ex(loop_batch, index, efa->len, false);
index += efa->len;
}
loop_vbo_count = index;
- GWN_batch_program_use_end(loop_batch);
+ GPU_batch_program_use_end(loop_batch);
immUnbindProgram();
@@ -790,14 +790,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
if (interpedges) {
/* Create a color buffer. */
- static Gwn_VertFormat format = { 0 };
+ static GPUVertFormat format = { 0 };
static uint shdr_col;
if (format.attr_len == 0) {
- shdr_col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ shdr_col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo_col = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo_col, loop_vbo_count);
+ GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo_col, loop_vbo_count);
index = 0;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
@@ -806,36 +806,36 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- GWN_vertbuf_attr_set(vbo_col, shdr_col, index++, sel ? col1 : col2);
+ GPU_vertbuf_attr_set(vbo_col, shdr_col, index++, sel ? col1 : col2);
}
}
/* Reuse the UV buffer and add the color buffer. */
- GWN_batch_vertbuf_add_ex(loop_batch, vbo_col, true);
+ GPU_batch_vertbuf_add_ex(loop_batch, vbo_col, true);
/* Now draw each face contour separately with another builtin program. */
- GWN_batch_program_set_builtin(loop_batch, GPU_SHADER_2D_SMOOTH_COLOR);
- gpuBindMatrices(loop_batch->interface);
+ GPU_batch_program_set_builtin(loop_batch, GPU_SHADER_2D_SMOOTH_COLOR);
+ GPU_matrix_bind(loop_batch->interface);
- GWN_batch_program_use_begin(loop_batch);
+ GPU_batch_program_use_begin(loop_batch);
index = 0;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+ GPU_batch_draw_range_ex(loop_batch, index, efa->len, false);
index += efa->len;
}
- GWN_batch_program_use_end(loop_batch);
+ GPU_batch_program_use_end(loop_batch);
}
else {
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
/* Use batch here to avoid problems with `IMM_BUFFER_SIZE`. */
- Gwn_Batch *flat_edges_batch = immBeginBatchAtMost(GWN_PRIM_LINES, loop_vbo_count * 2);
+ GPUBatch *flat_edges_batch = immBeginBatchAtMost(GPU_PRIM_LINES, loop_vbo_count * 2);
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -852,27 +852,27 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
immEnd();
- GWN_batch_draw(flat_edges_batch);
- GWN_batch_discard(flat_edges_batch);
+ GPU_batch_draw(flat_edges_batch);
+ GPU_batch_discard(flat_edges_batch);
immUnbindProgram();
}
}
else {
- GWN_batch_uniform_4fv(loop_batch, "color", col2);
+ GPU_batch_uniform_4fv(loop_batch, "color", col2);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* no nice edges */
- GWN_batch_program_use_begin(loop_batch);
+ GPU_batch_program_use_begin(loop_batch);
index = 0;
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- GWN_batch_draw_range_ex(loop_batch, index, efa->len, false);
+ GPU_batch_draw_range_ex(loop_batch, index, efa->len, false);
index += efa->len;
}
- GWN_batch_program_use_end(loop_batch);
+ GPU_batch_program_use_end(loop_batch);
immUnbindProgram();
}
}
@@ -881,7 +881,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immUnbindProgram();
}
- GWN_batch_discard(loop_batch);
+ GPU_batch_discard(loop_batch);
if (sima->flag & SI_SMOOTH_UV) {
GPU_line_smooth(false);
@@ -894,16 +894,16 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
float cent[2];
bool col_set = false;
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
GPU_point_size(pointsize);
- immBeginAtMost(GWN_PRIM_POINTS, bm->totface);
+ immBeginAtMost(GPU_PRIM_POINTS, bm->totface);
/* unselected faces */
@@ -955,7 +955,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
/* 6. draw uv vertices */
if (drawfaces != 2) { /* 2 means Mesh Face Mode */
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -964,7 +964,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
GPU_point_size(pointsize);
- immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
+ immBeginAtMost(GPU_PRIM_POINTS, bm->totloop);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
@@ -984,7 +984,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
GPU_point_size(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
imm_cpack(0xFF);
- immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
+ immBeginAtMost(GPU_PRIM_POINTS, bm->totloop);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
@@ -1004,7 +1004,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immUniformThemeColor(TH_VERTEX_SELECT);
GPU_point_size(pointsize);
- immBeginAtMost(GWN_PRIM_POINTS, bm->totloop);
+ immBeginAtMost(GPU_PRIM_POINTS, bm->totloop);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index faccb44767f..32bf32b03ab 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -80,6 +80,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -971,7 +972,7 @@ static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa
for (iterv = first; iterv; iterv = iterv->next) {
if (iterv->separate)
first = iterv;
- if (iterv->f == BM_elem_index_get(efa))
+ if (iterv->poly_index == BM_elem_index_get(efa))
return first;
}
@@ -993,9 +994,9 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, UvMapVert *first1,
if (iterv2->separate && iterv2 != first2)
break;
- if (iterv1->f == iterv2->f) {
+ if (iterv1->poly_index == iterv2->poly_index) {
/* if face already tagged, don't do this edge */
- efa = BM_face_at_index(em->bm, iterv1->f);
+ efa = BM_face_at_index(em->bm, iterv1->poly_index);
if (BM_elem_flag_test(efa, BM_ELEM_TAG))
return false;
@@ -1019,8 +1020,8 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, UvMapVert *first1,
if (iterv2->separate && iterv2 != first2)
break;
- if (iterv1->f == iterv2->f) {
- efa = BM_face_at_index(em->bm, iterv1->f);
+ if (iterv1->poly_index == iterv2->poly_index) {
+ efa = BM_face_at_index(em->bm, iterv1->poly_index);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
break;
}
@@ -1231,18 +1232,19 @@ static void uv_select_linked_multi(
for (iterv = vlist; iterv; iterv = iterv->next) {
if (iterv->separate)
startv = iterv;
- if (iterv->f == a)
+ if (iterv->poly_index == a)
break;
}
for (iterv = startv; iterv; iterv = iterv->next) {
if ((startv != iterv) && (iterv->separate))
break;
- else if (!flag[iterv->f]) {
- flag[iterv->f] = 1;
- stack[stacksize] = iterv->f;
+ else if (!flag[iterv->poly_index]) {
+ flag[iterv->poly_index] = 1;
+ stack[stacksize] = iterv->poly_index;
stacksize++;
}
+
}
}
}
@@ -2742,7 +2744,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(
if (vlist_iter->separate)
start_vlist = vlist_iter;
- if (efa_index == vlist_iter->f)
+ if (efa_index == vlist_iter->poly_index)
break;
vlist_iter = vlist_iter->next;
@@ -2754,12 +2756,12 @@ static void uv_select_flush_from_tag_sticky_loc_internal(
if (vlist_iter != start_vlist && vlist_iter->separate)
break;
- if (efa_index != vlist_iter->f) {
+ if (efa_index != vlist_iter->poly_index) {
BMLoop *l_other;
- efa_vlist = BM_face_at_index(em->bm, vlist_iter->f);
+ efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index);
/* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */
- l_other = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex);
+ l_other = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index);
uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset);
}
@@ -4178,14 +4180,14 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
v1coincident = 0;
separated2 = 0;
- efa1 = BM_face_at_index(bm, mv1->f);
+ efa1 = BM_face_at_index(bm, mv1->poly_index);
mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
if (mv2->separate)
mv2sep = mv2;
- efa2 = BM_face_at_index(bm, mv2->f);
+ efa2 = BM_face_at_index(bm, mv2->poly_index);
if (efa1 == efa2) {
/* if v1 is not coincident no point in comparing */
if (v1coincident) {
@@ -4403,6 +4405,15 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt");
#endif
+ /* Select Element (Sync Select: on) */
+ ED_keymap_editmesh_elem_mode(keyconf, keymap);
+ /* Hack to prevent fall-through, when the button isn't visible. */
+ WM_keymap_add_item(keymap, "MESH_OT_select_mode", FOURKEY, KM_PRESS, 0, 0);
+ /* Select Element (Sync Select: off) */
+ WM_keymap_add_context_enum_set_items(
+ keymap, rna_enum_mesh_select_mode_uv_items, "tool_settings.uv_select_mode",
+ ONEKEY, KM_PRESS, 0, 0);
+
/* Mark edge seam */
WM_keymap_add_item(keymap, "UV_OT_mark_seam", EKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index c3737787933..422c3489e01 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -54,6 +54,7 @@
#include "BKE_customdata.h"
#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "DEG_depsgraph.h"
@@ -150,20 +151,11 @@ typedef struct UvEdge {
/* stitch state object */
typedef struct StitchState {
float aspect;
- /* use limit flag */
- bool use_limit;
- /* limit to operator, same as original operator */
- float limit_dist;
- /* snap uv islands together during stitching */
- bool snap_islands;
- /* stitch at midpoints or at islands */
- bool midpoints;
/* object for editmesh */
Object *obedit;
/* editmesh, cached for use in modal handler */
BMEditMesh *em;
- /* clear seams of stitched edges after stitch */
- bool clear_seams;
+
/* element map for getting info about uv connectivity */
UvElementMap *element_map;
/* edge container */
@@ -178,6 +170,8 @@ typedef struct StitchState {
UvEdge *edges;
/* hash for quick lookup of edges */
GHash *edge_hash;
+ /* which islands to stop at (to make active) when pressing 'I' */
+ bool *island_is_stitchable;
/* count of separate uvs and edges */
int total_separate_edges;
@@ -185,18 +179,39 @@ typedef struct StitchState {
/* hold selection related information */
void **selection_stack;
int selection_size;
- /* island that stays in place */
- int static_island;
+
/* store number of primitives per face so that we can allocate the active island buffer later */
unsigned int *tris_per_island;
+ /* preview data */
+ StitchPreviewer *stitch_preview;
+} StitchState;
+/* Stitch state container. */
+typedef struct StitchStateContainer {
+ /* clear seams of stitched edges after stitch */
+ bool clear_seams;
+ /* use limit flag */
+ bool use_limit;
+ /* limit to operator, same as original operator */
+ float limit_dist;
+ /* snap uv islands together during stitching */
+ bool snap_islands;
+ /* stitch at midpoints or at islands */
+ bool midpoints;
/* vert or edge mode used for stitching */
char mode;
/* handle for drawing */
void *draw_handle;
- /* preview data */
- StitchPreviewer *stitch_preview;
-} StitchState;
+ /* island that stays in place */
+ int static_island;
+
+ /* Objects and states are aligned. */
+ int objects_len;
+ Object **objects;
+ StitchState **states;
+
+ int active_object_index;
+} StitchStateContainer;
typedef struct PreviewPosition {
int data_position;
@@ -270,7 +285,7 @@ static void stitch_preview_delete(StitchPreviewer *stitch_preview)
}
/* This function updates the header of the UV editor when the stitch tool updates its settings */
-static void stitch_update_header(StitchState *state, bContext *C)
+static void stitch_update_header(StitchStateContainer *ssc, bContext *C)
{
const char *str = IFACE_(
"Mode(TAB) %s, "
@@ -285,12 +300,13 @@ static void stitch_update_header(StitchState *state, bContext *C)
ScrArea *sa = CTX_wm_area(C);
if (sa) {
- BLI_snprintf(msg, sizeof(msg), str,
- state->mode == STITCH_VERT ? IFACE_("Vertex") : IFACE_("Edge"),
- WM_bool_as_string(state->snap_islands),
- WM_bool_as_string(state->midpoints),
- state->limit_dist,
- WM_bool_as_string(state->use_limit));
+ BLI_snprintf(
+ msg, sizeof(msg), str,
+ ssc->mode == STITCH_VERT ? IFACE_("Vertex") : IFACE_("Edge"),
+ WM_bool_as_string(ssc->snap_islands),
+ WM_bool_as_string(ssc->midpoints),
+ ssc->limit_dist,
+ WM_bool_as_string(ssc->use_limit));
ED_workspace_status_text(C, msg);
}
@@ -320,7 +336,9 @@ static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2],
}
/* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
-static bool stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
+static bool stitch_check_uvs_stitchable(
+ UvElement *element, UvElement *element_iter,
+ StitchStateContainer *ssc, StitchState *state)
{
BMesh *bm = state->em->bm;
float limit;
@@ -329,9 +347,9 @@ static bool stitch_check_uvs_stitchable(UvElement *element, UvElement *element_i
return 0;
}
- limit = state->limit_dist;
+ limit = ssc->limit_dist;
- if (state->use_limit) {
+ if (ssc->use_limit) {
MLoopUV *luv, *luv_iter;
BMLoop *l;
@@ -355,7 +373,9 @@ static bool stitch_check_uvs_stitchable(UvElement *element, UvElement *element_i
}
}
-static bool stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
+static bool stitch_check_edges_stitchable(
+ UvEdge *edge, UvEdge *edge_iter,
+ StitchStateContainer *ssc, StitchState *state)
{
BMesh *bm = state->em->bm;
float limit;
@@ -364,9 +384,9 @@ static bool stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, Stitc
return 0;
}
- limit = state->limit_dist;
+ limit = ssc->limit_dist;
- if (state->use_limit) {
+ if (ssc->use_limit) {
BMLoop *l;
MLoopUV *luv_orig1, *luv_iter1;
MLoopUV *luv_orig2, *luv_iter2;
@@ -397,27 +417,30 @@ static bool stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, Stitc
}
}
-static bool stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
+static bool stitch_check_uvs_state_stitchable(
+ UvElement *element, UvElement *element_iter,
+ StitchStateContainer *ssc, StitchState *state)
{
- if ((state->snap_islands && element->island == element_iter->island) ||
- (!state->midpoints && element->island == element_iter->island))
+ if ((ssc->snap_islands && element->island == element_iter->island) ||
+ (!ssc->midpoints && element->island == element_iter->island))
{
return 0;
}
- return stitch_check_uvs_stitchable(element, element_iter, state);
+ return stitch_check_uvs_stitchable(element, element_iter, ssc, state);
}
-
-static bool stitch_check_edges_state_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
+static bool stitch_check_edges_state_stitchable(
+ UvEdge *edge, UvEdge *edge_iter,
+ StitchStateContainer *ssc, StitchState *state)
{
- if ((state->snap_islands && edge->element->island == edge_iter->element->island) ||
- (!state->midpoints && edge->element->island == edge_iter->element->island))
+ if ((ssc->snap_islands && edge->element->island == edge_iter->element->island) ||
+ (!ssc->midpoints && edge->element->island == edge_iter->element->island))
{
return 0;
}
- return stitch_check_edges_stitchable(edge, edge_iter, state);
+ return stitch_check_edges_stitchable(edge, edge_iter, ssc, state);
}
/* calculate snapping for islands */
@@ -489,9 +512,10 @@ static void stitch_calculate_island_snapping(
int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint,
- preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect);
+ preview->preview_polys + face_preview_pos + 2 * element->loop_of_poly_index,
+ state->aspect);
- add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
+ add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->loop_of_poly_index,
island_stitch_data[i].translation);
}
}
@@ -505,8 +529,8 @@ static void stitch_calculate_island_snapping(
static void stitch_island_calculate_edge_rotation(
- UvEdge *edge, StitchState *state, UVVertAverage *uv_average, unsigned int *uvfinal_map,
- IslandStitchData *island_stitch_data)
+ UvEdge *edge, StitchStateContainer *ssc, StitchState *state, UVVertAverage *uv_average,
+ unsigned int *uvfinal_map, IslandStitchData *island_stitch_data)
{
BMesh *bm = state->em->bm;
UvElement *element1, *element2;
@@ -522,7 +546,7 @@ static void stitch_island_calculate_edge_rotation(
luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_MLOOPUV);
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
index1 = uvfinal_map[element1 - state->element_map->buf];
index2 = uvfinal_map[element2 - state->element_map->buf];
}
@@ -561,7 +585,7 @@ static void stitch_island_calculate_edge_rotation(
static void stitch_island_calculate_vert_rotation(
- UvElement *element, StitchState *state,
+ UvElement *element, StitchStateContainer *ssc, StitchState *state,
IslandStitchData *island_stitch_data)
{
float edgecos = 1.0f, edgesin = 0.0f;
@@ -571,7 +595,7 @@ static void stitch_island_calculate_vert_rotation(
int rot_elem = 0, rot_elem_neg = 0;
BMLoop *l;
- if (element->island == state->static_island && !state->midpoints)
+ if (element->island == ssc->static_island && !ssc->midpoints)
return;
l = element->l;
@@ -581,12 +605,12 @@ static void stitch_island_calculate_vert_rotation(
element_iter = state->element_map->vert[index];
for (; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, state)) {
+ if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
int index_tmp1, index_tmp2;
float normal[2];
/* only calculate rotation against static island uv verts */
- if (!state->midpoints && element_iter->island != state->static_island)
+ if (!ssc->midpoints && element_iter->island != ssc->static_island)
continue;
index_tmp1 = element_iter - state->element_map->buf;
@@ -608,7 +632,7 @@ static void stitch_island_calculate_vert_rotation(
}
}
- if (state->midpoints) {
+ if (ssc->midpoints) {
rotation /= 2.0f;
rotation_neg /= 2.0f;
}
@@ -622,6 +646,9 @@ static void stitch_island_calculate_vert_rotation(
static void state_delete(StitchState *state)
{
if (state) {
+ if (state->island_is_stitchable) {
+ MEM_freeN(state->island_is_stitchable);
+ }
if (state->element_map) {
BM_uv_element_map_free(state->element_map);
}
@@ -653,6 +680,18 @@ static void state_delete(StitchState *state)
}
}
+static void state_delete_all(StitchStateContainer *ssc)
+{
+ if (ssc) {
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ state_delete(ssc->states[ob_index]);
+ }
+ MEM_freeN(ssc->states);
+ MEM_freeN(ssc->objects);
+ MEM_freeN(ssc);
+ }
+}
+
static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
{
UvEdge *edges = state->edges;
@@ -735,7 +774,7 @@ static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *
/* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
static void determine_uv_stitchability(
- UvElement *element, StitchState *state,
+ UvElement *element, StitchStateContainer *ssc, StitchState *state,
IslandStitchData *island_stitch_data)
{
int vert_index;
@@ -749,7 +788,7 @@ static void determine_uv_stitchability(
for (; element_iter; element_iter = element_iter->next) {
if (element_iter->separate) {
- if (stitch_check_uvs_stitchable(element, element_iter, state)) {
+ if (stitch_check_uvs_stitchable(element, element_iter, ssc, state)) {
island_stitch_data[element_iter->island].stitchableCandidate = 1;
island_stitch_data[element->island].stitchableCandidate = 1;
element->flag |= STITCH_STITCHABLE_CANDIDATE;
@@ -759,13 +798,13 @@ static void determine_uv_stitchability(
}
static void determine_uv_edge_stitchability(
- UvEdge *edge, StitchState *state,
+ UvEdge *edge, StitchStateContainer *ssc, StitchState *state,
IslandStitchData *island_stitch_data)
{
UvEdge *edge_iter = edge->first;
for (; edge_iter; edge_iter = edge_iter->next) {
- if (stitch_check_edges_stitchable(edge, edge_iter, state)) {
+ if (stitch_check_edges_stitchable(edge, edge_iter, ssc, state)) {
island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
island_stitch_data[edge->element->island].stitchableCandidate = 1;
edge->flag |= STITCH_STITCHABLE_CANDIDATE;
@@ -790,16 +829,16 @@ static void stitch_set_face_preview_buffer_position(
/* setup face preview for all coincident uvs and their faces */
static void stitch_setup_face_preview_for_uv_group(
- UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
- PreviewPosition *preview_position)
+ UvElement *element, StitchStateContainer *ssc, StitchState *state,
+ IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
{
StitchPreviewer *preview = state->stitch_preview;
/* static island does not change so returning immediately */
- if (state->snap_islands && !state->midpoints && state->static_island == element->island)
+ if (ssc->snap_islands && !ssc->midpoints && ssc->static_island == element->island)
return;
- if (state->snap_islands) {
+ if (ssc->snap_islands) {
island_stitch_data[element->island].addedForPreview = 1;
}
@@ -812,11 +851,18 @@ static void stitch_setup_face_preview_for_uv_group(
/* checks if uvs are indeed stitchable and registers so that they can be shown in preview */
static void stitch_validate_uv_stitchability(
- UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
- PreviewPosition *preview_position)
+ UvElement *element, StitchStateContainer *ssc, StitchState *state,
+ IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
{
- UvElement *element_iter;
StitchPreviewer *preview = state->stitch_preview;
+
+ /* If not the active object, then it's unstitchable */
+ if (ssc->states[ssc->active_object_index] != state) {
+ preview->num_unstitchable++;
+ return;
+ }
+
+ UvElement *element_iter;
int vert_index;
BMLoop *l;
@@ -830,11 +876,11 @@ static void stitch_validate_uv_stitchability(
if (element_iter->separate) {
if (element_iter == element)
continue;
- if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
- if ((element_iter->island == state->static_island) || (element->island == state->static_island)) {
+ if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
+ if ((element_iter->island == ssc->static_island) || (element->island == ssc->static_island)) {
element->flag |= STITCH_STITCHABLE;
preview->num_stitchable++;
- stitch_setup_face_preview_for_uv_group(element, state, island_stitch_data, preview_position);
+ stitch_setup_face_preview_for_uv_group(element, ssc, state, island_stitch_data, preview_position);
return;
}
}
@@ -849,21 +895,28 @@ static void stitch_validate_uv_stitchability(
static void stitch_validate_edge_stitchability(
- UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data,
- PreviewPosition *preview_position)
+ UvEdge *edge, StitchStateContainer *ssc, StitchState *state,
+ IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
{
- UvEdge *edge_iter = edge->first;
StitchPreviewer *preview = state->stitch_preview;
+ /* If not the active object, then it's unstitchable */
+ if (ssc->states[ssc->active_object_index] != state) {
+ preview->num_unstitchable++;
+ return;
+ }
+
+ UvEdge *edge_iter = edge->first;
+
for (; edge_iter; edge_iter = edge_iter->next) {
if (edge_iter == edge)
continue;
- if (stitch_check_edges_state_stitchable(edge, edge_iter, state)) {
- if ((edge_iter->element->island == state->static_island) || (edge->element->island == state->static_island)) {
+ if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
+ if ((edge_iter->element->island == ssc->static_island) || (edge->element->island == ssc->static_island)) {
edge->flag |= STITCH_STITCHABLE;
preview->num_stitchable++;
- stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1], state, island_stitch_data, preview_position);
- stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2], state, island_stitch_data, preview_position);
+ stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1], ssc, state, island_stitch_data, preview_position);
+ stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2], ssc, state, island_stitch_data, preview_position);
return;
}
}
@@ -879,7 +932,7 @@ static void stitch_validate_edge_stitchability(
static void stitch_propagate_uv_final_position(
Scene *scene,
UvElement *element, int index, PreviewPosition *preview_position,
- UVVertAverage *final_position, StitchState *state,
+ UVVertAverage *final_position, StitchStateContainer *ssc, StitchState *state,
const bool final)
{
BMesh *bm = state->em->bm;
@@ -907,13 +960,13 @@ static void stitch_propagate_uv_final_position(
else {
int face_preview_pos = preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
if (face_preview_pos != STITCH_NO_PREVIEW) {
- copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
- final_position[index].uv);
+ copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->loop_of_poly_index,
+ final_position[index].uv);
}
}
/* end of calculations, keep only the selection flag */
- if ((!state->snap_islands) || ((!state->midpoints) && (element_iter->island == state->static_island))) {
+ if ((!ssc->snap_islands) || ((!ssc->midpoints) && (element_iter->island == ssc->static_island))) {
element_iter->flag &= STITCH_SELECTED;
}
@@ -923,18 +976,20 @@ static void stitch_propagate_uv_final_position(
}
/* main processing function. It calculates preview and final positions. */
-static int stitch_process_data(StitchState *state, Scene *scene, int final)
+static int stitch_process_data(
+ StitchStateContainer *ssc, StitchState *state, Scene *scene, int final)
{
int i;
StitchPreviewer *preview;
IslandStitchData *island_stitch_data = NULL;
- int previous_island = state->static_island;
+ int previous_island = ssc->static_island;
BMesh *bm = state->em->bm;
BMFace *efa;
BMIter iter;
UVVertAverage *final_position = NULL;
+ bool is_active_state = (state == ssc->states[ssc->active_object_index]);
- char stitch_midpoints = state->midpoints;
+ char stitch_midpoints = ssc->midpoints;
/* used to map uv indices to uvaverage indices for selection */
unsigned int *uvfinal_map = NULL;
/* per face preview position in preview buffer */
@@ -965,32 +1020,41 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
*****************************************/
for (i = 0; i < state->selection_size; i++) {
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
UvElement *element = (UvElement *)state->selection_stack[i];
- determine_uv_stitchability(element, state, island_stitch_data);
+ determine_uv_stitchability(element, ssc, state, island_stitch_data);
}
else {
UvEdge *edge = (UvEdge *)state->selection_stack[i];
- determine_uv_edge_stitchability(edge, state, island_stitch_data);
+ determine_uv_edge_stitchability(edge, ssc, state, island_stitch_data);
}
}
- /* set static island to one that is added for preview */
- state->static_island %= state->element_map->totalIslands;
- while (!(island_stitch_data[state->static_island].stitchableCandidate)) {
- state->static_island++;
- state->static_island %= state->element_map->totalIslands;
- /* this is entirely possible if for example limit stitching with no stitchable verts or no selection */
- if (state->static_island == previous_island)
- break;
+ /* remember stitchable candidates as places the 'I' button */
+ /* will stop at. */
+ for (int island_idx = 0; island_idx < state->element_map->totalIslands; island_idx++) {
+ state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ? true : false;
+ }
+
+ if (is_active_state) {
+ /* set static island to one that is added for preview */
+ ssc->static_island %= state->element_map->totalIslands;
+ while (!(island_stitch_data[ssc->static_island].stitchableCandidate)) {
+ ssc->static_island++;
+ ssc->static_island %= state->element_map->totalIslands;
+ /* this is entirely possible if for example limit stitching with no stitchable verts or no selection */
+ if (ssc->static_island == previous_island) {
+ break;
+ }
+ }
}
for (i = 0; i < state->selection_size; i++) {
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
UvElement *element = (UvElement *)state->selection_stack[i];
if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
- stitch_validate_uv_stitchability(element, state, island_stitch_data, preview_position);
+ stitch_validate_uv_stitchability(element, ssc, state, island_stitch_data, preview_position);
}
else {
/* add to preview for unstitchable */
@@ -1001,7 +1065,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
UvEdge *edge = (UvEdge *)state->selection_stack[i];
if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
- stitch_validate_edge_stitchability(edge, state, island_stitch_data, preview_position);
+ stitch_validate_edge_stitchability(edge, ssc, state, island_stitch_data, preview_position);
}
else {
preview->num_unstitchable++;
@@ -1009,10 +1073,90 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
}
+ /*********************************************************************
+ * Setup the stitchable & unstitchable preview buffers and fill *
+ * them with the appropriate data *
+ *********************************************************************/
+ if (!final) {
+ BMLoop *l;
+ MLoopUV *luv;
+ int stitchBufferIndex = 0, unstitchBufferIndex = 0;
+ int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
+ /* initialize the preview buffers */
+ preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stitchable_data");
+ preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * preview_size, "stitch_preview_unstitchable_data");
+
+ /* will cause cancel and freeing of all data structures so OK */
+ if (!preview->preview_stitchable || !preview->preview_unstitchable) {
+ return 0;
+ }
+
+ /* fill the appropriate preview buffers */
+ if (ssc->mode == STITCH_VERT) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ UvElement *element = (UvElement *)state->uvs[i];
+ if (element->flag & STITCH_STITCHABLE) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
+
+ stitchBufferIndex++;
+ }
+ else if (element->flag & STITCH_SELECTED) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
+ unstitchBufferIndex++;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ if (edge->flag & STITCH_STITCHABLE) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
+
+ l = element2->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
+
+ stitchBufferIndex++;
+ BLI_assert(stitchBufferIndex <= preview->num_stitchable);
+ }
+ else if (edge->flag & STITCH_SELECTED) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
+
+ l = element2->l;
+ luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
+
+ unstitchBufferIndex++;
+ BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
+ }
+ }
+ }
+ }
+
+ if (ssc->states[ssc->active_object_index] != state) {
+ /* This is not the active object/state, exit here */
+ MEM_freeN(island_stitch_data);
+ MEM_freeN(preview_position);
+ return 1;
+ }
+
/*****************************************
* Setup preview for stitchable islands *
*****************************************/
- if (state->snap_islands) {
+ if (ssc->snap_islands) {
for (i = 0; i < state->element_map->totalIslands; i++) {
if (island_stitch_data[i].addedForPreview) {
int numOfIslandUVs = 0, j;
@@ -1027,26 +1171,24 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
/*********************************************************************
- * Setup the preview buffers and fill them with the appropriate data *
+ * Setup the remaining preview buffers and fill them with the *
+ * appropriate data *
*********************************************************************/
if (!final) {
BMIter liter;
BMLoop *l;
MLoopUV *luv;
unsigned int buffer_index = 0;
- int stitchBufferIndex = 0, unstitchBufferIndex = 0;
- int preview_size = (state->mode == STITCH_VERT) ? 2 : 4;
+
/* initialize the preview buffers */
preview->preview_polys = (float *)MEM_mallocN(preview->preview_uvs * sizeof(float) * 2, "tri_uv_stitch_prev");
preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon), "tri_uv_stitch_prev");
- preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stitchable_data");
- preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * preview_size, "stitch_preview_unstitchable_data");
- preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[state->static_island] * sizeof(float) * 6, "static_island_preview_tris");
+ preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[ssc->static_island] * sizeof(float) * 6, "static_island_preview_tris");
- preview->num_static_tris = state->tris_per_island[state->static_island];
+ preview->num_static_tris = state->tris_per_island[ssc->static_island];
/* will cause cancel and freeing of all data structures so OK */
- if (!preview->preview_polys || !preview->preview_stitchable || !preview->preview_unstitchable) {
+ if (!preview->preview_polys) {
return 0;
}
@@ -1067,7 +1209,8 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
}
- if (element->island == state->static_island) {
+ /* if this is the static_island on the active object */
+ if (element->island == ssc->static_island) {
BMLoop *fl = BM_FACE_FIRST_LOOP(efa);
MLoopUV *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_MLOOPUV);
@@ -1090,67 +1233,13 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
}
}
-
- /* fill the appropriate preview buffers */
- if (state->mode == STITCH_VERT) {
- for (i = 0; i < state->total_separate_uvs; i++) {
- UvElement *element = (UvElement *)state->uvs[i];
- if (element->flag & STITCH_STITCHABLE) {
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
-
- stitchBufferIndex++;
- }
- else if (element->flag & STITCH_SELECTED) {
- l = element->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
- unstitchBufferIndex++;
- }
- }
- }
- else {
- for (i = 0; i < state->total_separate_edges; i++) {
- UvEdge *edge = state->edges + i;
- UvElement *element1 = state->uvs[edge->uv1];
- UvElement *element2 = state->uvs[edge->uv2];
-
- if (edge->flag & STITCH_STITCHABLE) {
- l = element1->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
-
- l = element2->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
-
- stitchBufferIndex++;
- BLI_assert(stitchBufferIndex <= preview->num_stitchable);
- }
- else if (edge->flag & STITCH_SELECTED) {
- l = element1->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
-
- l = element2->l;
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
-
- unstitchBufferIndex++;
- BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
- }
- }
- }
}
/******************************************************
* Here we calculate the final coordinates of the uvs *
******************************************************/
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
}
@@ -1160,7 +1249,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
/* first pass, calculate final position for stitchable uvs of the static island */
for (i = 0; i < state->selection_size; i++) {
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
UvElement *element = state->selection_stack[i];
if (element->flag & STITCH_STITCHABLE) {
@@ -1176,21 +1265,21 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
copy_v2_v2(final_position[i].uv, luv->uv);
final_position[i].count = 1;
- if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
+ if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints)
continue;
element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
for ( ; element_iter; element_iter = element_iter->next) {
if (element_iter->separate) {
- if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
+ if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
l = element_iter->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
if (stitch_midpoints) {
add_v2_v2(final_position[i].uv, luv->uv);
final_position[i].count++;
}
- else if (element_iter->island == state->static_island) {
+ else if (element_iter->island == ssc->static_island) {
/* if multiple uvs on the static island exist,
* last checked remains. to disambiguate we need to limit or use
* edge stitch */
@@ -1226,11 +1315,11 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
- if (state->snap_islands && edge->element->island == state->static_island && !stitch_midpoints)
+ if (ssc->snap_islands && edge->element->island == ssc->static_island && !stitch_midpoints)
continue;
for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
- if (stitch_check_edges_state_stitchable (edge, edge_iter, state)) {
+ if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
l = state->uvs[edge_iter->uv1]->l;
luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
l = state->uvs[edge_iter->uv2]->l;
@@ -1242,7 +1331,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
final_position[edge->uv2].count++;
}
- else if (edge_iter->element->island == state->static_island) {
+ else if (edge_iter->element->island == ssc->static_island) {
copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
}
@@ -1253,7 +1342,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
/* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
- if (state->mode == STITCH_EDGE && stitch_midpoints) {
+ if (ssc->mode == STITCH_EDGE && stitch_midpoints) {
for (i = 0; i < state->total_separate_uvs; i++) {
final_position[i].uv[0] /= final_position[i].count;
final_position[i].uv[1] /= final_position[i].count;
@@ -1261,8 +1350,8 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
/* second pass, calculate island rotation and translation before modifying any uvs */
- if (state->snap_islands) {
- if (state->mode == STITCH_VERT) {
+ if (ssc->snap_islands) {
+ if (ssc->mode == STITCH_VERT) {
for (i = 0; i < state->selection_size; i++) {
UvElement *element = state->selection_stack[i];
@@ -1290,13 +1379,13 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
(state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
(state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
{
- stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
+ stitch_island_calculate_edge_rotation(edge, ssc, state, final_position, uvfinal_map, island_stitch_data);
island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
}
}
/* clear seams of stitched edges */
- if (final && state->clear_seams) {
+ if (final && ssc->clear_seams) {
for (i = 0; i < state->total_separate_edges; i++) {
UvEdge *edge = state->edges + i;
if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
@@ -1311,7 +1400,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
UvElement *element = state->selection_stack[i];
if (!island_stitch_data[element->island].use_edge_rotation) {
if (element->flag & STITCH_STITCHABLE) {
- stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
+ stitch_island_calculate_vert_rotation(element, ssc, state, island_stitch_data);
}
}
}
@@ -1328,7 +1417,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
/* accumulate each islands' translation from stitchable elements. it is important to do here
- * because in final pass MTFaces get modified and result is zero. */
+ * because in final pass MTFaces get modified and result is zero. */
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
@@ -1341,13 +1430,13 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
UvEdge *edge = state->selection_stack[i];
if (edge->flag & STITCH_STITCHABLE) {
- stitch_island_calculate_edge_rotation(edge, state, final_position, NULL, island_stitch_data);
+ stitch_island_calculate_edge_rotation(edge, ssc, state, final_position, NULL, island_stitch_data);
island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = true;
}
}
/* clear seams of stitched edges */
- if (final && state->clear_seams) {
+ if (final && ssc->clear_seams) {
for (i = 0; i < state->selection_size; i++) {
UvEdge *edge = state->selection_stack[i];
if (edge->flag & STITCH_STITCHABLE) {
@@ -1360,30 +1449,30 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
/* third pass, propagate changes to coincident uvs */
for (i = 0; i < state->selection_size; i++) {
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
UvElement *element = state->selection_stack[i];
- stitch_propagate_uv_final_position(scene, element, i, preview_position, final_position, state, final);
+ stitch_propagate_uv_final_position(scene, element, i, preview_position, final_position, ssc, state, final);
}
else {
UvEdge *edge = state->selection_stack[i];
stitch_propagate_uv_final_position(
- scene, state->uvs[edge->uv1], edge->uv1, preview_position, final_position, state, final);
+ scene, state->uvs[edge->uv1], edge->uv1, preview_position, final_position, ssc, state, final);
stitch_propagate_uv_final_position(
- scene, state->uvs[edge->uv2], edge->uv2, preview_position, final_position, state, final);
+ scene, state->uvs[edge->uv2], edge->uv2, preview_position, final_position, ssc, state, final);
edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
}
}
/* final pass, calculate Island translation/rotation if needed */
- if (state->snap_islands) {
+ if (ssc->snap_islands) {
stitch_calculate_island_snapping(state, preview_position, preview, island_stitch_data, final);
}
MEM_freeN(final_position);
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
MEM_freeN(uvfinal_map);
}
MEM_freeN(island_stitch_data);
@@ -1392,6 +1481,17 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
return 1;
}
+static int stitch_process_data_all(StitchStateContainer *ssc, Scene *scene, int final)
+{
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (!stitch_process_data(ssc, ssc->states[ob_index], scene, final)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/* Stitch hash initialization functions */
static unsigned int uv_edge_hash(const void *key)
{
@@ -1476,13 +1576,13 @@ static void stitch_select_uv(UvElement *element, StitchState *state, int always_
}
}
-static void stitch_switch_selection_mode(StitchState *state)
+static void stitch_set_selection_mode(StitchState *state, const char from_stitch_mode)
{
void **old_selection_stack = state->selection_stack;
int old_selection_size = state->selection_size;
state->selection_size = 0;
- if (state->mode == STITCH_VERT) {
+ if (from_stitch_mode == STITCH_VERT) {
int i;
state->selection_stack = MEM_mallocN(state->total_separate_edges * sizeof(*state->selection_stack),
"stitch_new_edge_selection_stack");
@@ -1503,7 +1603,6 @@ static void stitch_switch_selection_mode(StitchState *state)
element->flag &= ~STITCH_SELECTED;
}
- state->mode = STITCH_EDGE;
}
else {
int i;
@@ -1520,12 +1619,26 @@ static void stitch_switch_selection_mode(StitchState *state)
edge->flag &= ~STITCH_SELECTED;
}
- state->mode = STITCH_VERT;
}
MEM_freeN(old_selection_stack);
}
-static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
+static void stitch_switch_selection_mode_all(StitchStateContainer *ssc)
+{
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ stitch_set_selection_mode(ssc->states[ob_index], ssc->mode);
+ }
+
+ if (ssc->mode == STITCH_VERT) {
+ ssc->mode = STITCH_EDGE;
+ }
+ else {
+ ssc->mode = STITCH_VERT;
+ }
+}
+
+static void stitch_calculate_edge_normal(
+ BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
{
BMLoop *l1 = edge->element->l;
MLoopUV *luv1, *luv2;
@@ -1534,7 +1647,7 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no
luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
- sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
+ sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
tangent[1] /= aspect;
@@ -1546,123 +1659,132 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no
/**
*/
-static void stitch_draw_vbo(Gwn_VertBuf *vbo, Gwn_PrimType prim_type, const float col[4])
+static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float col[4])
{
- Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO);
- GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
- GWN_batch_uniform_4fv(batch, "color", col);
- GWN_batch_draw(batch);
- GWN_batch_discard(batch);
+ GPUBatch *batch = GPU_batch_create_ex(prim_type, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4fv(batch, "color", col);
+ GPU_batch_draw(batch);
+ GPU_batch_discard(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 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;
- Gwn_VertBuf *vbo, *vbo_line;
- float col[4];
-
- static Gwn_VertFormat format = { 0 };
- static unsigned int pos_id;
- if (format.attr_len == 0) {
- pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
- GPU_blend(true);
+ StitchStateContainer *ssc = (StitchStateContainer *)arg;
- /* Static Tris */
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3);
- for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) {
- GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]);
- }
- stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col);
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ int j, index = 0;
+ unsigned int num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
+ StitchState *state = ssc->states[ob_index];
+ StitchPreviewer *stitch_preview = state->stitch_preview;
+ GPUVertBuf *vbo, *vbo_line;
+ float col[4];
+ static GPUVertFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
- /* Preview Polys */
- for (int i = 0; i < stitch_preview->num_polys; i++)
- num_line += stitch_preview->uvs_per_polygon[i];
+ GPU_blend(true);
- num_tri = num_line - 2 * stitch_preview->num_polys;
+ /* Static Tris */
+ if (stitch_preview->static_tris) {
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3);
+ for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
+ }
- /* we need to convert the polys into triangles / lines */
- vbo = GWN_vertbuf_create_with_format(&format);
- vbo_line = GWN_vertbuf_create_with_format(&format);
+ /* Preview Polys */
+ if (stitch_preview->preview_polys) {
+ for (int i = 0; i < stitch_preview->num_polys; i++)
+ num_line += stitch_preview->uvs_per_polygon[i];
- GWN_vertbuf_data_alloc(vbo, num_tri * 3);
- GWN_vertbuf_data_alloc(vbo_line, num_line * 2);
+ num_tri = num_line - 2 * stitch_preview->num_polys;
- for (int i = 0; i < stitch_preview->num_polys; i++) {
- BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
+ /* we need to convert the polys into triangles / lines */
+ vbo = GPU_vertbuf_create_with_format(&format);
+ vbo_line = GPU_vertbuf_create_with_format(&format);
- /* Start line */
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
+ GPU_vertbuf_data_alloc(vbo, num_tri * 3);
+ GPU_vertbuf_data_alloc(vbo_line, num_line * 2);
- for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
- GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
- GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
- GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
- }
+ for (int i = 0; i < stitch_preview->num_polys; i++) {
+ BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
- /* Closing line */
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
- /* j = uvs_per_polygon[i] - 1*/
- GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
+ /* Start line */
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
- index += stitch_preview->uvs_per_polygon[i] * 2;
- }
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
- stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col);
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
- stitch_draw_vbo(vbo_line, GWN_PRIM_LINES, col);
+ for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
+ GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
+ GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GPU_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
- GPU_blend(false);
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
+ }
+ /* Closing line */
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ /* j = uvs_per_polygon[i] - 1*/
+ GPU_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
- /* draw stitch vert/lines preview */
- if (state->mode == STITCH_VERT) {
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
+ index += stitch_preview->uvs_per_polygon[i] * 2;
+ }
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable);
- for (int i = 0; i < stitch_preview->num_stitchable; i++) {
- GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
+ stitch_draw_vbo(vbo, GPU_PRIM_TRIS, col);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
+ stitch_draw_vbo(vbo_line, GPU_PRIM_LINES, col);
}
- stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col);
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable);
- for (int i = 0; i < stitch_preview->num_unstitchable; i++) {
- GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
- }
- stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col);
- }
- else {
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2);
- for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) {
- GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ GPU_blend(false);
+
+ /* draw stitch vert/lines preview */
+ if (ssc->mode == STITCH_VERT) {
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable);
+ for (int i = 0; i < stitch_preview->num_stitchable; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable);
+ for (int i = 0; i < stitch_preview->num_unstitchable; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_POINTS, col);
}
- stitch_draw_vbo(vbo, GWN_PRIM_LINES, col);
+ else {
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2);
+ for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
- UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
- vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2);
- for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) {
- GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2);
+ for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GPU_PRIM_LINES, col);
}
- stitch_draw_vbo(vbo, GWN_PRIM_LINES, col);
}
}
@@ -1688,7 +1810,9 @@ static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
}
-static int stitch_init(bContext *C, wmOperator *op)
+static StitchState *stitch_init(
+ bContext *C, wmOperator *op,
+ StitchStateContainer *ssc, Object *obedit)
{
/* for fast edge lookup... */
GHash *edge_hash;
@@ -1706,47 +1830,16 @@ static int stitch_init(bContext *C, wmOperator *op)
StitchState *state;
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
- ARegion *ar = CTX_wm_region(C);
float aspx, aspy;
- Object *obedit = CTX_data_edit_object(C);
+
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- if (!ar)
- return 0;
-
- state = MEM_callocN(sizeof(StitchState), "stitch state");
-
- op->customdata = state;
+ state = MEM_callocN(sizeof(StitchState), "stitch state obj");
/* initialize state */
- state->use_limit = RNA_boolean_get(op->ptr, "use_limit");
- state->limit_dist = RNA_float_get(op->ptr, "limit");
state->obedit = obedit;
state->em = em;
- state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
- state->static_island = RNA_int_get(op->ptr, "static_island");
- state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
- state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
- if (RNA_struct_property_is_set(op->ptr, "mode")) {
- state->mode = RNA_enum_get(op->ptr, "mode");
- }
- else {
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_VERTEX)
- state->mode = STITCH_VERT;
- else
- state->mode = STITCH_EDGE;
- }
- else {
- if (ts->uv_selectmode & UV_SELECT_VERTEX) {
- state->mode = STITCH_VERT;
- }
- else {
- state->mode = STITCH_EDGE;
- }
- }
- }
/* in uv synch selection, all uv's are visible */
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -1757,16 +1850,12 @@ static int stitch_init(bContext *C, wmOperator *op)
}
if (!state->element_map) {
state_delete(state);
- return 0;
+ return NULL;
}
ED_uvedit_get_aspect(scene, obedit, em->bm, &aspx, &aspy);
state->aspect = aspx / aspy;
- /* Entirely possible if redoing last operator that static island is bigger than total number of islands.
- * This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
- state->static_island %= state->element_map->totalIslands;
-
/* Count 'unique' uvs */
for (i = 0; i < state->element_map->totalUVs; i++) {
if (state->element_map->buf[i].separate) {
@@ -1785,11 +1874,11 @@ static int stitch_init(bContext *C, wmOperator *op)
state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
/* Allocate the edge stack */
edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
- all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "stitch_all_edges");
+ all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "ssc_edges");
if (!state->uvs || !map || !edge_hash || !all_edges) {
state_delete(state);
- return 0;
+ return NULL;
}
/* So that we can use this as index for the UvElements */
@@ -1858,7 +1947,7 @@ static int stitch_init(bContext *C, wmOperator *op)
/* I assume any system will be able to at least allocate an iterator :p */
if (!edges) {
state_delete(state);
- return 0;
+ return NULL;
}
state->total_separate_edges = total_edges;
@@ -1908,7 +1997,8 @@ static int stitch_init(bContext *C, wmOperator *op)
state->selection_size = 0;
/* Load old selection if redoing operator with different settings */
- if (RNA_struct_property_is_set(op->ptr, "selection")) {
+ /* WIP */
+ if (false && RNA_struct_property_is_set(op->ptr, "selection")) {
int faceIndex, elementIndex;
UvElement *element;
enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
@@ -1961,16 +2051,15 @@ static int stitch_init(bContext *C, wmOperator *op)
}
/* if user has switched the operator mode after operation, we need to convert
* the stored format */
- if (state->mode != stored_mode) {
- state->mode = stored_mode;
- stitch_switch_selection_mode(state);
+ if (ssc->mode != stored_mode) {
+ stitch_set_selection_mode(state, stored_mode);
}
/* Clear the selection */
RNA_collection_clear(op->ptr, "selection");
}
else {
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -2022,22 +2111,154 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
- if (!stitch_process_data(state, scene, false)) {
+ state->island_is_stitchable = MEM_callocN(sizeof(bool) * state->element_map->totalIslands, "stitch I stops");
+ if (!state->island_is_stitchable) {
+ state_delete(state);
+ return NULL;
+ }
+ if (!stitch_process_data(ssc, state, scene, false)) {
state_delete(state);
+ return NULL;
+ }
+
+ return state;
+}
+
+static bool goto_next_island(StitchStateContainer *ssc)
+{
+ StitchState *active_state = ssc->states[ssc->active_object_index];
+ StitchState *original_active_state = active_state;
+
+ int original_island = ssc->static_island;
+
+ do {
+ ssc->static_island++;
+ if (ssc->static_island >= active_state->element_map->totalIslands) {
+ /* go to next object */
+ ssc->active_object_index++;
+ ssc->active_object_index %= ssc->objects_len;
+
+ active_state = ssc->states[ssc->active_object_index];
+ ssc->static_island = 0;
+ }
+
+ if (active_state->island_is_stitchable[ssc->static_island]) {
+ /* We're at an island to make active */
+ return true;
+ }
+ } while (!(active_state == original_active_state &&
+ ssc->static_island == original_island));
+
+ return false;
+}
+
+static int stitch_init_all(bContext *C, wmOperator *op)
+{
+ ARegion *ar = CTX_wm_region(C);
+ if (!ar)
+ return 0;
+
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+
+ StitchStateContainer *ssc = MEM_callocN(sizeof(StitchStateContainer), "stitch collection");
+
+ op->customdata = ssc;
+
+ ssc->use_limit = RNA_boolean_get(op->ptr, "use_limit");
+ ssc->limit_dist = RNA_float_get(op->ptr, "limit");
+ ssc->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
+ ssc->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
+ ssc->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
+ ssc->active_object_index = RNA_int_get(op->ptr, "active_object_index");
+ ssc->static_island = 0;
+
+ if (RNA_struct_property_is_set(op->ptr, "mode")) {
+ ssc->mode = RNA_enum_get(op->ptr, "mode");
+ }
+ else {
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_VERTEX)
+ ssc->mode = STITCH_VERT;
+ else
+ ssc->mode = STITCH_EDGE;
+ }
+ else {
+ if (ts->uv_selectmode & UV_SELECT_VERTEX) {
+ ssc->mode = STITCH_VERT;
+ }
+ else {
+ ssc->mode = STITCH_EDGE;
+ }
+ }
+ }
+
+ ssc->objects_len = 0;
+ ssc->states = NULL;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, &objects_len);
+
+ if (objects_len == 0) {
+ MEM_freeN(objects);
+ state_delete_all(ssc);
return 0;
}
- state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, state, REGION_DRAW_POST_VIEW);
+ ssc->objects = MEM_callocN(sizeof(Object *) * objects_len, "Object *ssc->objects");
+ ssc->states = MEM_callocN(sizeof(StitchState *) * objects_len, "StitchState");
+ ssc->objects_len = 0;
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+
+ StitchState *stitch_state_ob = stitch_init(C, op, ssc, obedit);
+
+ if (stitch_state_ob) {
+ ssc->objects[ssc->objects_len] = obedit;
+ ssc->states[ssc->objects_len] = stitch_state_ob;
+ ssc->objects_len++;
+ }
+ }
+
+ MEM_freeN(objects);
+
+ if (ssc->objects_len == 0) {
+ state_delete_all(ssc);
+ return 0;
+ }
+
+ ssc->active_object_index %= ssc->objects_len;
+
+ ssc->static_island = RNA_int_get(op->ptr, "static_island");
+
+ StitchState *state = ssc->states[ssc->active_object_index];
+ ssc->static_island %= state->element_map->totalIslands;
+
+ /* If the initial active object doesn't have any stitchable islands */
+ /* then no active island will be seen in the UI. Make sure we're on */
+ /* a stitchable object and island. */
+ if (!state->island_is_stitchable[ssc->static_island]) {
+ goto_next_island(ssc);
+ state = ssc->states[ssc->active_object_index];
+ }
+
+ /* process active stitchobj again now that it can detect it's the active stitchobj */
+ stitch_process_data(ssc, state, scene, false);
+
+ stitch_update_header(ssc, C);
+
+ ssc->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, ssc, REGION_DRAW_POST_VIEW);
- stitch_update_header(state, C);
return 1;
}
static int stitch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *obedit = CTX_data_edit_object(C);
- if (!stitch_init(C, op))
+ if (!stitch_init_all(C, op))
return OPERATOR_CANCELLED;
WM_event_add_modal_handler(C, op);
@@ -2047,34 +2268,37 @@ static int stitch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(even
static void stitch_exit(bContext *C, wmOperator *op, int finished)
{
- StitchState *state;
Scene *scene;
SpaceImage *sima;
ScrArea *sa = CTX_wm_area(C);
- Object *obedit;
scene = CTX_data_scene(C);
- obedit = CTX_data_edit_object(C);
sima = CTX_wm_space_image(C);
- state = (StitchState *)op->customdata;
+ StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
+ StitchState *state = ssc->states[ssc->active_object_index];
+ Object *obedit = state->obedit;
if (finished) {
int i;
- RNA_float_set(op->ptr, "limit", state->limit_dist);
- RNA_boolean_set(op->ptr, "use_limit", state->use_limit);
- RNA_boolean_set(op->ptr, "snap_islands", state->snap_islands);
- RNA_int_set(op->ptr, "static_island", state->static_island);
- RNA_boolean_set(op->ptr, "midpoint_snap", state->midpoints);
- RNA_enum_set(op->ptr, "mode", state->mode);
- RNA_enum_set(op->ptr, "stored_mode", state->mode);
+ RNA_float_set(op->ptr, "limit", ssc->limit_dist);
+ RNA_boolean_set(op->ptr, "use_limit", ssc->use_limit);
+ RNA_boolean_set(op->ptr, "snap_islands", ssc->snap_islands);
+ RNA_boolean_set(op->ptr, "midpoint_snap", ssc->midpoints);
+ RNA_boolean_set(op->ptr, "clear_seams", ssc->clear_seams);
+ RNA_enum_set(op->ptr, "mode", ssc->mode);
+ RNA_enum_set(op->ptr, "stored_mode", ssc->mode);
+ RNA_int_set(op->ptr, "active_object_index", ssc->active_object_index);
+
+ RNA_int_set(op->ptr, "static_island", ssc->static_island);
/* Store selection for re-execution of stitch */
+ /* WIP */
for (i = 0; i < state->selection_size; i++) {
UvElement *element;
PointerRNA itemptr;
- if (state->mode == STITCH_VERT) {
+ if (ssc->mode == STITCH_VERT) {
element = state->selection_stack[i];
}
else {
@@ -2083,7 +2307,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
RNA_collection_add(op->ptr, "selection", &itemptr);
RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
- RNA_int_set(&itemptr, "element_index", element->tfindex);
+ RNA_int_set(&itemptr, "element_index", element->loop_of_poly_index);
}
uvedit_live_unwrap_update(sima, scene, obedit);
@@ -2092,12 +2316,13 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
if (sa)
ED_workspace_status_text(C, NULL);
- ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
+ ED_region_draw_cb_exit(CTX_wm_region(C)->type, ssc->draw_handle);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- state_delete(state);
+ state_delete_all(ssc);
+
op->customdata = NULL;
}
@@ -2112,9 +2337,9 @@ static int stitch_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- if (!stitch_init(C, op))
+ if (!stitch_init_all(C, op))
return OPERATOR_CANCELLED;
- if (stitch_process_data((StitchState *)op->customdata, scene, 1)) {
+ if (stitch_process_data_all((StitchStateContainer *)op->customdata, scene, 1)) {
stitch_exit(C, op, 1);
return OPERATOR_FINISHED;
}
@@ -2124,7 +2349,8 @@ static int stitch_exec(bContext *C, wmOperator *op)
}
}
-static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, StitchState *state)
+static StitchState *stitch_select(
+ bContext *C, Scene *scene, const wmEvent *event, StitchStateContainer *ssc)
{
/* add uv under mouse to processed uv's */
float co[2];
@@ -2134,36 +2360,60 @@ static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, Stitc
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
- if (state->mode == STITCH_VERT) {
- if (uv_find_nearest_vert(
- scene, ima, state->obedit, co, 0.0f, &hit))
+ if (ssc->mode == STITCH_VERT) {
+ if (uv_find_nearest_vert_multi(
+ scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit))
{
/* Add vertex to selection, deselect all common uv's of vert other
* than selected and update the preview. This behavior was decided so that
* you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
+ /* find StitchState from hit->ob */
+ StitchState *state = NULL;
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (hit.ob == ssc->objects[ob_index]) {
+ state = ssc->states[ob_index];
+ break;
+ }
+ }
+
/* This works due to setting of tmp in find nearest uv vert */
UvElement *element = BM_uv_element_get(state->element_map, hit.efa, hit.l);
stitch_select_uv(element, state, false);
+ return state;
}
}
else {
- if (uv_find_nearest_edge(
- scene, ima, state->obedit, co, &hit))
+ if (uv_find_nearest_edge_multi(
+ scene, ima, ssc->objects, ssc->objects_len, co, &hit))
{
+ /* find StitchState from hit->ob */
+ StitchState *state = NULL;
+ for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
+ if (hit.ob == ssc->objects[ob_index]) {
+ state = ssc->states[ob_index];
+ break;
+ }
+ }
+
UvEdge *edge = uv_edge_get(hit.l, state);
stitch_select_edge(edge, state, false);
+
+ return state;
}
}
+
+ return NULL;
}
static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- StitchState *state;
+ StitchStateContainer *ssc;
Scene *scene = CTX_data_scene(C);
- state = (StitchState *)op->customdata;
+ ssc = op->customdata;
+ StitchState *active_state = ssc->states[ssc->active_object_index];
switch (event->type) {
case MIDDLEMOUSE:
@@ -2177,9 +2427,9 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
if (event->shift && (U.flag & USER_LMOUSESELECT)) {
if (event->val == KM_PRESS) {
- stitch_select(C, scene, event, state);
+ StitchState *selected_state = stitch_select(C, scene, event, ssc);
- if (!stitch_process_data(state, scene, false)) {
+ if (selected_state && !stitch_process_data(ssc, selected_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2190,7 +2440,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADENTER:
case RETKEY:
if (event->val == KM_PRESS) {
- if (stitch_process_data(state, scene, true)) {
+ if (stitch_process_data(ssc, active_state, scene, true)) {
stitch_exit(C, op, 1);
return OPERATOR_FINISHED;
}
@@ -2206,8 +2456,8 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADPLUSKEY:
case WHEELUPMOUSE:
if (event->val == KM_PRESS && event->alt) {
- state->limit_dist += 0.01f;
- if (!stitch_process_data(state, scene, false)) {
+ ssc->limit_dist += 0.01f;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2220,9 +2470,9 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PADMINUS:
case WHEELDOWNMOUSE:
if (event->val == KM_PRESS && event->alt) {
- state->limit_dist -= 0.01f;
- state->limit_dist = MAX2(0.01f, state->limit_dist);
- if (!stitch_process_data(state, scene, false)) {
+ ssc->limit_dist -= 0.01f;
+ ssc->limit_dist = MAX2(0.01f, ssc->limit_dist);
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2235,8 +2485,8 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Use Limit (Default off) */
case LKEY:
if (event->val == KM_PRESS) {
- state->use_limit = !state->use_limit;
- if (!stitch_process_data(state, scene, false)) {
+ ssc->use_limit = !ssc->use_limit;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2246,12 +2496,23 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case IKEY:
if (event->val == KM_PRESS) {
- state->static_island++;
- state->static_island %= state->element_map->totalIslands;
+ /* Move to next island and maybe next object */
- if (!stitch_process_data(state, scene, false)) {
- stitch_cancel(C, op);
- return OPERATOR_CANCELLED;
+ if (goto_next_island(ssc)) {
+ StitchState *new_active_state = ssc->states[ssc->active_object_index];
+
+ /* active_state is the origional active state */
+ if (active_state != new_active_state) {
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!stitch_process_data(ssc, new_active_state, scene, false)) {
+ stitch_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
}
break;
}
@@ -2259,8 +2520,8 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MKEY:
if (event->val == KM_PRESS) {
- state->midpoints = !state->midpoints;
- if (!stitch_process_data(state, scene, false)) {
+ ssc->midpoints = !ssc->midpoints;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2274,9 +2535,9 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
if (event->val == KM_PRESS && !(U.flag & USER_LMOUSESELECT)) {
- stitch_select(C, scene, event, state);
+ StitchState *selected_state = stitch_select(C, scene, event, ssc);
- if (!stitch_process_data(state, scene, false)) {
+ if (selected_state && !stitch_process_data(ssc, selected_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2287,8 +2548,8 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* snap islands on/off */
case SKEY:
if (event->val == KM_PRESS) {
- state->snap_islands = !state->snap_islands;
- if (!stitch_process_data(state, scene, false)) {
+ ssc->snap_islands = !ssc->snap_islands;
+ if (!stitch_process_data(ssc, active_state, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2301,9 +2562,9 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* switch between edge/vertex mode */
case TABKEY:
if (event->val == KM_PRESS) {
- stitch_switch_selection_mode(state);
+ stitch_switch_selection_mode_all(ssc);
- if (!stitch_process_data(state, scene, false)) {
+ if (!stitch_process_data_all(ssc, scene, false)) {
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -2315,8 +2576,9 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* if updated settings, renew feedback message */
- stitch_update_header(state, C);
+ stitch_update_header(ssc, C);
ED_region_tag_redraw(CTX_wm_region(C));
+
return OPERATOR_RUNNING_MODAL;
}
@@ -2352,14 +2614,16 @@ void UV_OT_stitch(wmOperatorType *ot)
"Limit distance in normalized coordinates", 0.0, FLT_MAX);
RNA_def_int(ot->srna, "static_island", 0, 0, INT_MAX, "Static Island",
"Island that stays in place when stitching islands", 0, INT_MAX);
+ RNA_def_int(ot->srna, "active_object_index", 0, 0, INT_MAX, "Active Object",
+ "Index of the active object", 0, INT_MAX);
RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint",
"UVs are stitched at midpoint instead of at static island");
RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams",
"Clear seams of stitched edges");
RNA_def_enum(ot->srna, "mode", stitch_modes, STITCH_VERT, "Operation Mode",
"Use vertex or edge stitching");
- prop = RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
- "Use vertex or edge stitching");
+ prop = RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
+ "Use vertex or edge stitching");
RNA_def_property_flag(prop, PROP_HIDDEN);
prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
/* Selection should not be editable or viewed in toolbar */
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
new file mode 100644
index 00000000000..5ad91d4e01b
--- /dev/null
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -0,0 +1,70 @@
+# ***** 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) 2018, Blender Foundation
+# All rights reserved.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+ ../blenkernel
+ ../blenlib
+ ../blenfont
+ ../depsgraph
+ ../makesdna
+ ../makesrna
+ ../bmesh
+ ../render/extern/include
+ ../../../intern/elbeem/extern
+ ../../../intern/guardedalloc
+ ../../../intern/eigen
+)
+
+set(INC_SYS
+ ${ZLIB_INCLUDE_DIRS}
+)
+
+set(SRC
+ intern/MOD_gpencil_util.h
+
+ intern/MOD_gpencil_util.c
+ intern/MOD_gpencilnoise.c
+ intern/MOD_gpencilsubdiv.c
+ intern/MOD_gpencilsimplify.c
+ intern/MOD_gpencilthick.c
+ intern/MOD_gpenciltint.c
+ intern/MOD_gpencilcolor.c
+ intern/MOD_gpencilinstance.c
+ intern/MOD_gpencilbuild.c
+ intern/MOD_gpencilopacity.c
+ intern/MOD_gpencillattice.c
+ intern/MOD_gpencilmirror.c
+ intern/MOD_gpencilsmooth.c
+ intern/MOD_gpencilhook.c
+ intern/MOD_gpenciloffset.c
+
+ MOD_gpencil_modifiertypes.h
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_gpencil_modifiers "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
new file mode 100644
index 00000000000..73386601d10
--- /dev/null
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -0,0 +1,51 @@
+/*
+ * ***** 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 MOD_gpencil_modifiertypes.h
+ * \ingroup modifiers
+ */
+
+#ifndef __MOD_GPENCIL_MODIFIERTYPES_H__
+#define __MOD_GPENCIL_MODIFIERTYPES_H__
+
+#include "BKE_gpencil_modifier.h"
+
+/* ****************** Type structures for all modifiers ****************** */
+
+extern GpencilModifierTypeInfo modifierType_Gpencil_None;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Noise;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Subdiv;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Simplify;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Thick;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Tint;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Color;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Instance;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Build;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Opacity;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Lattice;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Mirror;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Smooth;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Hook;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Offset;
+
+/* MOD_gpencil_util.c */
+void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
+
+#endif /* __MOD_GPENCIL_MODIFIERTYPES_H__ */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
new file mode 100644
index 00000000000..151218c06e4
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -0,0 +1,189 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+ * \ingroup bke
+ */
+
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_math_color.h"
+#include "BLI_rand.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_lattice.h"
+#include "BKE_material.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_colortools.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+#include "MOD_gpencil_util.h"
+
+void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
+{
+#define INIT_GP_TYPE(typeName) (types[eGpencilModifierType_##typeName] = &modifierType_Gpencil_##typeName)
+ INIT_GP_TYPE(Noise);
+ INIT_GP_TYPE(Subdiv);
+ INIT_GP_TYPE(Simplify);
+ INIT_GP_TYPE(Thick);
+ INIT_GP_TYPE(Tint);
+ INIT_GP_TYPE(Color);
+ INIT_GP_TYPE(Instance);
+ INIT_GP_TYPE(Build);
+ INIT_GP_TYPE(Opacity);
+ INIT_GP_TYPE(Lattice);
+ INIT_GP_TYPE(Mirror);
+ INIT_GP_TYPE(Smooth);
+ INIT_GP_TYPE(Hook);
+ INIT_GP_TYPE(Offset);
+#undef INIT_GP_TYPE
+}
+
+/* verify if valid layer and pass index */
+bool is_stroke_affected_by_modifier(
+ Object *ob, char *mlayername, int mpassindex, int minpoints,
+ bGPDlayer *gpl, bGPDstroke *gps, bool inv1, bool inv2)
+{
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* omit if filter by layer */
+ if (mlayername[0] != '\0') {
+ if (inv1 == false) {
+ if (!STREQ(mlayername, gpl->info)) {
+ return false;
+ }
+ }
+ else {
+ if (STREQ(mlayername, gpl->info)) {
+ return false;
+ }
+ }
+ }
+ /* verify pass */
+ if (mpassindex > 0) {
+ if (inv2 == false) {
+ if (gp_style->index != mpassindex) {
+ return false;
+ }
+ }
+ else {
+ if (gp_style->index == mpassindex) {
+ return false;
+ }
+ }
+ }
+ /* need to have a minimum number of points */
+ if ((minpoints > 0) && (gps->totpoints < minpoints)) {
+ return false;
+ }
+
+ return true;
+}
+
+/* verify if valid vertex group *and return weight */
+float get_modifier_point_weight(MDeformVert *dvert, int inverse, int vindex)
+{
+ float weight = 1.0f;
+
+ if (vindex >= 0) {
+ weight = BKE_gpencil_vgroup_use_index(dvert, vindex);
+ if ((weight >= 0.0f) && (inverse == 1)) {
+ return -1.0f;
+ }
+
+ if ((weight < 0.0f) && (inverse == 0)) {
+ return -1.0f;
+ }
+
+ /* if inverse, weight is always 1 */
+ if ((weight < 0.0f) && (inverse == 1)) {
+ return 1.0f;
+ }
+
+ }
+
+ return weight;
+}
+
+/* set material when apply modifiers (used in tint and color modifier) */
+void gpencil_apply_modifier_material(
+ Main *bmain, Object *ob, Material *mat,
+ GHash *gh_color, bGPDstroke *gps, bool crt_material)
+{
+ MaterialGPencilStyle *gp_style = mat->gp_style;
+
+ /* look for color */
+ if (crt_material) {
+ Material *newmat = BLI_ghash_lookup(gh_color, mat->id.name);
+ if (newmat == NULL) {
+ BKE_object_material_slot_add(bmain, ob);
+ newmat = BKE_material_copy(bmain, mat);
+ newmat->preview = NULL;
+
+ assign_material(bmain, ob, newmat, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+
+ copy_v4_v4(newmat->gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
+ copy_v4_v4(newmat->gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
+
+ BLI_ghash_insert(gh_color, mat->id.name, newmat);
+ DEG_id_tag_update(&newmat->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ /* reasign color index */
+ int idx = BKE_gpencil_get_material_index(ob, newmat);
+ gps->mat_nr = idx - 1;
+ }
+ else {
+ /* reuse existing color (but update only first time) */
+ if (BLI_ghash_lookup(gh_color, mat->id.name) == NULL) {
+ copy_v4_v4(gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
+ copy_v4_v4(gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
+ BLI_ghash_insert(gh_color, mat->id.name, mat);
+ }
+ /* update previews (icon and thumbnail) */
+ if (mat->preview != NULL) {
+ mat->preview->flag[ICON_SIZE_ICON] |= PRV_CHANGED;
+ mat->preview->flag[ICON_SIZE_PREVIEW] |= PRV_CHANGED;
+ }
+ DEG_id_tag_update(&mat->id, DEG_TAG_COPY_ON_WRITE);
+ }
+}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
new file mode 100644
index 00000000000..1ca9febbdca
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
@@ -0,0 +1,54 @@
+/*
+ * ***** 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) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencil_util.h
+ * \ingroup modifiers
+ */
+
+
+#ifndef __MOD_GPENCIL_UTIL_H__
+#define __MOD_GPENCIL_UTIL_H__
+
+struct Main;
+struct Object;
+struct bGPDlayer;
+struct bGPDstroke;
+struct MDeformVert;
+struct Material;
+struct GHash;
+
+bool is_stroke_affected_by_modifier(
+ struct Object *ob, char *mlayername, int mpassindex, int minpoints,
+ bGPDlayer *gpl, bGPDstroke *gps, bool inv1, bool inv2);
+
+float get_modifier_point_weight(struct MDeformVert *dvert, int inverse, int vindex);
+
+void gpencil_apply_modifier_material(
+ struct Main *bmain, struct Object *ob, struct Material *mat,
+ struct GHash *gh_color, struct bGPDstroke *gps, bool crt_material);
+
+#endif /* __MOD_GPENCIL_UTIL_H__ */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
new file mode 100644
index 00000000000..945afec002d
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -0,0 +1,558 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ BuildGpencilModifierData *gpmd = (BuildGpencilModifierData *)md;
+
+ /* We deliberately set this range to the half the default
+ * frame-range to have an immediate effect ot suggest use-cases
+ */
+ gpmd->start_frame = 1;
+ gpmd->end_frame = 125;
+
+ /* Init default length of each build effect - Nothing special */
+ gpmd->start_delay = 0.0f;
+ gpmd->length = 100.0f;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+static bool dependsOnTime(GpencilModifierData *UNUSED(md))
+{
+ return true;
+}
+
+/* ******************************************** */
+/* Build Modifier - Stroke generation logic
+ *
+ * There are two modes for how the strokes are sequenced (at a macro-level):
+ * - Sequential Mode - Strokes appear/disappear one after the other. Only a single one changes at a time.
+ * - Concurrent Mode - Multiple strokes appear/disappear at once.
+ *
+ * Assumptions:
+ * - Stroke points are generally equally spaced. This implies that we can just add/remove points,
+ * without worrying about distances between them / adding extra interpolated points between
+ * an visible point and one about to be added/removed (or any similar tapering effects).
+
+ * - All strokes present are fully visible (i.e. we don't have to ignore any)
+ */
+
+/* Remove a particular stroke */
+static void clear_stroke(bGPDframe *gpf, bGPDstroke *gps)
+{
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
+}
+
+/* Clear all strokes in frame */
+static void gpf_clear_all_strokes(bGPDframe *gpf)
+{
+ bGPDstroke *gps, *gps_next;
+ for (gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+ clear_stroke(gpf, gps);
+ }
+ BLI_listbase_clear(&gpf->strokes);
+}
+
+/* Reduce the number of points in the stroke
+ *
+ * Note: This won't be called if all points are present/removed
+ * TODO: Allow blending of growing/shrinking tip (e.g. for more gradual transitions)
+ */
+static void reduce_stroke_points(bGPDstroke *gps, const int num_points, const eBuildGpencil_Transition transition)
+{
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__);
+ MDeformVert *new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__);
+
+ /* Which end should points be removed from */
+ // TODO: free stroke weights
+ switch (transition) {
+ case GP_BUILD_TRANSITION_GROW: /* Show in forward order = Remove ungrown-points from end of stroke */
+ case GP_BUILD_TRANSITION_SHRINK: /* Hide in reverse order = Remove dead-points from end of stroke */
+ {
+ /* copy over point data */
+ memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points);
+ memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points);
+
+ /* free unused point weights */
+ for (int i = num_points; i < gps->totpoints; i++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ BKE_gpencil_free_point_weights(dvert);
+ }
+
+ break;
+ }
+
+ /* Hide in forward order = Remove points from start of stroke */
+ case GP_BUILD_TRANSITION_FADE:
+ {
+ /* num_points is the number of points left after reducing.
+ * We need to know how many to remove
+ */
+ const int offset = gps->totpoints - num_points;
+
+ /* copy over point data */
+ memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points);
+ memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points);
+
+ /* free unused weights */
+ for (int i = 0; i < offset; i++) {
+ MDeformVert *dvert = &gps->dvert[i];
+ BKE_gpencil_free_point_weights(dvert);
+ }
+
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__);
+ break;
+ }
+
+ /* replace stroke geometry */
+ MEM_SAFE_FREE(gps->points);
+ MEM_SAFE_FREE(gps->dvert);
+ gps->points = new_points;
+ gps->dvert = new_dvert;
+ gps->totpoints = num_points;
+
+ /* mark stroke as needing to have its geometry caches rebuilt */
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
+ MEM_SAFE_FREE(gps->triangles);
+}
+
+/* --------------------------------------------- */
+
+/* Stroke Data Table Entry - This represents one stroke being generated */
+typedef struct tStrokeBuildDetails {
+ bGPDstroke *gps;
+
+ /* Indices - first/last indices for the stroke's points (overall) */
+ size_t start_idx, end_idx;
+
+ /* Number of points - Cache for more convenient access */
+ int totpoints;
+} tStrokeBuildDetails;
+
+
+/* Sequential - Show strokes one after the other */
+static void build_sequential(BuildGpencilModifierData *mmd, bGPDframe *gpf, float fac)
+{
+ const size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
+ bGPDstroke *gps;
+ size_t i;
+
+ /* 1) Compute proportion of time each stroke should occupy */
+ /* NOTE: This assumes that the total number of points won't overflow! */
+ tStrokeBuildDetails *table = MEM_callocN(sizeof(tStrokeBuildDetails) * tot_strokes, __func__);
+ size_t totpoints = 0;
+
+ /* 1.1) First pass - Tally up points */
+ for (gps = gpf->strokes.first, i = 0; gps; gps = gps->next, i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ cell->gps = gps;
+ cell->totpoints = gps->totpoints;
+
+ totpoints += cell->totpoints;
+ }
+
+ /* 1.2) Second pass - Compute the overall indices for points */
+ for (i = 0; i < tot_strokes; i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ if (i == 0) {
+ cell->start_idx = 0;
+ }
+ else {
+ cell->start_idx = (cell - 1)->end_idx;
+ }
+ cell->end_idx = cell->start_idx + cell->totpoints - 1;
+ }
+
+
+ /* 2) Determine the global indices for points that should be visible */
+ size_t first_visible = 0;
+ size_t last_visible = 0;
+
+ switch (mmd->transition) {
+ /* Show in forward order
+ * - As fac increases, the number of visible points increases
+ */
+ case GP_BUILD_TRANSITION_GROW:
+ first_visible = 0; /* always visible */
+ last_visible = (size_t)roundf(totpoints * fac);
+ break;
+
+ /* Hide in reverse order
+ * - As fac increases, the number of points visible at the end decreases
+ */
+ case GP_BUILD_TRANSITION_SHRINK:
+ first_visible = 0; /* always visible (until last point removed) */
+ last_visible = (size_t)(totpoints * (1.0f - fac));
+ break;
+
+ /* Hide in forward order
+ * - As fac increases, the early points start getting hidden
+ */
+ case GP_BUILD_TRANSITION_FADE:
+ first_visible = (size_t)(totpoints * fac);
+ last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
+ break;
+ }
+
+
+ /* 3) Go through all strokes, deciding which to keep, and/or how much of each to keep */
+ for (i = 0; i < tot_strokes; i++) {
+ tStrokeBuildDetails *cell = &table[i];
+
+ /* Determine what portion of the stroke is visible */
+ if ((cell->end_idx < first_visible) || (cell->start_idx > last_visible)) {
+ /* Not visible at all - Either ended before */
+ clear_stroke(gpf, cell->gps);
+ }
+ else {
+ /* Some proportion of stroke is visible */
+ /* XXX: Will the transition settings still be valid now? */
+ if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) {
+ /* Do nothing - whole stroke is visible */
+ }
+ else if (first_visible > cell->start_idx) {
+ /* Starts partway through this stroke */
+ int num_points = cell->end_idx - first_visible;
+ reduce_stroke_points(cell->gps, num_points, mmd->transition);
+ }
+ else {
+ /* Ends partway through this stroke */
+ int num_points = last_visible - cell->start_idx;
+ reduce_stroke_points(cell->gps, num_points, mmd->transition);
+ }
+ }
+ }
+
+ /* Free table */
+ MEM_freeN(table);
+}
+
+/* --------------------------------------------- */
+
+/* Concurrent - Show multiple strokes at once */
+// TODO: Allow random offsets to start times
+// TODO: Allow varying speeds? Scaling of progress?
+static void build_concurrent(BuildGpencilModifierData *mmd, bGPDframe *gpf, float fac)
+{
+ bGPDstroke *gps, *gps_next;
+ int max_points = 0;
+
+ const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
+
+ /* 1) Determine the longest stroke, to figure out when short strokes should start */
+ /* FIXME: A *really* long stroke here could dwarf everything else, causing bad timings */
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (gps->totpoints > max_points) {
+ max_points = gps->totpoints;
+ }
+ }
+ if (max_points == 0) {
+ printf("ERROR: Strokes are all empty (GP Build Modifier: %s)\n", __func__);
+ return;
+ }
+
+ /* 2) For each stroke, determine how it should be handled */
+ for (gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+
+ /* Relative Length of Stroke - Relative to the longest stroke,
+ * what proportion of the available time should this stroke use
+ */
+ const float relative_len = (float)gps->totpoints / (float)max_points;
+
+ /* Determine how many points should be left in the stroke */
+ int num_points = 0;
+
+ switch (mmd->time_alignment) {
+ case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */
+ {
+ /* Build effect occurs over when fac = 0, to fac = relative_len */
+ if (fac <= relative_len) {
+ /* Scale fac to fit relative_len */
+ /* FIXME: prevent potential div by zero (e.g. very short stroke vs one very long one) */
+ const float scaled_fac = fac / relative_len;
+
+ if (reverse) {
+ num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
+ }
+ else {
+ num_points = (int)roundf(scaled_fac * gps->totpoints);
+ }
+ }
+ else {
+ /* Build effect has ended */
+ if (reverse) {
+ num_points = 0;
+ }
+ else {
+ num_points = gps->totpoints;
+ }
+ }
+
+ break;
+ }
+ case GP_BUILD_TIMEALIGN_END: /* all end on same frame */
+ {
+ /* Build effect occurs over 1.0 - relative_len, to 1.0 (i.e. over the end of the range) */
+ const float start_fac = 1.0f - relative_len;
+
+ if (fac >= start_fac) {
+ /* FIXME: prevent potential div by zero (e.g. very short stroke vs one very long one) */
+ const float scaled_fac = (fac - start_fac) / relative_len;
+
+ if (reverse) {
+ num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
+ }
+ else {
+ num_points = (int)roundf(scaled_fac * gps->totpoints);
+ }
+ }
+ else {
+ /* Build effect hasn't started */
+ if (reverse) {
+ num_points = gps->totpoints;
+ }
+ else {
+ num_points = 0;
+ }
+ }
+
+ break;
+ }
+
+ /* TODO... */
+ }
+
+ /* Modify the stroke geometry */
+ if (num_points <= 0) {
+ /* Nothing Left - Delete the stroke */
+ clear_stroke(gpf, gps);
+ }
+ else if (num_points < gps->totpoints) {
+ /* Remove some points */
+ reduce_stroke_points(gps, num_points, mmd->transition);
+ }
+ }
+}
+
+/* --------------------------------------------- */
+
+/* Entry-point for Build Modifier */
+static void generateStrokes(
+ GpencilModifierData *md, Depsgraph *depsgraph,
+ Object *UNUSED(ob), bGPDlayer *gpl, bGPDframe *gpf)
+{
+ BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
+ const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
+
+ const float ctime = DEG_get_ctime(depsgraph);
+ //printf("GP Build Modifier - %f\n", ctime);
+
+ /* Early exit if it's an empty frame */
+ if (gpf->strokes.first == NULL) {
+ return;
+ }
+
+ /* Omit layer if filter by layer */
+ if (mmd->layername[0] != '\0') {
+ if ((mmd->flag & GP_BUILD_INVERT_LAYER) == 0) {
+ if (!STREQ(mmd->layername, gpl->info)) {
+ return;
+ }
+ }
+ else {
+ if (STREQ(mmd->layername, gpl->info)) {
+ return;
+ }
+ }
+ }
+
+ /* Early exit if outside of the frame range for this modifier
+ * (e.g. to have one forward, and one backwards modifier)
+ */
+ if (mmd->flag & GP_BUILD_RESTRICT_TIME) {
+ if ((ctime < mmd->start_frame) || (ctime > mmd->end_frame)) {
+ return;
+ }
+ }
+
+ /* Compute start and end frames for the animation effect
+ * By default, the upper bound is given by the "maximum length" setting
+ */
+ float start_frame = gpf->framenum + mmd->start_delay;
+ float end_frame = gpf->framenum + mmd->length;
+
+ if (gpf->next) {
+ /* Use the next frame or upper bound as end frame, whichever is lower/closer */
+ end_frame = MIN2(end_frame, gpf->next->framenum);
+ }
+
+
+ /* Early exit if current frame is outside start/end bounds */
+ /* NOTE: If we're beyond the next/prev frames (if existent), then we wouldn't have this problem anyway... */
+ if (ctime < start_frame) {
+ /* Before Start - Animation hasn't started. Display initial state. */
+ if (reverse) {
+ /* 1) Reverse = Start with all, end with nothing.
+ * ==> Do nothing (everything already present)
+ */
+ }
+ else {
+ /* 2) Forward Order = Start with nothing, end with the full frame.
+ * ==> Free all strokes, and return an empty frame
+ */
+ gpf_clear_all_strokes(gpf);
+ }
+
+ /* Early exit */
+ return;
+ }
+ else if (ctime >= end_frame) {
+ /* Past End - Animation finished. Display final result. */
+ if (reverse) {
+ /* 1) Reverse = Start with all, end with nothing.
+ * ==> Free all strokes, and return an empty frame
+ */
+ gpf_clear_all_strokes(gpf);
+ }
+ else {
+ /* 2) Forward Order = Start with nothing, end with the full frame.
+ * ==> Do Nothing (everything already present)
+ */
+ }
+
+ /* Early exit */
+ return;
+ }
+
+
+ /* Determine how far along we are between the keyframes */
+ float fac = (ctime - start_frame) / (end_frame - start_frame);
+ //printf(" Progress on %d = %f (%f - %f)\n", gpf->framenum, fac, start_frame, end_frame);
+
+ /* Time management mode */
+ switch (mmd->mode) {
+ case GP_BUILD_MODE_SEQUENTIAL:
+ build_sequential(mmd, gpf, fac);
+ break;
+
+ case GP_BUILD_MODE_CONCURRENT:
+ build_concurrent(mmd, gpf, fac);
+ break;
+
+ default:
+ printf("Unsupported build mode (%d) for GP Build Modifier: '%s'\n", mmd->mode, mmd->modifier.name);
+ break;
+ }
+}
+
+/* ******************************************** */
+
+/* FIXME: Baking the Build Modifier is currently unsupported.
+ * Adding support for this is more complicated than for other
+ * modifiers, as to implement this, we'd have to add more frames,
+ * which would in turn break how the modifier functions.
+ */
+#if 0
+static void bakeModifier(
+ Main *bmain, const Depsgraph *UNUSED(depsgraph),
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+
+ }
+ }
+}
+#endif
+
+/* ******************************************** */
+
+GpencilModifierTypeInfo modifierType_Gpencil_Build = {
+ /* name */ "Build",
+ /* structName */ "BuildGpencilModifierData",
+ /* structSize */ sizeof(BuildGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ NULL,
+ /* generateStrokes */ generateStrokes,
+ /* bakeModifier */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
new file mode 100644
index 00000000000..0bbd26da670
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -0,0 +1,164 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math_color.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ ARRAY_SET_ITEMS(gpmd->hsv, 1.0f, 1.0f, 1.0f);
+ gpmd->layername[0] = '\0';
+ gpmd->flag |= GP_COLOR_CREATE_COLORS;
+ gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* color correction strokes */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+
+ ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
+ float hsv[3], factor[3];
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_COLOR_INVERT_LAYER, mmd->flag & GP_COLOR_INVERT_PASS))
+ {
+ return;
+ }
+
+ copy_v3_v3(factor, mmd->hsv);
+ add_v3_fl(factor, -1.0f);
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
+ rgb_to_hsv_v(gps->runtime.tmp_stroke_rgba, hsv);
+ add_v3_v3(hsv, factor);
+ CLAMP3(hsv, 0.0f, 1.0f);
+ hsv_to_rgb_v(hsv, gps->runtime.tmp_stroke_rgba);
+ }
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ rgb_to_hsv_v(gps->runtime.tmp_fill_rgba, hsv);
+ add_v3_v3(hsv, factor);
+ CLAMP3(hsv, 0.0f, 1.0f);
+ hsv_to_rgb_v(hsv, gps->runtime.tmp_fill_rgba);
+ }
+}
+
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
+ bGPdata *gpd = ob->data;
+
+ GHash *gh_color = BLI_ghash_str_new("GP_Color modifier");
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+
+ Material *mat = give_current_material(ob, gps->mat_nr + 1);
+ if (mat == NULL)
+ continue;
+ MaterialGPencilStyle *gp_style = mat->gp_style;
+ /* skip stroke if it doesn't have color info */
+ if (ELEM(NULL, gp_style))
+ continue;
+
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ deformStroke(md, depsgraph, ob, gpl, gps);
+
+ gpencil_apply_modifier_material(
+ bmain, ob, mat, gh_color, gps,
+ (bool)(mmd->flag & GP_COLOR_CREATE_COLORS));
+ }
+ }
+ }
+ /* free hash buffers */
+ if (gh_color) {
+ BLI_ghash_free(gh_color, NULL, NULL);
+ gh_color = NULL;
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Color = {
+ /* name */ "Hue/Saturation",
+ /* structName */ "ColorGpencilModifierData",
+ /* structSize */ sizeof(ColorGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
new file mode 100644
index 00000000000..46d452545e2
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -0,0 +1,355 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_modifier_types.h"
+#include "BLI_math.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_colortools.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_modifier.h"
+#include "BKE_library_query.h"
+#include "BKE_scene.h"
+#include "BKE_main.h"
+#include "BKE_layer.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+/* temp struct to hold data */
+struct GPHookData_cb {
+ struct CurveMapping *curfalloff;
+
+ char falloff_type;
+ float falloff;
+ float falloff_sq;
+ float fac_orig;
+
+ unsigned int use_falloff : 1;
+ unsigned int use_uniform : 1;
+
+ float cent[3];
+
+ float mat_uniform[3][3];
+ float mat[4][4];
+};
+
+static void initData(GpencilModifierData *md)
+{
+ HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->object = NULL;
+ gpmd->force = 0.5f;
+ gpmd->falloff_type = eGPHook_Falloff_Smooth;
+ gpmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curfalloff) {
+ curvemapping_initialize(gpmd->curfalloff);
+ }
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ HookGpencilModifierData *gmd = (HookGpencilModifierData *)md;
+ HookGpencilModifierData *tgmd = (HookGpencilModifierData *)target;
+
+ if (tgmd->curfalloff != NULL) {
+ curvemapping_free(tgmd->curfalloff);
+ tgmd->curfalloff = NULL;
+ }
+
+ BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curfalloff = curvemapping_copy(gmd->curfalloff);
+}
+
+/* calculate factor of fallof */
+static float gp_hook_falloff(const struct GPHookData_cb *tData, const float len_sq)
+{
+ BLI_assert(tData->falloff_sq);
+ if (len_sq > tData->falloff_sq) {
+ return 0.0f;
+ }
+ else if (len_sq > 0.0f) {
+ float fac;
+
+ if (tData->falloff_type == eGPHook_Falloff_Const) {
+ fac = 1.0f;
+ goto finally;
+ }
+ else if (tData->falloff_type == eGPHook_Falloff_InvSquare) {
+ /* avoid sqrt below */
+ fac = 1.0f - (len_sq / tData->falloff_sq);
+ goto finally;
+ }
+
+ fac = 1.0f - (sqrtf(len_sq) / tData->falloff);
+
+ switch (tData->falloff_type) {
+ case eGPHook_Falloff_Curve:
+ fac = curvemapping_evaluateF(tData->curfalloff, 0, fac);
+ break;
+ case eGPHook_Falloff_Sharp:
+ fac = fac * fac;
+ break;
+ case eGPHook_Falloff_Smooth:
+ fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
+ break;
+ case eGPHook_Falloff_Root:
+ fac = sqrtf(fac);
+ break;
+ case eGPHook_Falloff_Linear:
+ /* pass */
+ break;
+ case eGPHook_Falloff_Sphere:
+ fac = sqrtf(2 * fac - fac * fac);
+ break;
+ default:
+ fac = fac;
+ break;
+ }
+
+ finally:
+ return fac * tData->fac_orig;
+ }
+ else {
+ return tData->fac_orig;
+ }
+}
+
+/* apply point deformation */
+static void gp_hook_co_apply(struct GPHookData_cb *tData, float weight, bGPDspoint *pt)
+{
+ float fac;
+
+ if (tData->use_falloff) {
+ float len_sq;
+
+ if (tData->use_uniform) {
+ float co_uniform[3];
+ mul_v3_m3v3(co_uniform, tData->mat_uniform, &pt->x);
+ len_sq = len_squared_v3v3(tData->cent, co_uniform);
+ }
+ else {
+ len_sq = len_squared_v3v3(tData->cent, &pt->x);
+ }
+
+ fac = gp_hook_falloff(tData, len_sq);
+ }
+ else {
+ fac = tData->fac_orig;
+ }
+
+ if (fac) {
+ float co_tmp[3];
+ mul_v3_m4v3(co_tmp, tData->mat, &pt->x);
+ interp_v3_v3v3(&pt->x, &pt->x, co_tmp, fac * weight);
+ }
+}
+
+/* deform stroke */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ HookGpencilModifierData *mmd = (HookGpencilModifierData *)md;
+ if (!mmd->object) {
+ return;
+ }
+
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+ float weight = 1.0f;
+
+ bPoseChannel *pchan = BKE_pose_channel_find_name(mmd->object->pose, mmd->subtarget);
+ float dmat[4][4];
+ struct GPHookData_cb tData;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_HOOK_INVERT_LAYER, mmd->flag & GP_HOOK_INVERT_PASS))
+ {
+ return;
+ }
+
+ /* init struct */
+ tData.curfalloff = mmd->curfalloff;
+ tData.falloff_type = mmd->falloff_type;
+ tData.falloff = (mmd->falloff_type == eHook_Falloff_None) ? 0.0f : mmd->falloff;
+ tData.falloff_sq = SQUARE(tData.falloff);
+ tData.fac_orig = mmd->force;
+ tData.use_falloff = (tData.falloff_sq != 0.0f);
+ tData.use_uniform = (mmd->flag & GP_HOOK_UNIFORM_SPACE) != 0;
+
+ if (tData.use_uniform) {
+ copy_m3_m4(tData.mat_uniform, mmd->parentinv);
+ mul_v3_m3v3(tData.cent, tData.mat_uniform, mmd->cent);
+ }
+ else {
+ unit_m3(tData.mat_uniform);
+ copy_v3_v3(tData.cent, mmd->cent);
+ }
+
+ /* get world-space matrix of target, corrected for the space the verts are in */
+ if (mmd->subtarget[0] && pchan) {
+ /* bone target if there's a matching pose-channel */
+ mul_m4_m4m4(dmat, mmd->object->obmat, pchan->pose_mat);
+ }
+ else {
+ /* just object target */
+ copy_m4_m4(dmat, mmd->object->obmat);
+ }
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_series(tData.mat, ob->imat, dmat, mmd->parentinv);
+
+ /* loop points and apply deform */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ /* verify vertex group */
+ weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_HOOK_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+ gp_hook_co_apply(&tData, weight, pt);
+ }
+}
+
+/* FIXME: Ideally we be doing this on a copy of the main depsgraph
+ * (i.e. one where we don't have to worry about restoring state)
+ */
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ HookGpencilModifierData *mmd = (HookGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ if (mmd->object == NULL)
+ return;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* apply hook effects on this frame
+ * NOTE: this assumes that we don't want hook animation on non-keyframed frames
+ */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ /* compute hook effects on this frame */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ HookGpencilModifierData *mmd = (HookGpencilModifierData *)md;
+
+ if (mmd->curfalloff) {
+ curvemapping_free(mmd->curfalloff);
+ }
+}
+
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ HookGpencilModifierData *mmd = (HookGpencilModifierData *)md;
+
+ return !mmd->object;
+}
+
+static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ HookGpencilModifierData *lmd = (HookGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Hook Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
+}
+
+static void foreachObjectLink(
+ GpencilModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ HookGpencilModifierData *mmd = (HookGpencilModifierData *)md;
+
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Hook = {
+ /* name */ "Hook",
+ /* structName */ "HookGpencilModifierData",
+ /* structSize */ sizeof(HookGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c
new file mode 100644
index 00000000000..a35174d882f
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c
@@ -0,0 +1,360 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilinstance.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_layer.h"
+#include "BKE_collection.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ InstanceGpencilModifierData *gpmd = (InstanceGpencilModifierData *)md;
+ gpmd->count[0] = 1;
+ gpmd->count[1] = 1;
+ gpmd->count[2] = 1;
+ gpmd->offset[0] = 1.0f;
+ gpmd->offset[1] = 1.0f;
+ gpmd->offset[2] = 1.0f;
+ gpmd->shift[0] = 0.0f;
+ gpmd->shift[1] = 0.0f;
+ gpmd->shift[2] = 0.0f;
+ gpmd->scale[0] = 1.0f;
+ gpmd->scale[1] = 1.0f;
+ gpmd->scale[2] = 1.0f;
+ gpmd->rnd_rot = 0.5f;
+ gpmd->rnd_size = 0.5f;
+ gpmd->lock_axis |= GP_LOCKAXIS_X;
+ gpmd->flag |= GP_INSTANCE_MAKE_OBJECTS;
+
+ /* fill random values */
+ BLI_array_frand(gpmd->rnd, 20, 1);
+ gpmd->rnd[0] = 1;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* -------------------------------- */
+
+/* array modifier - generate geometry callback (for viewport/rendering) */
+/* TODO: How to skip this for the simplify options? --> !GP_SIMPLIFY_MODIF(ts, playing) */
+static void generate_geometry(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
+{
+ InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
+ ListBase stroke_cache = {NULL, NULL};
+ bGPDstroke *gps;
+ int idx;
+
+ /* Check which strokes we can use once, and store those results in an array
+ * for quicker checking of what's valid (since string comparisons are expensive)
+ */
+ const int num_strokes = BLI_listbase_count(&gpf->strokes);
+ int num_valid = 0;
+
+ bool *valid_strokes = MEM_callocN(sizeof(bool) * num_strokes, __func__);
+
+ for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) {
+ /* Record whether this stroke can be used
+ * ATTENTION: The logic here is the inverse of what's used everywhere else!
+ */
+ if (is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_INSTANCE_INVERT_LAYER, mmd->flag & GP_INSTANCE_INVERT_PASS))
+ {
+ valid_strokes[idx] = true;
+ num_valid++;
+ }
+ }
+
+ /* Early exit if no strokes can be copied */
+ if (num_valid == 0) {
+ if (G.debug & G_DEBUG) {
+ printf("GP Array Mod - No strokes to be included\n");
+ }
+
+ MEM_SAFE_FREE(valid_strokes);
+ return;
+ }
+
+
+ /* Generate new instances of all existing strokes,
+ * keeping each instance together so they maintain
+ * the correct ordering relative to each other
+ */
+ for (int x = 0; x < mmd->count[0]; x++) {
+ for (int y = 0; y < mmd->count[1]; y++) {
+ for (int z = 0; z < mmd->count[2]; z++) {
+ /* original strokes are at index = 0,0,0 */
+ if ((x == 0) && (y == 0) && (z == 0)) {
+ continue;
+ }
+
+ /* Compute transforms for this instance */
+ const int elem_idx[3] = {x, y, z};
+ float mat[4][4];
+
+ BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat);
+
+ /* apply shift */
+ int sh = x;
+ if (mmd->lock_axis == GP_LOCKAXIS_Y) {
+ sh = y;
+ }
+ if (mmd->lock_axis == GP_LOCKAXIS_Z) {
+ sh = z;
+ }
+ madd_v3_v3fl(mat[3], mmd->shift, sh);
+
+ /* Duplicate original strokes to create this instance */
+ for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) {
+ /* check if stroke can be duplicated */
+ if (valid_strokes[idx]) {
+ /* Duplicate stroke */
+ bGPDstroke *gps_dst = MEM_dupallocN(gps);
+ gps_dst->points = MEM_dupallocN(gps->points);
+ gps_dst->dvert = MEM_dupallocN(gps->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps, gps_dst);
+
+ gps_dst->triangles = MEM_dupallocN(gps->triangles);
+
+ /* Move points */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps_dst->points[i];
+ mul_m4_v3(mat, &pt->x);
+ }
+
+ /* Add new stroke to cache, to be added to the frame once
+ * all duplicates have been made
+ */
+ BLI_addtail(&stroke_cache, gps_dst);
+ }
+ }
+ }
+ }
+ }
+
+ /* merge newly created stroke instances back into the main stroke list */
+ BLI_movelisttolist(&gpf->strokes, &stroke_cache);
+
+ /* free temp data */
+ MEM_SAFE_FREE(valid_strokes);
+}
+
+/* bakeModifier - "Bake to Data" Mode */
+static void bakeModifierGP_strokes(
+ Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ generate_geometry(md, depsgraph, ob, gpl, gpf);
+ }
+ }
+}
+
+/* -------------------------------- */
+
+/* helper to create a new object */
+static Object *array_instance_add_ob_copy(Main *bmain, Scene *scene, Object *from_ob)
+{
+ Object *ob;
+
+ ob = BKE_object_copy(bmain, from_ob);
+ BKE_collection_object_add_from(bmain, scene, from_ob, ob);
+
+ zero_v3(ob->loc);
+ zero_v3(ob->rot);
+
+ DEG_id_type_tag(bmain, ID_OB);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, 0);
+
+ return ob;
+}
+
+/* bakeModifier - "Make Objects" Mode */
+static void bakeModifierGP_objects(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
+{
+ InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ /* reset random */
+ mmd->rnd[0] = 1;
+
+ /* generate instances as objects */
+ for (int x = 0; x < mmd->count[0]; x++) {
+ for (int y = 0; y < mmd->count[1]; y++) {
+ for (int z = 0; z < mmd->count[2]; z++) {
+ Object *newob;
+ GpencilModifierData *fmd;
+
+ const int elem_idx[3] = {x, y, z};
+ float mat[4][4], finalmat[4][4];
+ int sh;
+
+ /* original strokes are at index = 0,0,0 */
+ if ((x == 0) && (y == 0) && (z == 0)) {
+ continue;
+ }
+
+ /* compute transform for instance */
+ BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat);
+ mul_m4_m4m4(finalmat, ob->obmat, mat);
+
+ /* moves to new origin */
+ sh = x;
+ if (mmd->lock_axis == GP_LOCKAXIS_Y) {
+ sh = y;
+ }
+ if (mmd->lock_axis == GP_LOCKAXIS_Z) {
+ sh = z;
+ }
+ madd_v3_v3fl(finalmat[3], mmd->shift, sh);
+
+ /* Create a new object
+ *
+ * NOTE: Copies share the same original GP datablock
+ * Artists can later user make_single_user on these
+ * to make them unique (if necessary), without too
+ * much extra memory usage.
+ */
+ newob = array_instance_add_ob_copy(bmain, scene, ob);
+
+ /* remove array on destination object */
+ fmd = (GpencilModifierData *)BLI_findstring(&newob->greasepencil_modifiers, md->name, offsetof(GpencilModifierData, name));
+ if (fmd) {
+ BLI_remlink(&newob->greasepencil_modifiers, fmd);
+ BKE_gpencil_modifier_free(fmd);
+ }
+
+ /* copy transforms to destination object */
+ copy_m4_m4(newob->obmat, finalmat);
+
+ copy_v3_v3(newob->loc, finalmat[3]);
+ mat4_to_eul(newob->rot, finalmat);
+ mat4_to_size(newob->size, finalmat);
+ }
+ }
+ }
+}
+
+/* -------------------------------- */
+
+/* Generic "generateStrokes" callback */
+static void generateStrokes(
+ GpencilModifierData *md, Depsgraph *depsgraph,
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
+{
+ InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
+
+ /* When the "make_objects" flag is set, this modifier is handled as part of the
+ * draw engine instead. The main benefit is that the instances won't suffer from
+ * z-ordering problems.
+ *
+ * FIXME: Ultimately, the draw-engine hack here shouldn't be necessary, but until
+ * we find a better fix to the z-ordering problems, it's better to have
+ * working functionality
+ */
+ if ((mmd->flag & GP_INSTANCE_MAKE_OBJECTS) == 0) {
+ generate_geometry(md, depsgraph, ob, gpl, gpf);
+ }
+}
+
+/* Generic "bakeModifier" callback */
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md;
+
+ /* Create new objects or add all to current datablock.
+ * Sometimes it's useful to have the option to do either of these...
+ */
+ if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) {
+ bakeModifierGP_objects(bmain, depsgraph, md, ob);
+ }
+ else {
+ bakeModifierGP_strokes(depsgraph, md, ob);
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Instance = {
+ /* name */ "Instance",
+ /* structName */ "InstanceGpencilModifierData",
+ /* structSize */ sizeof(InstanceGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ NULL,
+ /* generateStrokes */ generateStrokes,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
new file mode 100644
index 00000000000..33bdb9c861d
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -0,0 +1,213 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_modifier.h"
+#include "BKE_lattice.h"
+#include "BKE_library_query.h"
+#include "BKE_scene.h"
+#include "BKE_main.h"
+#include "BKE_layer.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+static void initData(GpencilModifierData *md)
+{
+ LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->object = NULL;
+ gpmd->cache_data = NULL;
+ gpmd->strength = 1.0f;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+ float weight = 1.0f;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_LATTICE_INVERT_LAYER, mmd->flag & GP_LATTICE_INVERT_PASS))
+ {
+ return;
+ }
+
+ if (mmd->cache_data == NULL) {
+ return;
+ }
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ /* verify vertex group */
+ weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_LATTICE_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+
+ calc_latt_deform((struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
+ }
+}
+
+/* FIXME: Ideally we be doing this on a copy of the main depsgraph
+ * (i.e. one where we don't have to worry about restoring state)
+ */
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ struct LatticeDeformData *ldata = NULL;
+ bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ if (mmd->object == NULL)
+ return;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* apply lattice effects on this frame
+ * NOTE: this assumes that we don't want lattice animation on non-keyframed frames
+ */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ /* recalculate lattice data */
+ BKE_gpencil_lattice_init(ob);
+
+ /* compute lattice effects on this frame */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+
+ /* free lingering data */
+ ldata = (struct LatticeDeformData *)mmd->cache_data;
+ if (ldata) {
+ end_latt_deform(ldata);
+ mmd->cache_data = NULL;
+ }
+
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ struct LatticeDeformData *ldata = (struct LatticeDeformData *)mmd->cache_data;
+ /* free deform data */
+ if (ldata) {
+ end_latt_deform(ldata);
+ }
+}
+
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+
+ return !mmd->object;
+}
+
+static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ LatticeGpencilModifierData *lmd = (LatticeGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Lattice Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
+}
+
+static void foreachObjectLink(
+ GpencilModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Lattice = {
+ /* name */ "Lattice",
+ /* structName */ "LatticeGpencilModifierData",
+ /* structSize */ sizeof(LatticeGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_Single | eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
new file mode 100644
index 00000000000..4c359be670f
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -0,0 +1,210 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_modifier.h"
+#include "BKE_library_query.h"
+#include "BKE_scene.h"
+#include "BKE_main.h"
+#include "BKE_layer.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+static void initData(GpencilModifierData *md)
+{
+ MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->object = NULL;
+ gpmd->flag |= GP_MIRROR_AXIS_X;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+static void update_position(Object *ob, MirrorGpencilModifierData *mmd, bGPDstroke *gps, int axis)
+{
+ int i;
+ bGPDspoint *pt;
+ float factor[3] = { 1.0f, 1.0f, 1.0f };
+ factor[axis] = -1.0f;
+
+ float clear[3] = { 0.0f, 0.0f, 0.0f };
+ clear[axis] = 1.0f;
+
+ float origin[3];
+ float mirror_origin[3];
+
+ copy_v3_v3(origin, ob->loc);
+ /* only works with current axis */
+ mul_v3_v3(origin, clear);
+ zero_v3(mirror_origin);
+
+ if (mmd->object) {
+ copy_v3_v3(mirror_origin, mmd->object->loc);
+ mul_v3_v3(mirror_origin, clear);
+ sub_v3_v3(origin, mirror_origin);
+ }
+ /* clear other axis */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ add_v3_v3(&pt->x, origin);
+ mul_v3_v3(&pt->x, factor);
+ add_v3_v3(&pt->x, mirror_origin);
+ }
+
+}
+
+/* Generic "generateStrokes" callback */
+static void generateStrokes(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
+{
+ MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
+ bGPDstroke *gps, *gps_new = NULL;
+ int tot_strokes;
+ int i;
+
+ /* check each axis for mirroring */
+ for (int xi = 0; xi < 3; ++xi) {
+ if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
+
+ /* count strokes to avoid infinite loop after adding new strokes to tail of listbase */
+ tot_strokes = BLI_listbase_count(&gpf->strokes);
+
+ for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) {
+ if (is_stroke_affected_by_modifier(
+ ob, mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_MIRROR_INVERT_LAYER, mmd->flag & GP_MIRROR_INVERT_PASS))
+ {
+ gps_new = BKE_gpencil_stroke_duplicate(gps);
+ update_position(ob, mmd, gps_new, xi);
+ BLI_addtail(&gpf->strokes, gps_new);
+ }
+ }
+ }
+ }
+}
+
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* apply mirror effects on this frame */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ /* compute mirror effects on this frame */
+ generateStrokes(md, depsgraph, ob, gpl, gpf);
+ }
+ }
+
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+}
+
+static bool isDisabled(GpencilModifierData *UNUSED(md), int UNUSED(userRenderParams))
+{
+ //MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
+
+ return false;
+}
+
+static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ MirrorGpencilModifierData *lmd = (MirrorGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Mirror Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
+}
+
+static void foreachObjectLink(
+ GpencilModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
+
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
+ /* name */ "Mirror",
+ /* structName */ "MirrorGpencilModifierData",
+ /* structSize */ sizeof(MirrorGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ NULL,
+ /* generateStrokes */ generateStrokes,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
new file mode 100644
index 00000000000..be361498578
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -0,0 +1,285 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_rand.h"
+
+#include "PIL_time.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_object.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->flag |= GP_NOISE_MOD_LOCATION;
+ gpmd->flag |= GP_NOISE_FULL_STROKE;
+ gpmd->flag |= GP_NOISE_USE_RANDOM;
+ gpmd->factor = 0.5f;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->step = 1;
+ gpmd->scene_frame = -999999;
+ gpmd->gp_frame = -999999;
+
+ gpmd->vrand1 = 1.0;
+ gpmd->vrand2 = 1.0;
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
+
+ if (mmd->rng != NULL) {
+ BLI_rng_free(mmd->rng);
+ }
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+static bool dependsOnTime(GpencilModifierData *md)
+{
+ NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
+ return (mmd->flag & GP_NOISE_USE_RANDOM) != 0;
+}
+
+/* aply noise effect based on stroke direction */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *depsgraph,
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
+ bGPDspoint *pt0, *pt1;
+ MDeformVert *dvert;
+ float shift, vran, vdir;
+ float normal[3];
+ float vec1[3], vec2[3];
+#if 0
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+#endif
+ int sc_frame = 0;
+ int sc_diff = 0;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+ float weight = 1.0f;
+
+ /* Random generator, only init once. */
+ if (mmd->rng == NULL) {
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(mmd);
+ mmd->rng = BLI_rng_new(rng_seed);
+ }
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_NOISE_INVERT_LAYER, mmd->flag & GP_NOISE_INVERT_PASS))
+ {
+ return;
+ }
+
+ sc_frame = (int)DEG_get_ctime(depsgraph);
+
+ zero_v3(vec2);
+
+ /* calculate stroke normal*/
+ BKE_gpencil_stroke_normal(gps, normal);
+
+ /* move points */
+ for (int i = 0; i < gps->totpoints; i++) {
+ if (((i == 0) || (i == gps->totpoints - 1)) && ((mmd->flag & GP_NOISE_MOVE_EXTREME) == 0)) {
+ continue;
+ }
+
+ /* last point is special */
+ if (i == gps->totpoints) {
+ dvert = &gps->dvert[i - 2];
+ pt0 = &gps->points[i - 2];
+ pt1 = &gps->points[i - 1];
+ }
+ else {
+ dvert = &gps->dvert[i - 1];
+ pt0 = &gps->points[i - 1];
+ pt1 = &gps->points[i];
+
+ }
+
+ /* verify vertex group */
+ weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_NOISE_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+
+ /* initial vector (p0 -> p1) */
+ sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
+ vran = len_v3(vec1);
+ /* vector orthogonal to normal */
+ cross_v3_v3v3(vec2, vec1, normal);
+ normalize_v3(vec2);
+ /* use random noise */
+ if (mmd->flag & GP_NOISE_USE_RANDOM) {
+ sc_diff = abs(mmd->scene_frame - sc_frame);
+ /* only recalc if the gp frame change or the number of scene frames is bigger than step */
+ if ((!gpl->actframe) || (mmd->gp_frame != gpl->actframe->framenum) ||
+ (sc_diff >= mmd->step))
+ {
+ vran = mmd->vrand1 = BLI_rng_get_float(mmd->rng);
+ vdir = mmd->vrand2 = BLI_rng_get_float(mmd->rng);
+ mmd->gp_frame = gpl->actframe->framenum;
+ mmd->scene_frame = sc_frame;
+ }
+ else {
+ vran = mmd->vrand1;
+ if (mmd->flag & GP_NOISE_FULL_STROKE) {
+ vdir = mmd->vrand2;
+ }
+ else {
+ int f = (mmd->vrand2 * 10.0f) + i;
+ vdir = f % 2;
+ }
+ }
+ }
+ else {
+ vran = 1.0f;
+ if (mmd->flag & GP_NOISE_FULL_STROKE) {
+ vdir = gps->totpoints % 2;
+ }
+ else {
+ vdir = i % 2;
+ }
+ mmd->gp_frame = -999999;
+ }
+
+ /* apply randomness to location of the point */
+ if (mmd->flag & GP_NOISE_MOD_LOCATION) {
+ /* factor is too sensitive, so need divide */
+ shift = ((vran * mmd->factor) / 1000.0f) * weight;
+ if (vdir > 0.5f) {
+ mul_v3_fl(vec2, shift);
+ }
+ else {
+ mul_v3_fl(vec2, shift * -1.0f);
+ }
+ add_v3_v3(&pt1->x, vec2);
+ }
+
+ /* apply randomness to thickness */
+ if (mmd->flag & GP_NOISE_MOD_THICKNESS) {
+ if (vdir > 0.5f) {
+ pt1->pressure -= pt1->pressure * vran * mmd->factor;
+ }
+ else {
+ pt1->pressure += pt1->pressure * vran * mmd->factor;
+ }
+ CLAMP_MIN(pt1->pressure, GPENCIL_STRENGTH_MIN);
+ }
+
+ /* apply randomness to color strength */
+ if (mmd->flag & GP_NOISE_MOD_STRENGTH) {
+ if (vdir > 0.5f) {
+ pt1->strength -= pt1->strength * vran * mmd->factor;
+ }
+ else {
+ pt1->strength += pt1->strength * vran * mmd->factor;
+ }
+ CLAMP_MIN(pt1->strength, GPENCIL_STRENGTH_MIN);
+ }
+ /* apply randomness to uv rotation */
+ if (mmd->flag & GP_NOISE_MOD_UV) {
+ if (vdir > 0.5f) {
+ pt1->uv_rot -= pt1->uv_rot * vran * mmd->factor;
+ }
+ else {
+ pt1->uv_rot += pt1->uv_rot * vran * mmd->factor;
+ }
+ CLAMP(pt1->uv_rot, -M_PI_2, M_PI_2);
+ }
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Noise = {
+ /* name */ "Noise",
+ /* structName */ "NoiseGpencilModifierData",
+ /* structSize */ sizeof(NoiseGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ dependsOnTime,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
new file mode 100644
index 00000000000..a31f889c48a
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -0,0 +1,143 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ ARRAY_SET_ITEMS(gpmd->loc, 0.0f, 0.0f, 0.0f);
+ ARRAY_SET_ITEMS(gpmd->rot, 0.0f, 0.0f, 0.0f);
+ ARRAY_SET_ITEMS(gpmd->scale, 0.0f, 0.0f, 0.0f);
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* change stroke offsetness */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ OffsetGpencilModifierData *mmd = (OffsetGpencilModifierData *)md;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+
+ float mat[4][4];
+ float loc[3], rot[3], scale[3];
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_OFFSET_INVERT_LAYER, mmd->flag & GP_OFFSET_INVERT_PASS))
+ {
+ return;
+ }
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ /* verify vertex group */
+ float weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_OFFSET_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+ /* calculate matrix */
+ mul_v3_v3fl(loc, mmd->loc, weight);
+ mul_v3_v3fl(rot, mmd->rot, weight);
+ mul_v3_v3fl(scale, mmd->scale, weight);
+ add_v3_fl(scale, 1.0);
+ loc_eul_size_to_mat4(mat, loc, rot, scale);
+
+ mul_m4_v3(mat, &pt->x);
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Offset = {
+ /* name */ "Offset",
+ /* structName */ "OffsetGpencilModifierData",
+ /* structSize */ sizeof(OffsetGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
new file mode 100644
index 00000000000..e0484e19959
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -0,0 +1,183 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_material.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_main.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->factor = 1.0f;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->flag |= GP_OPACITY_CREATE_COLORS;
+ gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* opacity strokes */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+
+ if (!is_stroke_affected_by_modifier(
+ ob,
+ mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_OPACITY_INVERT_LAYER, mmd->flag & GP_OPACITY_INVERT_PASS))
+ {
+ return;
+ }
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
+ gps->runtime.tmp_stroke_rgba[3] *= mmd->factor;
+ /* if factor is > 1, then force opacity */
+ if (mmd->factor > 1.0f) {
+ gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
+ }
+ CLAMP(gps->runtime.tmp_stroke_rgba[3], 0.0f, 1.0f);
+ }
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ gps->runtime.tmp_fill_rgba[3] *= mmd->factor;
+ /* if factor is > 1, then force opacity */
+ if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
+ gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
+ }
+ CLAMP(gps->runtime.tmp_fill_rgba[3], 0.0f, 1.0f);
+ }
+
+ /* if opacity > 1.0, affect the strength of the stroke */
+ if (mmd->factor > 1.0f) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ /* verify vertex group */
+ float weight = get_modifier_point_weight(dvert, ((mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ pt->strength += mmd->factor - 1.0f;
+ }
+ else {
+ pt->strength += (mmd->factor - 1.0f) * weight;
+ }
+ CLAMP(pt->strength, 0.0f, 1.0f);
+ }
+ }
+}
+
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
+ bGPdata *gpd = ob->data;
+
+ GHash *gh_color = BLI_ghash_str_new("GP_Opacity modifier");
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+
+ Material *mat = give_current_material(ob, gps->mat_nr + 1);
+ if (mat == NULL)
+ continue;
+ MaterialGPencilStyle *gp_style = mat->gp_style;
+ /* skip stroke if it doesn't have color info */
+ if (ELEM(NULL, gp_style))
+ continue;
+
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ deformStroke(md, depsgraph, ob, gpl, gps);
+
+ gpencil_apply_modifier_material(bmain, ob, mat, gh_color, gps,
+ (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
+ }
+ }
+ }
+ /* free hash buffers */
+ if (gh_color) {
+ BLI_ghash_free(gh_color, NULL, NULL);
+ gh_color = NULL;
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
+ /* name */ "Opacity",
+ /* structName */ "OpacityGpencilModifierData",
+ /* structSize */ sizeof(OpacityGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
new file mode 100644
index 00000000000..a8d10c973ce
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -0,0 +1,123 @@
+/* ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_vec_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->step = 1;
+ gpmd->factor = 0.0f;
+ gpmd->layername[0] = '\0';
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ SimplifyGpencilModifierData *mmd = (SimplifyGpencilModifierData *)md;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 4, gpl, gps,
+ mmd->flag & GP_SIMPLIFY_INVERT_LAYER, mmd->flag & GP_SIMPLIFY_INVERT_PASS))
+ {
+ return;
+ }
+
+ if (mmd->mode == GP_SIMPLIFY_FIXED) {
+ for (int i = 0; i < mmd->step; i++) {
+ BKE_gpencil_simplify_fixed(gps);
+ }
+ }
+ else {
+ /* simplify stroke using Ramer-Douglas-Peucker algorithm */
+ BKE_gpencil_simplify_stroke(gps, mmd->factor);
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Simplify = {
+ /* name */ "Simplify",
+ /* structName */ "SimplifyGpencilModifierData",
+ /* structSize */ sizeof(SimplifyGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
new file mode 100644
index 00000000000..b5f2f0349af
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -0,0 +1,152 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->flag |= GP_SMOOTH_MOD_LOCATION;
+ gpmd->factor = 0.5f;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->step = 1;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* aply smooth effect based on stroke direction */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ SmoothGpencilModifierData *mmd = (SmoothGpencilModifierData *)md;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+ float weight = 1.0f;
+ float val;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_SMOOTH_INVERT_LAYER, mmd->flag & GP_SMOOTH_INVERT_PASS))
+ {
+ return;
+ }
+
+ /* smooth stroke */
+ if (mmd->factor > 0.0f) {
+ for (int r = 0; r < mmd->step; r++) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ // bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+
+ /* verify vertex group */
+ weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_SMOOTH_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+
+ val = mmd->factor * weight;
+ /* perform smoothing */
+ if (mmd->flag & GP_SMOOTH_MOD_LOCATION) {
+ BKE_gpencil_smooth_stroke(gps, i, val);
+ }
+ if (mmd->flag & GP_SMOOTH_MOD_STRENGTH) {
+ BKE_gpencil_smooth_stroke_strength(gps, i, val);
+ }
+ if ((mmd->flag & GP_SMOOTH_MOD_THICKNESS) && (val > 0)) {
+ /* thickness need to repeat process several times */
+ for (int r2 = 0; r2 < r * 10; r2++) {
+ BKE_gpencil_smooth_stroke_thickness(gps, i, val);
+ }
+ }
+ if (mmd->flag & GP_SMOOTH_MOD_UV) {
+ BKE_gpencil_smooth_stroke_uv(gps, i, val);
+ }
+ }
+ }
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Smooth = {
+ /* name */ "Smooth",
+ /* structName */ "SmoothGpencilModifierData",
+ /* structSize */ sizeof(SmoothGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
new file mode 100644
index 00000000000..dba3e028904
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -0,0 +1,193 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->level = 1;
+ gpmd->layername[0] = '\0';
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* subdivide stroke to get more control points */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
+ bGPDspoint *temp_points;
+ int totnewpoints, oldtotpoints;
+ int i2;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_SUBDIV_INVERT_LAYER, mmd->flag & GP_SUBDIV_INVERT_PASS))
+ {
+ return;
+ }
+
+ /* loop as many times as levels */
+ for (int s = 0; s < mmd->level; s++) {
+ totnewpoints = gps->totpoints - 1;
+ /* duplicate points in a temp area */
+ temp_points = MEM_dupallocN(gps->points);
+ oldtotpoints = gps->totpoints;
+
+ /* resize the points arrys */
+ gps->totpoints += totnewpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+
+ /* move points from last to first to new place */
+ i2 = gps->totpoints - 1;
+ for (int i = oldtotpoints - 1; i > 0; i--) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *pt_final = &gps->points[i2];
+
+ MDeformVert *dvert = &gps->dvert[i];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
+ copy_v3_v3(&pt_final->x, &pt->x);
+ pt_final->pressure = pt->pressure;
+ pt_final->strength = pt->strength;
+ pt_final->time = pt->time;
+ pt_final->flag = pt->flag;
+
+ dvert_final->totweight = dvert->totweight;
+ dvert_final->dw = dvert->dw;
+ i2 -= 2;
+ }
+ /* interpolate mid points */
+ i2 = 1;
+ for (int i = 0; i < oldtotpoints - 1; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i2];
+ MDeformVert *dvert_final = &gps->dvert[i2];
+
+ /* add a half way point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
+ pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
+ CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ pt_final->time = interpf(pt->time, next->time, 0.5f);
+
+ dvert_final->totweight = 0;
+ dvert_final->dw = NULL;
+ i2 += 2;
+ }
+
+ MEM_SAFE_FREE(temp_points);
+
+ /* move points to smooth stroke (not simple flag )*/
+ if ((mmd->flag & GP_SUBDIV_SIMPLE) == 0) {
+ /* duplicate points in a temp area with the new subdivide data */
+ temp_points = MEM_dupallocN(gps->points);
+
+ /* extreme points are not changed */
+ for (int i = 0; i < gps->totpoints - 2; i++) {
+ bGPDspoint *pt = &temp_points[i];
+ bGPDspoint *next = &temp_points[i + 1];
+ bGPDspoint *pt_final = &gps->points[i + 1];
+
+ /* move point */
+ interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
+ }
+ /* free temp memory */
+ MEM_SAFE_FREE(temp_points);
+ }
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
+ /* name */ "Subdivision",
+ /* structName */ "SubdivGpencilModifierData",
+ /* structSize */ sizeof(SubdivGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
new file mode 100644
index 00000000000..2c01fec1357
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -0,0 +1,171 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->thickness = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->curve_thickness = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_thickness) {
+ curvemapping_initialize(gpmd->curve_thickness);
+ }
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
+
+ if (gpmd->curve_thickness) {
+ curvemapping_free(gpmd->curve_thickness);
+ }
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ ThickGpencilModifierData *gmd = (ThickGpencilModifierData *)md;
+ ThickGpencilModifierData *tgmd = (ThickGpencilModifierData *)target;
+
+ if (tgmd->curve_thickness != NULL) {
+ curvemapping_free(tgmd->curve_thickness);
+ tgmd->curve_thickness = NULL;
+ }
+
+ BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_thickness = curvemapping_copy(gmd->curve_thickness);
+}
+
+/* change stroke thickness */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
+ int vindex = defgroup_name_index(ob, mmd->vgname);
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 3, gpl, gps,
+ mmd->flag & GP_THICK_INVERT_LAYER, mmd->flag & GP_THICK_INVERT_PASS))
+ {
+ return;
+ }
+
+ /* if normalize, set stroke thickness */
+ if (mmd->flag & GP_THICK_NORMALIZE) {
+ gps->thickness = mmd->thickness;
+ }
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = &gps->dvert[i];
+ float curvef = 1.0f;
+ /* verify vertex group */
+ float weight = get_modifier_point_weight(dvert, (int)((mmd->flag & GP_THICK_INVERT_VGROUP) != 0), vindex);
+ if (weight < 0) {
+ continue;
+ }
+
+ if (mmd->flag & GP_THICK_NORMALIZE) {
+ pt->pressure = 1.0f;
+ }
+ else {
+ if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
+ /* normalize value to evaluate curve */
+ float value = (float)i / (gps->totpoints - 1);
+ curvef = curvemapping_evaluateF(mmd->curve_thickness, 0, value);
+ }
+
+ pt->pressure += mmd->thickness * weight * curvef;
+ CLAMP(pt->strength, 0.0f, 1.0f);
+ }
+ }
+}
+
+static void bakeModifier(
+ struct Main *UNUSED(bmain), Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ deformStroke(md, depsgraph, ob, gpl, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
+ /* name */ "Thickness",
+ /* structName */ "ThickGpencilModifierData",
+ /* structSize */ sizeof(ThickGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
new file mode 100644
index 00000000000..8af9ff6eec8
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -0,0 +1,171 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+static void initData(GpencilModifierData *md)
+{
+ TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->factor = 0.5f;
+ gpmd->layername[0] = '\0';
+ ARRAY_SET_ITEMS(gpmd->rgb, 1.0f, 1.0f, 1.0f);
+ gpmd->flag |= GP_TINT_CREATE_COLORS;
+ gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* tint strokes */
+static void deformStroke(
+ GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
+ Object *ob, bGPDlayer *gpl, bGPDstroke *gps)
+{
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername, mmd->pass_index, 1, gpl, gps,
+ mmd->flag & GP_TINT_INVERT_LAYER, mmd->flag & GP_TINT_INVERT_PASS))
+ {
+ return;
+ }
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
+ interp_v3_v3v3(gps->runtime.tmp_stroke_rgba, gps->runtime.tmp_stroke_rgba, mmd->rgb, mmd->factor);
+ /* if factor is > 1, the alpha must be changed to get full tint */
+ if (mmd->factor > 1.0f) {
+ gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
+ }
+ CLAMP4(gps->runtime.tmp_stroke_rgba, 0.0f, 1.0f);
+ }
+
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ interp_v3_v3v3(gps->runtime.tmp_fill_rgba, gps->runtime.tmp_fill_rgba, mmd->rgb, mmd->factor);
+ /* if factor is > 1, the alpha must be changed to get full tint */
+ if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
+ gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
+ }
+ CLAMP4(gps->runtime.tmp_fill_rgba, 0.0f, 1.0f);
+ }
+
+ /* if factor > 1.0, affect the strength of the stroke */
+ if (mmd->factor > 1.0f) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->strength += mmd->factor - 1.0f;
+ CLAMP(pt->strength, 0.0f, 1.0f);
+ }
+ }
+}
+
+static void bakeModifier(
+ Main *bmain, Depsgraph *depsgraph,
+ GpencilModifierData *md, Object *ob)
+{
+ TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ bGPdata *gpd = ob->data;
+
+ GHash *gh_color = BLI_ghash_str_new("GP_Tint modifier");
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+
+ Material *mat = give_current_material(ob, gps->mat_nr + 1);
+ if (mat == NULL)
+ continue;
+ MaterialGPencilStyle *gp_style = mat->gp_style;
+ /* skip stroke if it doesn't have color info */
+ if (ELEM(NULL, gp_style))
+ continue;
+
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ deformStroke(md, depsgraph, ob, gpl, gps);
+
+ gpencil_apply_modifier_material(bmain, ob, mat, gh_color, gps,
+ (bool)(mmd->flag & GP_TINT_CREATE_COLORS));
+ }
+ }
+ }
+ /* free hash buffers */
+ if (gh_color) {
+ BLI_ghash_free(gh_color, NULL, NULL);
+ gh_color = NULL;
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
+ /* name */ "Tint",
+ /* structName */ "TintGpencilModifierData",
+ /* structSize */ sizeof(TintGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 716e00164ce..b9cc1de447f 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -23,7 +23,7 @@
#
# ***** END GPL LICENSE BLOCK *****
-# WITH_OPENGL limits the visibility of the opengl headers to just gawain and bg_gpu,
+# WITH_OPENGL limits the visibility of the opengl headers to just GPU and bg_gpu,
# to more easily highlight codepadths in other libraries that need to be refactored,
# bf_gpu is allowed to have opengl regardless of this option.
@@ -50,7 +50,6 @@ set(INC
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
- ../../../intern/gawain
)
set(INC_SYS
@@ -58,14 +57,17 @@ set(INC_SYS
)
set(SRC
+ intern/gpu_attr_binding.c
intern/gpu_basic_shader.c
intern/gpu_batch.c
intern/gpu_batch_presets.c
intern/gpu_batch_utils.c
intern/gpu_buffers.c
intern/gpu_codegen.c
+ intern/gpu_context.cpp
intern/gpu_debug.c
intern/gpu_draw.c
+ intern/gpu_element.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
intern/gpu_immediate.c
@@ -73,13 +75,17 @@ set(SRC
intern/gpu_init_exit.c
intern/gpu_material.c
intern/gpu_matrix.c
+ intern/gpu_primitive.c
intern/gpu_select.c
intern/gpu_select_pick.c
intern/gpu_select_sample_query.c
intern/gpu_shader.c
+ intern/gpu_shader_interface.c
intern/gpu_state.c
intern/gpu_texture.c
intern/gpu_uniformbuffer.c
+ intern/gpu_vertex_buffer.c
+ intern/gpu_vertex_format.c
intern/gpu_viewport.c
shaders/gpu_shader_fx_lib.glsl
@@ -103,11 +109,14 @@ set(SRC
shaders/gpu_shader_smoke_frag.glsl
shaders/gpu_shader_smoke_vert.glsl
+ GPU_attr_binding.h
GPU_basic_shader.h
GPU_batch.h
GPU_buffers.h
+ GPU_common.h
GPU_debug.h
GPU_draw.h
+ GPU_element.h
GPU_extensions.h
GPU_framebuffer.h
GPU_glew.h
@@ -117,17 +126,26 @@ set(SRC
GPU_legacy_stubs.h
GPU_material.h
GPU_matrix.h
+ GPU_primitive.h
GPU_select.h
GPU_shader.h
+ GPU_shader_interface.h
GPU_state.h
GPU_texture.h
GPU_uniformbuffer.h
+ GPU_vertex_buffer.h
+ GPU_vertex_format.h
GPU_viewport.h
+ intern/gpu_attr_binding_private.h
+ intern/gpu_batch_private.h
intern/gpu_codegen.h
+ intern/gpu_context_private.h
+ intern/gpu_primitive_private.h
intern/gpu_private.h
intern/gpu_select_private.h
intern/gpu_shader_private.h
+ intern/gpu_vertex_format_private.h
)
data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC)
@@ -242,6 +260,14 @@ 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_gpencil_stroke_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_gpencil_stroke_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_gpencil_stroke_geom.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_gpencil_fill_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_gpencil_fill_frag.glsl SRC)
+
+
if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
diff --git a/intern/opensubdiv/opensubdiv_gl_mesh.h b/source/blender/gpu/GPU_attr_binding.h
index 1e99fc5bce4..186acacb71d 100644
--- a/intern/opensubdiv/opensubdiv_gl_mesh.h
+++ b/source/blender/gpu/GPU_attr_binding.h
@@ -15,26 +15,28 @@
* 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) 2018 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- * Contributor(s): Sergey Sharybin.
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __OPENSUBDIV_GL_MESH_H__
-#define __OPENSUBDIV_GL_MESH_H__
+/** \file blender/gpu/GPU_attr_binding.h
+ * \ingroup gpu
+ *
+ * GPU vertex attribute binding
+ */
+
+#ifndef __GPU_ATTR_BINDING_H__
+#define __GPU_ATTR_BINDING_H__
-struct OpenSubdiv_GLMeshDescr;
-struct OpenSubdiv_TopologyRefinerDescr;
-struct OpenSubdiv_GLMeshFVarData;
+#include "GPU_common.h"
-typedef struct OpenSubdiv_GLMesh {
- int evaluator_type;
- OpenSubdiv_GLMeshDescr *descriptor;
- OpenSubdiv_TopologyRefinerDescr *topology_refiner;
- OpenSubdiv_GLMeshFVarData *fvar_data;
-} OpenSubdiv_GLMesh;
+typedef struct GPUAttrBinding {
+ uint64_t loc_bits; /* store 4 bits for each of the 16 attribs */
+ uint16_t enabled_bits; /* 1 bit for each attrib */
+} GPUAttrBinding;
-#endif /* __OPENSUBDIV_GL_MESH_H__ */
+#endif /* __GPU_ATTR_BINDING_H__ */
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index f73968eda54..bb67a90d619 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -15,37 +15,185 @@
* 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) 2016 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- *
- * Contributor(s): Mike Erwin
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
-/* Batched geometry rendering is powered by the Gawain library.
- * This file contains any additions or modifications specific to Blender.
+/** \file blender/gpu/GPU_batch.h
+ * \ingroup gpu
+ *
+ * GPU geometry batch
+ * Contains VAOs + VBOs + Shader representing a drawable entity.
*/
#ifndef __GPU_BATCH_H__
#define __GPU_BATCH_H__
-#include "../../../intern/gawain/gawain/gwn_batch.h"
-#include "../../../intern/gawain/gawain/gwn_batch_private.h"
+#include "GPU_vertex_buffer.h"
+#include "GPU_element.h"
+#include "GPU_shader_interface.h"
+#include "GPU_shader.h"
-// TODO: CMake magic to do this:
-// #include "gawain/batch.h"
+typedef enum {
+ GPU_BATCH_READY_TO_FORMAT,
+ GPU_BATCH_READY_TO_BUILD,
+ GPU_BATCH_BUILDING,
+ GPU_BATCH_READY_TO_DRAW
+} GPUBatchPhase;
-#include "BLI_compiler_attrs.h"
-#include "BLI_sys_types.h"
+#define GPU_BATCH_VBO_MAX_LEN 3
+#define GPU_BATCH_VAO_STATIC_LEN 3
+#define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16
-#include "GPU_shader.h"
+typedef struct GPUBatch {
+ /* geometry */
+ GPUVertBuf *verts[GPU_BATCH_VBO_MAX_LEN]; /* verts[0] is required, others can be NULL */
+ GPUVertBuf *inst; /* instance attribs */
+ GPUIndexBuf *elem; /* NULL if element list not needed */
+ uint32_t gl_prim_type;
+
+ /* cached values (avoid dereferencing later) */
+ uint32_t vao_id;
+ uint32_t program;
+ const struct GPUShaderInterface *interface;
+
+ /* book-keeping */
+ uint owns_flag;
+ struct GPUContext *context; /* used to free all vaos. this implies all vaos were created under the same context. */
+ GPUBatchPhase phase;
+ bool program_in_use;
+
+ /* Vao management: remembers all geometry state (vertex attrib bindings & element buffer)
+ * for each shader interface. Start with a static number of vaos and fallback to dynamic count
+ * if necessary. Once a batch goes dynamic it does not go back. */
+ bool is_dynamic_vao_count;
+ union {
+ /* Static handle count */
+ struct {
+ const struct GPUShaderInterface *interfaces[GPU_BATCH_VAO_STATIC_LEN];
+ uint32_t vao_ids[GPU_BATCH_VAO_STATIC_LEN];
+ } static_vaos;
+ /* Dynamic handle count */
+ struct {
+ uint count;
+ const struct GPUShaderInterface **interfaces;
+ uint32_t *vao_ids;
+ } dynamic_vaos;
+ };
+
+ /* XXX This is the only solution if we want to have some data structure using
+ * batches as key to identify nodes. We must destroy these nodes with this callback. */
+ void (*free_callback)(struct GPUBatch *, void *);
+ void *callback_data;
+} GPUBatch;
+
+enum {
+ GPU_BATCH_OWNS_VBO = (1 << 0),
+ /* each vbo index gets bit-shifted */
+ GPU_BATCH_OWNS_INSTANCES = (1 << 30),
+ GPU_BATCH_OWNS_INDEX = (1 << 31),
+};
+
+GPUBatch *GPU_batch_create_ex(GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag);
+void GPU_batch_init_ex(GPUBatch *, GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag);
+GPUBatch *GPU_batch_duplicate(GPUBatch *batch_src);
+
+#define GPU_batch_create(prim, verts, elem) \
+ GPU_batch_create_ex(prim, verts, elem, 0)
+#define GPU_batch_init(batch, prim, verts, elem) \
+ GPU_batch_init_ex(batch, prim, verts, elem, 0)
+
+void GPU_batch_discard(GPUBatch *); /* verts & elem are not discarded */
+
+void GPU_batch_vao_cache_clear(GPUBatch *);
+
+void GPU_batch_callback_free_set(GPUBatch *, void (*callback)(GPUBatch *, void *), void *);
+
+void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
+
+int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
+
+#define GPU_batch_vertbuf_add(batch, verts) \
+ GPU_batch_vertbuf_add_ex(batch, verts, false)
-/* gpu_batch.c */
-void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id) ATTR_NONNULL(1);
+void GPU_batch_program_set_no_use(GPUBatch *, uint32_t program, const GPUShaderInterface *);
+void GPU_batch_program_set(GPUBatch *, uint32_t program, const GPUShaderInterface *);
+void GPU_batch_program_set_builtin(GPUBatch *batch, GPUBuiltinShader shader_id);
+/* 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. */
+
+void GPU_batch_program_use_begin(GPUBatch *); /* call before Batch_Uniform (temp hack?) */
+void GPU_batch_program_use_end(GPUBatch *);
+
+void GPU_batch_uniform_1ui(GPUBatch *, const char *name, int value);
+void GPU_batch_uniform_1i(GPUBatch *, const char *name, int value);
+void GPU_batch_uniform_1b(GPUBatch *, const char *name, bool value);
+void GPU_batch_uniform_1f(GPUBatch *, const char *name, float value);
+void GPU_batch_uniform_2f(GPUBatch *, const char *name, float x, float y);
+void GPU_batch_uniform_3f(GPUBatch *, const char *name, float x, float y, float z);
+void GPU_batch_uniform_4f(GPUBatch *, const char *name, float x, float y, float z, float w);
+void GPU_batch_uniform_2fv(GPUBatch *, const char *name, const float data[2]);
+void GPU_batch_uniform_3fv(GPUBatch *, const char *name, const float data[3]);
+void GPU_batch_uniform_4fv(GPUBatch *, const char *name, const float data[4]);
+void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, int len, const float *data);
+void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, int len, const float *data);
+void GPU_batch_uniform_mat4(GPUBatch *, const char *name, const float data[4][4]);
+
+void GPU_batch_draw(GPUBatch *);
+
+/* This does not bind/unbind shader and does not call GPU_matrix_bind() */
+void GPU_batch_draw_range_ex(GPUBatch *, int v_first, int v_count, bool force_instance);
+
+/* Does not even need batch */
+void GPU_draw_primitive(GPUPrimType, int v_count);
+
+#if 0 /* future plans */
+
+/* Can multiple batches share a GPUVertBuf? Use ref count? */
+
+
+/* We often need a batch with its own data, to be created and discarded together. */
+/* WithOwn variants reduce number of system allocations. */
+
+typedef struct BatchWithOwnVertexBuffer {
+ GPUBatch batch;
+ GPUVertBuf verts; /* link batch.verts to this */
+} BatchWithOwnVertexBuffer;
+
+typedef struct BatchWithOwnElementList {
+ GPUBatch batch;
+ GPUIndexBuf elem; /* link batch.elem to this */
+} BatchWithOwnElementList;
+
+typedef struct BatchWithOwnVertexBufferAndElementList {
+ GPUBatch batch;
+ GPUIndexBuf elem; /* link batch.elem to this */
+ GPUVertBuf verts; /* link batch.verts to this */
+} BatchWithOwnVertexBufferAndElementList;
+
+GPUBatch *create_BatchWithOwnVertexBuffer(GPUPrimType, GPUVertFormat *, uint v_len, GPUIndexBuf *);
+GPUBatch *create_BatchWithOwnElementList(GPUPrimType, GPUVertBuf *, uint prim_len);
+GPUBatch *create_BatchWithOwnVertexBufferAndElementList(GPUPrimType, GPUVertFormat *, uint v_len, uint prim_len);
+/* verts: shared, own */
+/* elem: none, shared, own */
+GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff);
+
+#endif /* future plans */
void gpu_batch_init(void);
void gpu_batch_exit(void);
-#endif /* __GPU_BATCH_H__ */
+/* Macros */
+
+#define GPU_BATCH_DISCARD_SAFE(batch) do { \
+ if (batch != NULL) { \
+ GPU_batch_discard(batch); \
+ batch = NULL; \
+ } \
+} while (0)
+
+#endif /* __GPU_BATCH_H__ */
diff --git a/source/blender/gpu/GPU_batch_presets.h b/source/blender/gpu/GPU_batch_presets.h
index 2450a1760c3..a33b864c5b9 100644
--- a/source/blender/gpu/GPU_batch_presets.h
+++ b/source/blender/gpu/GPU_batch_presets.h
@@ -24,7 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/* Batched geometry rendering is powered by the Gawain library.
+/* Batched geometry rendering is powered by the GPU library.
* This file contains any additions or modifications specific to Blender.
*/
@@ -32,20 +32,20 @@
#define __GPU_BATCH_PRESETS_H__
struct rctf;
-struct Gwn_VertFormat;
+struct GPUVertFormat;
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
/* gpu_batch_presets.c */
-struct Gwn_VertFormat *GPU_batch_preset_format_3d(void);
+struct GPUVertFormat *GPU_batch_preset_format_3d(void);
/* Replacement for gluSphere */
-struct Gwn_Batch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
-struct Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
+struct GPUBatch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
+struct GPUBatch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
void gpu_batch_presets_init(void);
-void gpu_batch_presets_register(struct Gwn_Batch *preset_batch);
+void gpu_batch_presets_register(struct GPUBatch *preset_batch);
void gpu_batch_presets_reset(void);
void gpu_batch_presets_exit(void);
diff --git a/source/blender/gpu/GPU_batch_utils.h b/source/blender/gpu/GPU_batch_utils.h
index b23b7723dc0..d558b7a1097 100644
--- a/source/blender/gpu/GPU_batch_utils.h
+++ b/source/blender/gpu/GPU_batch_utils.h
@@ -27,14 +27,14 @@ struct rctf;
#include "BLI_sys_types.h"
/* gpu_batch_utils.c */
-struct Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
+struct GPUBatch *GPU_batch_tris_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
-struct Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
+struct GPUBatch *GPU_batch_wire_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/* Only use by draw manager. Use the presets function instead for interface. */
-struct Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT;
+struct GPUBatch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT;
#endif /* __GPU_BATCH_UTILS_H__ */
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index f496c92f283..77801256463 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -91,7 +91,7 @@ void GPU_pbvh_grid_buffers_update(
const int update_flags);
/* draw */
-struct Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast);
+struct GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast);
/* debug PBVH draw */
void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos);
diff --git a/intern/opensubdiv/opensubdiv_intern.h b/source/blender/gpu/GPU_common.h
index ccb32f9d0ac..3acc7fad5c2 100644
--- a/intern/opensubdiv/opensubdiv_intern.h
+++ b/source/blender/gpu/GPU_common.h
@@ -15,32 +15,47 @@
* 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) 2015 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- * Contributor(s): Sergey Sharybin.
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __OPENSUBDIV_INTERN_H__
-#define __OPENSUBDIV_INTERN_H__
+/** \file blender/gpu/GPU_common.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_COMMON_H__
+#define __GPU_COMMON_H__
+
+#define PROGRAM_NO_OPTI 0
-/* Perform full topology validation when exporting it to OpenSubdiv. */
-#ifdef NDEBUG
-# undef OPENSUBDIV_VALIDATE_TOPOLOGY
+#if defined(NDEBUG)
+# define TRUST_NO_ONE 0
#else
-/* TODO(sergey): Always disabled for now, the check doesn't handle
- * multiple non-manifolds from the OpenSubdiv side currently.
- */
-# undef OPENSUBDIV_VALIDATE_TOPOLOGY
+ /* strict error checking, enabled for debug builds during early development */
+# define TRUST_NO_ONE 1
#endif
-/* Currently OpenSubdiv expects topology to be oriented,
- * but sometimes it's handy to disable orientation code
- * to check whether it causes some weird issues by using
- * pre-oriented model.
- */
-#define OPENSUBDIV_ORIENT_TOPOLOGY
+#if defined(WITH_OPENGL)
+# include <GL/glew.h>
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "BLI_sys_types.h"
+
+#if TRUST_NO_ONE
+# include <assert.h>
+#endif
+
+/* GPU_INLINE */
+#if defined(_MSC_VER)
+# define GPU_INLINE static __forceinline
+#else
+# define GPU_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
+#endif
-#endif /* __OPENSUBDIV_INTERN_H__ */
+#endif /* __GPU_COMMON_H__ */
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
new file mode 100644
index 00000000000..3e32b64b281
--- /dev/null
+++ b/source/blender/gpu/GPU_context.h
@@ -0,0 +1,55 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_context.h
+ * \ingroup gpu
+ *
+ * This interface allow GPU to manage VAOs for mutiple context and threads.
+ */
+
+#ifndef __GPU_CONTEXT_H__
+#define __GPU_CONTEXT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "GPU_common.h"
+#include "GPU_batch.h"
+#include "GPU_shader_interface.h"
+
+typedef struct GPUContext GPUContext;
+
+GPUContext *GPU_context_create(void);
+void GPU_context_discard(GPUContext *);
+
+void GPU_context_active_set(GPUContext *);
+GPUContext *GPU_context_active_get(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_CONTEXT_H__ */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index ebce83d2a5f..028756bc739 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -101,7 +101,9 @@ void GPU_free_images_old(struct Main *bmain);
/* smoke drawing functions */
void GPU_free_smoke(struct SmokeModifierData *smd);
+void GPU_free_smoke_velocity(struct SmokeModifierData *smd);
void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
+void GPU_create_smoke_velocity(struct SmokeModifierData *smd);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(struct Main *bmain);
diff --git a/source/blender/gpu/GPU_element.h b/source/blender/gpu/GPU_element.h
new file mode 100644
index 00000000000..adc705ab641
--- /dev/null
+++ b/source/blender/gpu/GPU_element.h
@@ -0,0 +1,102 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_element.h
+ * \ingroup gpu
+ *
+ * GPU element list (AKA index buffer)
+ */
+
+#ifndef __GPU_ELEMENT_H__
+#define __GPU_ELEMENT_H__
+
+#include "GPU_primitive.h"
+
+#define GPU_TRACK_INDEX_RANGE 1
+
+#define GPU_PRIM_RESTART 0xFFFFFFFF
+
+typedef enum {
+ GPU_INDEX_U8, /* GL has this, Vulkan does not */
+ GPU_INDEX_U16,
+ GPU_INDEX_U32
+} GPUIndexBufType;
+
+typedef struct GPUIndexBuf {
+ uint index_len;
+#if GPU_TRACK_INDEX_RANGE
+ GPUIndexBufType index_type;
+ uint32_t gl_index_type;
+ uint min_index;
+ uint max_index;
+ uint base_index;
+#endif
+ uint32_t vbo_id; /* 0 indicates not yet sent to VRAM */
+ bool use_prim_restart;
+} GPUIndexBuf;
+
+void GPU_indexbuf_use(GPUIndexBuf *);
+uint GPU_indexbuf_size_get(const GPUIndexBuf *);
+
+typedef struct GPUIndexBufBuilder {
+ uint max_allowed_index;
+ uint max_index_len;
+ uint index_len;
+ GPUPrimType prim_type;
+ uint *data;
+ bool use_prim_restart;
+} GPUIndexBufBuilder;
+
+
+/* supports all primitive types. */
+void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len, bool use_prim_restart);
+
+/* supports only GPU_PRIM_POINTS, GPU_PRIM_LINES and GPU_PRIM_TRIS. */
+void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len);
+
+void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v);
+void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *);
+
+void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *, uint v);
+void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2);
+void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3);
+void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3, uint v4);
+
+GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *);
+void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *);
+
+void GPU_indexbuf_discard(GPUIndexBuf *);
+
+
+/* Macros */
+
+#define GPU_INDEXBUF_DISCARD_SAFE(elem) do { \
+ if (elem != NULL) { \
+ GPU_indexbuf_discard(elem); \
+ elem = NULL; \
+ } \
+} while (0)
+
+#endif /* __GPU_ELEMENT_H__ */
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index d36b0ea15be..f435be7fb34 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -42,6 +42,7 @@ bool GPU_full_non_power_of_two_support(void);
bool GPU_bicubic_bump_support(void);
int GPU_max_texture_size(void);
+int GPU_max_texture_layers(void);
int GPU_max_textures(void);
float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index ddf485c3c21..ef49f9721dd 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -69,8 +69,7 @@ void GPU_framebuffer_restore(void);
bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-/* internal use only */
-unsigned int GPU_framebuffer_current_get(void);
+GPUFrameBuffer *GPU_framebuffer_active_get(void);
#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \
if (fb != NULL) { \
@@ -179,7 +178,8 @@ void GPU_framebuffer_recursive_downsample(
* - wrapper around framebuffer and texture for simple offscreen drawing
*/
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
+GPUOffScreen *GPU_offscreen_create(
+ int width, int height, int samples,
bool depth, bool high_bitdepth, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index 2a2692e6baf..c8a4ea6a837 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -24,29 +24,113 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/* Immediate mode rendering is powered by the Gawain library.
- * This file contains any additions or modifications specific to Blender.
+/** \file blender/gpu/GPU_immediate.h
+ * \ingroup gpu
+ *
+ * GPU immediate mode work-alike
*/
#ifndef __GPU_IMMEDIATE_H__
#define __GPU_IMMEDIATE_H__
-#include "../../../intern/gawain/gawain/gwn_immediate.h"
-#include "../../../intern/gawain/gawain/gwn_imm_util.h"
+#include "GPU_vertex_format.h"
+#include "GPU_primitive.h"
+#include "GPU_shader_interface.h"
+#include "GPU_batch.h"
+#include "GPU_immediate_util.h"
+#include "GPU_shader.h"
-// TODO: CMake magic to do this:
-// #include "gawain/gwn_immediate.h"
-// #include "gawain/gwn_imm_util.h"
+GPUVertFormat *immVertexFormat(void); /* returns a cleared vertex format, ready for add_attrib. */
-#include "GPU_shader.h"
+void immBindProgram(uint32_t program, const GPUShaderInterface *); /* every immBegin must have a program bound first. */
+void immUnbindProgram(void); /* call after your last immEnd, or before binding another program. */
+
+void immBegin(GPUPrimType, uint vertex_len); /* must supply exactly vertex_len vertices. */
+void immBeginAtMost(GPUPrimType, uint max_vertex_len); /* can supply fewer vertices. */
+void immEnd(void); /* finishes and draws. */
+
+/* ImmBegin a batch, then use standard immFunctions as usual. */
+/* ImmEnd will finalize the batch instead of drawing. */
+/* Then you can draw it as many times as you like! Partially replaces the need for display lists. */
+GPUBatch *immBeginBatch(GPUPrimType, uint vertex_len);
+GPUBatch *immBeginBatchAtMost(GPUPrimType, uint vertex_len);
+
+/* Provide attribute values that can change per vertex. */
+/* First vertex after immBegin must have all its attributes specified. */
+/* Skipped attributes will continue using the previous value for that attrib_id. */
+void immAttrib1f(uint attrib_id, float x);
+void immAttrib2f(uint attrib_id, float x, float y);
+void immAttrib3f(uint attrib_id, float x, float y, float z);
+void immAttrib4f(uint attrib_id, float x, float y, float z, float w);
+
+void immAttrib2i(uint attrib_id, int x, int y);
+
+void immAttrib1u(uint attrib_id, uint x);
+
+void immAttrib2s(uint attrib_id, short x, short y);
+
+void immAttrib2fv(uint attrib_id, const float data[2]);
+void immAttrib3fv(uint attrib_id, const float data[3]);
+void immAttrib4fv(uint attrib_id, const float data[4]);
+
+void immAttrib3ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b);
+void immAttrib4ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+void immAttrib3ubv(uint attrib_id, const unsigned char data[4]);
+void immAttrib4ubv(uint attrib_id, const unsigned char data[4]);
+
+/* Explicitly skip an attribute. */
+/* This advanced option kills automatic value copying for this attrib_id. */
+void immSkipAttrib(uint attrib_id);
+
+/* Provide one last attribute value & end the current vertex. */
+/* This is most often used for 2D or 3D position (similar to glVertex). */
+void immVertex2f(uint attrib_id, float x, float y);
+void immVertex3f(uint attrib_id, float x, float y, float z);
+void immVertex4f(uint attrib_id, float x, float y, float z, float w);
+
+void immVertex2i(uint attrib_id, int x, int y);
+
+void immVertex2s(uint attrib_id, short x, short y);
+
+void immVertex2fv(uint attrib_id, const float data[2]);
+void immVertex3fv(uint attrib_id, const float data[3]);
+
+void immVertex2iv(uint attrib_id, const int data[2]);
+
+/* Provide uniform values that don't change for the entire draw call. */
+void immUniform1i(const char *name, int x);
+void immUniform4iv(const char *name, const int data[4]);
+void immUniform1f(const char *name, float x);
+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 immUniformArray4fv(const char *bare_name, const float *data, int count);
+void immUniformMatrix4fv(const char *name, const float data[4][4]);
+
+/* Convenience functions for setting "uniform vec4 color". */
+/* The rgb functions have implicit alpha = 1.0. */
+void immUniformColor4f(float r, float g, float b, float a);
+void immUniformColor4fv(const float rgba[4]);
+void immUniformColor3f(float r, float g, float b);
+void immUniformColor3fv(const float rgb[3]);
+void immUniformColor3fvAlpha(const float rgb[3], float a);
+
+void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b);
+void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+void immUniformColor3ubv(const unsigned char rgb[3]);
+void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char a);
+void immUniformColor4ubv(const unsigned char rgba[4]);
/* Extend immBindProgram to use Blender’s library of built-in shader programs.
* Use immUnbindProgram() when done. */
void immBindBuiltinProgram(GPUBuiltinShader shader_id);
-/*
- * Extend immUniformColor to take Blender's themes
- */
+/* Extend immUniformColor to take Blender's themes */
void immUniformThemeColor(int color_id);
void immUniformThemeColor3(int color_id);
void immUniformThemeColorShade(int color_id, int offset);
@@ -55,4 +139,10 @@ void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int
void immUniformThemeColorBlend(int color_id1, int color_id2, float fac);
void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+/* These are called by the system -- not part of drawing API. */
+void immInit(void);
+void immActivate(void);
+void immDeactivate(void);
+void immDestroy(void);
+
#endif /* __GPU_IMMEDIATE_H__ */
diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h
index c31d477ff5b..58555e287b0 100644
--- a/source/blender/gpu/GPU_immediate_util.h
+++ b/source/blender/gpu/GPU_immediate_util.h
@@ -27,6 +27,15 @@
#ifndef __GPU_IMMEDIATE_UTIL_H__
#define __GPU_IMMEDIATE_UTIL_H__
+/* Draw 2D rectangles (replaces glRect functions) */
+/* caller is reponsible for vertex format & shader */
+void immRectf(uint pos, float x1, float y1, float x2, float y2);
+void immRecti(uint pos, int x1, int y1, int x2, int y2);
+
+/* Same as immRectf/immRecti but does not call immBegin/immEnd. To use with GPU_PRIM_TRIS. */
+void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]);
+void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]);
+
void imm_cpack(uint x);
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments);
@@ -35,7 +44,7 @@ void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int
void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
-/* use this version when Gwn_VertFormat has a vec3 position */
+/* use this version when GPUVertFormat has a vec3 position */
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments);
void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 8ddb7b87c4a..6b0296361ec 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -55,7 +55,6 @@ struct GPUNodeStack;
struct GPUMaterial;
struct GPUTexture;
struct GPUUniformBuffer;
-struct GPULamp;
struct PreviewImage;
struct World;
struct bNode;
@@ -81,6 +80,7 @@ typedef enum GPUType {
GPU_MAT4 = 16,
/* Values not in GPU_DATATYPE_STR */
+ GPU_TEX1D_ARRAY = 1001,
GPU_TEX2D = 1002,
GPU_TEX3D = 1003,
GPU_SHADOW2D = 1004,
@@ -104,7 +104,7 @@ typedef enum GPUBuiltin {
GPU_AUTO_BUMPSCALE = (1 << 7),
GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
GPU_PARTICLE_SCALAR_PROPS = (1 << 9),
- GPU_PARTICLE_LOCATION = (1 << 10),
+ GPU_PARTICLE_LOCATION = (1 << 10),
GPU_PARTICLE_VELOCITY = (1 << 11),
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
@@ -125,6 +125,12 @@ typedef enum GPUMatType {
GPU_MATERIAL_TYPE_WORLD = 2,
} GPUMatType;
+typedef enum GPUMatFlag {
+ GPU_MATFLAG_DIFFUSE = (1 << 0),
+ GPU_MATFLAG_GLOSSY = (1 << 1),
+ GPU_MATFLAG_REFRACT = (1 << 2),
+ GPU_MATFLAG_SSS = (1 << 3),
+} GPUMatFlag;
typedef enum GPUBlendMode {
GPU_BLEND_SOLID = 0,
@@ -224,7 +230,7 @@ GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
-GPUNodeLink *GPU_texture(int size, float *pixels);
+GPUNodeLink *GPU_texture_ramp(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
@@ -248,17 +254,12 @@ GPUMaterial *GPU_material_from_nodetree_find(
struct ListBase *gpumaterials, const void *engine_type, int options);
GPUMaterial *GPU_material_from_nodetree(
struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, const char *name);
void GPU_material_compile(GPUMaterial *mat);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(struct Main *bmain);
-void GPU_material_orphans_init(void);
-void GPU_material_orphans_exit(void);
-/* This has to be called from a thread with an ogl context bound. */
-void GPU_material_orphans_delete(void);
-
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
@@ -268,13 +269,17 @@ GPUMaterialStatus GPU_material_status(GPUMaterial *mat);
struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material);
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs);
-void GPU_material_vertex_attributes(GPUMaterial *material,
- struct GPUVertexAttribs *attrib);
+void GPU_material_vertex_attributes(
+ GPUMaterial *material,
+ struct GPUVertexAttribs *attrib);
bool GPU_material_do_color_management(GPUMaterial *mat);
bool GPU_material_use_domain_surface(GPUMaterial *mat);
bool GPU_material_use_domain_volume(GPUMaterial *mat);
+void GPU_material_flag_set(GPUMaterial *mat, GPUMatFlag flag);
+bool GPU_material_flag_get(GPUMaterial *mat, GPUMatFlag flag);
+
void GPU_pass_cache_init(void);
void GPU_pass_cache_garbage_collect(void);
void GPU_pass_cache_free(void);
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index f22c0cd5c4d..23f19ed19cd 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -38,81 +38,81 @@
extern "C" {
#endif
-struct Gwn_ShaderInterface;
+struct GPUShaderInterface;
-void gpuMatrixReset(void); /* to Identity transform & empty stack */
+void GPU_matrix_reset(void); /* to Identity transform & empty stack */
/* ModelView Matrix (2D or 3D) */
-void gpuPushMatrix(void); /* TODO: PushCopy vs PushIdentity? */
-void gpuPopMatrix(void);
+void GPU_matrix_push(void); /* TODO: PushCopy vs PushIdentity? */
+void GPU_matrix_pop(void);
-void gpuLoadIdentity(void);
+void GPU_matrix_identity_set(void);
-void gpuScaleUniform(float factor);
+void GPU_matrix_scale_1f(float factor);
/* 3D ModelView Matrix */
-void gpuLoadMatrix(const float m[4][4]);
-void gpuMultMatrix(const float m[4][4]);
+void GPU_matrix_set(const float m[4][4]);
+void GPU_matrix_mul(const float m[4][4]);
-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? */
+void GPU_matrix_translate_3f(float x, float y, float z);
+void GPU_matrix_translate_3fv(const float vec[3]);
+void GPU_matrix_scale_3f(float x, float y, float z);
+void GPU_matrix_scale_3fv(const float vec[3]);
+void GPU_matrix_rotate_3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */
+void GPU_matrix_rotate_3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */
+void GPU_matrix_rotate_axis(float deg, char axis); /* TODO: enum for axis? */
-void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
+void GPU_matrix_look_at(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
/* TODO: variant that takes eye[3], center[3], up[3] */
/* 2D ModelView Matrix */
-void gpuTranslate2f(float x, float y);
-void gpuTranslate2fv(const float vec[2]);
-void gpuScale2f(float x, float y);
-void gpuScale2fv(const float vec[2]);
-void gpuRotate2D(float deg);
+void GPU_matrix_translate_2f(float x, float y);
+void GPU_matrix_translate_2fv(const float vec[2]);
+void GPU_matrix_scale_2f(float x, float y);
+void GPU_matrix_scale_2fv(const float vec[2]);
+void GPU_matrix_rotate_2d(float deg);
/* Projection Matrix (2D or 3D) */
-void gpuPushProjectionMatrix(void);
-void gpuPopProjectionMatrix(void);
+void GPU_matrix_push_projection(void);
+void GPU_matrix_pop_projection(void);
/* 3D Projection Matrix */
-void gpuLoadIdentityProjectionMatrix(void);
-void gpuLoadProjectionMatrix(const float m[4][4]);
+void GPU_matrix_identity_projection_set(void);
+void GPU_matrix_projection_set(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);
+void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far);
+void GPU_matrix_frustum_set(float left, float right, float bottom, float top, float near, float far);
+void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far);
/* 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]);
+void GPU_matrix_project(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]);
+bool GPU_matrix_unproject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]);
/* 2D Projection Matrix */
-void gpuOrtho2D(float left, float right, float bottom, float top);
+void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top);
/* functions to get matrix values */
-const float (*gpuGetModelViewMatrix(float m[4][4]))[4];
-const float (*gpuGetProjectionMatrix(float m[4][4]))[4];
-const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4];
+const float (*GPU_matrix_model_view_get(float m[4][4]))[4];
+const float (*GPU_matrix_projection_get(float m[4][4]))[4];
+const float (*GPU_matrix_model_view_projection_get(float m[4][4]))[4];
-const float (*gpuGetNormalMatrix(float m[3][3]))[3];
-const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3];
+const float (*GPU_matrix_normal_get(float m[3][3]))[3];
+const float (*GPU_matrix_normal_inverse_get(float m[3][3]))[3];
/* set uniform values for currently bound shader */
-void gpuBindMatrices(const struct Gwn_ShaderInterface *);
-bool gpuMatricesDirty(void); /* since last bind */
+void GPU_matrix_bind(const struct GPUShaderInterface *);
+bool GPU_matrix_dirty_get(void); /* since last bind */
/* Python API needs to be able to inspect the stack so errors raise exceptions instead of crashing. */
@@ -177,14 +177,14 @@ int GPU_matrix_stack_level_get_projection(void);
#endif /* C11 */
/* make matrix inputs generic, to avoid warnings */
-# define gpuMultMatrix(x) gpuMultMatrix(_GPU_MAT4_CONST_CAST(x))
-# define gpuLoadMatrix(x) gpuLoadMatrix(_GPU_MAT4_CONST_CAST(x))
-# define gpuLoadProjectionMatrix(x) gpuLoadProjectionMatrix(_GPU_MAT4_CONST_CAST(x))
-# define gpuGetModelViewMatrix(x) gpuGetModelViewMatrix(_GPU_MAT4_CAST(x))
-# define gpuGetProjectionMatrix(x) gpuGetProjectionMatrix(_GPU_MAT4_CAST(x))
-# define gpuGetModelViewProjectionMatrix(x) gpuGetModelViewProjectionMatrix(_GPU_MAT4_CAST(x))
-# define gpuGetNormalMatrix(x) gpuGetNormalMatrix(_GPU_MAT3_CAST(x))
-# define gpuGetNormalMatrixInverse(x) gpuGetNormalMatrixInverse(_GPU_MAT3_CAST(x))
+# define GPU_matrix_mul(x) GPU_matrix_mul(_GPU_MAT4_CONST_CAST(x))
+# define GPU_matrix_set(x) GPU_matrix_set(_GPU_MAT4_CONST_CAST(x))
+# define GPU_matrix_projection_set(x) GPU_matrix_projection_set(_GPU_MAT4_CONST_CAST(x))
+# define GPU_matrix_model_view_get(x) GPU_matrix_model_view_get(_GPU_MAT4_CAST(x))
+# define GPU_matrix_projection_get(x) GPU_matrix_projection_get(_GPU_MAT4_CAST(x))
+# define GPU_matrix_model_view_projection_get(x) GPU_matrix_model_view_projection_get(_GPU_MAT4_CAST(x))
+# define GPU_matrix_normal_get(x) GPU_matrix_normal_get(_GPU_MAT3_CAST(x))
+# define GPU_matrix_normal_inverse_get(x) GPU_matrix_normal_inverse_get(_GPU_MAT3_CAST(x))
#endif /* SUPPRESS_GENERIC_MATRIX_API */
#endif /* __GPU_MATRIX_H__ */
diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h
new file mode 100644
index 00000000000..bcedfa56ab1
--- /dev/null
+++ b/source/blender/gpu/GPU_primitive.h
@@ -0,0 +1,65 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_primitive.h
+ * \ingroup gpu
+ *
+ * GPU geometric primitives
+ */
+
+#ifndef __GPU_PRIMITIVE_H__
+#define __GPU_PRIMITIVE_H__
+
+#include "GPU_common.h"
+
+typedef enum {
+ GPU_PRIM_POINTS,
+ GPU_PRIM_LINES,
+ GPU_PRIM_TRIS,
+ GPU_PRIM_LINE_STRIP,
+ GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */
+ GPU_PRIM_TRI_STRIP,
+ GPU_PRIM_TRI_FAN,
+
+ GPU_PRIM_LINES_ADJ,
+ GPU_PRIM_TRIS_ADJ,
+ GPU_PRIM_LINE_STRIP_ADJ,
+
+ GPU_PRIM_NONE
+} GPUPrimType;
+
+/* what types of primitives does each shader expect? */
+typedef enum {
+ GPU_PRIM_CLASS_NONE = 0,
+ GPU_PRIM_CLASS_POINT = (1 << 0),
+ GPU_PRIM_CLASS_LINE = (1 << 1),
+ GPU_PRIM_CLASS_SURFACE = (1 << 2),
+ GPU_PRIM_CLASS_ANY = GPU_PRIM_CLASS_POINT | GPU_PRIM_CLASS_LINE | GPU_PRIM_CLASS_SURFACE
+} GPUPrimClass;
+
+GPUPrimClass GPU_primtype_class(GPUPrimType);
+bool GPU_primtype_belongs_to_class(GPUPrimType, GPUPrimClass);
+
+#endif /* __GPU_PRIMITIVE_H__ */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index f831d495ad0..ec5ffc0f354 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -62,7 +62,8 @@ GPUShader *GPU_shader_create(
const char *fragcode,
const char *geocode,
const char *libcode,
- const char *defines);
+ const char *defines,
+ const char *shader_name);
GPUShader *GPU_shader_create_ex(
const char *vertexcode,
const char *fragcode,
@@ -72,7 +73,8 @@ GPUShader *GPU_shader_create_ex(
const int flags,
const GPUShaderTFBType tf_type,
const char **tf_names,
- const int tf_count);
+ const int tf_count,
+ const char *shader_name);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
@@ -89,10 +91,12 @@ void *GPU_shader_get_interface(GPUShader *shader);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
-void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
- int arraysize, const float *value);
-void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
- int arraysize, const int *value);
+void GPU_shader_uniform_vector(
+ GPUShader *shader, int location, int length,
+ int arraysize, const float *value);
+void GPU_shader_uniform_vector_int(
+ GPUShader *shader, int location, int length,
+ int arraysize, const int *value);
void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
@@ -156,6 +160,10 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_IMAGE_MULTISAMPLE_4,
GPU_SHADER_2D_IMAGE_MULTISAMPLE_8,
GPU_SHADER_2D_IMAGE_MULTISAMPLE_16,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST,
GPU_SHADER_2D_CHECKER,
GPU_SHADER_2D_DIAG_STRIPES,
/* for simple 3D drawing */
@@ -340,7 +348,10 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
- /* specialized for UI drawing */
+ /* grease pencil drawing */
+ GPU_SHADER_GPENCIL_STROKE,
+ GPU_SHADER_GPENCIL_FILL,
+ /* specialized for widget drawing */
GPU_SHADER_2D_WIDGET_BASE,
GPU_SHADER_2D_WIDGET_BASE_INST,
GPU_SHADER_2D_WIDGET_SHADOW,
@@ -375,7 +386,7 @@ typedef struct GPUVertexAttribs {
int glinfoindoex;
int gltexco;
int attribid;
- char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
} layer[GPU_MAX_ATTRIB];
int totlayer;
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
new file mode 100644
index 00000000000..458a49a366b
--- /dev/null
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -0,0 +1,104 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_shader_interface.h
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ */
+
+#ifndef __GPU_SHADER_INTERFACE_H__
+#define __GPU_SHADER_INTERFACE_H__
+
+#include "GPU_common.h"
+
+typedef enum {
+ GPU_UNIFORM_NONE = 0, /* uninitialized/unknown */
+
+ GPU_UNIFORM_MODEL, /* mat4 ModelMatrix */
+ GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */
+ GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */
+ GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */
+ GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */
+ GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */
+
+ GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */
+ GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */
+ GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */
+ GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */
+ GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */
+
+ GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
+ GPU_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */
+ GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */
+ GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
+
+ GPU_UNIFORM_COLOR, /* vec4 color */
+ GPU_UNIFORM_EYE, /* vec3 eye */
+ GPU_UNIFORM_CALLID, /* int callId */
+
+ GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */
+
+ GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */
+} GPUUniformBuiltin;
+
+typedef struct GPUShaderInput {
+ struct GPUShaderInput *next;
+ uint32_t name_offset;
+ uint name_hash;
+ GPUUniformBuiltin builtin_type; /* only for uniform inputs */
+ uint32_t gl_type; /* only for attrib inputs */
+ int32_t size; /* only for attrib inputs */
+ int32_t location;
+} GPUShaderInput;
+
+#define GPU_NUM_SHADERINTERFACE_BUCKETS 257
+#define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16
+
+typedef struct GPUShaderInterface {
+ int32_t program;
+ uint32_t name_buffer_offset;
+ GPUShaderInput *attrib_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
+ GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
+ GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
+ GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS];
+ char *name_buffer;
+ struct GPUBatch **batches; /* references to batches using this interface */
+ uint batches_len;
+} GPUShaderInterface;
+
+GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id);
+void GPU_shaderinterface_discard(GPUShaderInterface *);
+
+const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name);
+const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *, GPUUniformBuiltin);
+const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name);
+const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *, const char *name);
+
+/* keep track of batches using this interface */
+void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *, struct GPUBatch *);
+void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *, struct GPUBatch *);
+
+#endif /* __GPU_SHADER_INTERFACE_H__ */
diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index 2d7ab6cd54c..16627fec42b 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -27,7 +27,7 @@
#ifndef __GPU_STATE_H__
#define __GPU_STATE_H__
- /* These map directly to the GL_ blend functions, to minimize API add as needed*/
+/* These map directly to the GL_ blend functions, to minimize API add as needed*/
typedef enum GPUBlendFunction {
GPU_ONE,
GPU_SRC_ALPHA,
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 81033f852e3..f5f00d29f1f 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -41,7 +41,7 @@ extern "C" {
struct Image;
struct ImageUser;
struct PreviewImage;
-struct Gwn_VertBuf;
+struct GPUVertBuf;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
@@ -163,6 +163,8 @@ GPUTexture *GPU_texture_create_nD(
GPUTexture *GPU_texture_create_1D(
int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_array(
+ int w, int h, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_2D(
int w, int h, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_2D_multisample(
@@ -174,7 +176,7 @@ GPUTexture *GPU_texture_create_3D(
GPUTexture *GPU_texture_create_cube(
int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_from_vertbuf(
- struct Gwn_VertBuf *vert);
+ struct GPUVertBuf *vert);
GPUTexture *GPU_texture_create_buffer(
GPUTextureFormat data_type, const uint buffer);
@@ -198,11 +200,6 @@ void GPU_invalid_tex_free(void);
void GPU_texture_free(GPUTexture *tex);
-void GPU_texture_orphans_init(void);
-void GPU_texture_orphans_exit(void);
-/* This has to be called from a thread with an ogl context bound. */
-void GPU_texture_orphans_delete(void);
-
void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h
new file mode 100644
index 00000000000..db1309bcede
--- /dev/null
+++ b/source/blender/gpu/GPU_vertex_buffer.h
@@ -0,0 +1,144 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_vertex_buffer.h
+ * \ingroup gpu
+ *
+ * GPU vertex buffer
+ */
+
+#ifndef __GPU_VERTEX_BUFFER_H__
+#define __GPU_VERTEX_BUFFER_H__
+
+#include "GPU_vertex_format.h"
+
+#define VRAM_USAGE 1
+/* How to create a GPUVertBuf: */
+/* 1) verts = GPU_vertbuf_create() or GPU_vertbuf_init(verts) */
+/* 2) GPU_vertformat_attr_add(verts->format, ...) */
+/* 3) GPU_vertbuf_data_alloc(verts, vertex_len) <-- finalizes/packs vertex format */
+/* 4) GPU_vertbuf_attr_fill(verts, pos, application_pos_buffer) */
+
+/* Is GPUVertBuf always used as part of a GPUBatch? */
+
+typedef enum {
+ /* can be extended to support more types */
+ GPU_USAGE_STREAM,
+ GPU_USAGE_STATIC, /* do not keep data in memory */
+ GPU_USAGE_DYNAMIC
+} GPUUsageType;
+
+typedef struct GPUVertBuf {
+ GPUVertFormat format;
+ uint vertex_len; /* number of verts we want to draw */
+ uint vertex_alloc; /* number of verts data */
+ bool dirty;
+ unsigned char *data; /* NULL indicates data in VRAM (unmapped) */
+ uint32_t vbo_id; /* 0 indicates not yet allocated */
+ GPUUsageType usage; /* usage hint for GL optimisation */
+} GPUVertBuf;
+
+GPUVertBuf *GPU_vertbuf_create(GPUUsageType);
+GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageType);
+
+#define GPU_vertbuf_create_with_format(format) \
+ GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC)
+
+void GPU_vertbuf_discard(GPUVertBuf *);
+
+void GPU_vertbuf_init(GPUVertBuf *, GPUUsageType);
+void GPU_vertbuf_init_with_format_ex(GPUVertBuf *, const GPUVertFormat *, GPUUsageType);
+
+#define GPU_vertbuf_init_with_format(verts, format) \
+ GPU_vertbuf_init_with_format_ex(verts, format, GPU_USAGE_STATIC)
+
+uint GPU_vertbuf_size_get(const GPUVertBuf *);
+void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len);
+void GPU_vertbuf_data_resize(GPUVertBuf *, uint v_len);
+void GPU_vertbuf_vertex_count_set(GPUVertBuf *, uint v_len);
+
+/* The most important set_attrib variant is the untyped one. Get it right first. */
+/* It takes a void* so the app developer is responsible for matching their app data types */
+/* to the vertex attribute's type and component count. They're in control of both, so this */
+/* should not be a problem. */
+
+void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data);
+void GPU_vertbuf_attr_fill(GPUVertBuf *, uint a_idx, const void *data); /* tightly packed, non interleaved input data */
+void GPU_vertbuf_attr_fill_stride(GPUVertBuf *, uint a_idx, uint stride, const void *data);
+
+/* For low level access only */
+typedef struct GPUVertBufRaw {
+ uint size;
+ uint stride;
+ unsigned char *data;
+ unsigned char *data_init;
+#if TRUST_NO_ONE
+ /* Only for overflow check */
+ unsigned char *_data_end;
+#endif
+} GPUVertBufRaw;
+
+GPU_INLINE void *GPU_vertbuf_raw_step(GPUVertBufRaw *a)
+{
+ unsigned char *data = a->data;
+ a->data += a->stride;
+#if TRUST_NO_ONE
+ assert(data < a->_data_end);
+#endif
+ return (void *)data;
+}
+
+GPU_INLINE uint GPU_vertbuf_raw_used(GPUVertBufRaw *a)
+{
+ return ((a->data - a->data_init) / a->stride);
+}
+
+void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access);
+
+/* TODO: decide whether to keep the functions below */
+/* doesn't immediate mode satisfy these needs? */
+
+/* void setAttrib1f(uint a_idx, uint v_idx, float x); */
+/* void setAttrib2f(uint a_idx, unsigned v_idx, float x, float y); */
+/* void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z); */
+/* void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w); */
+
+/* void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b); */
+/* void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a); */
+
+void GPU_vertbuf_use(GPUVertBuf *);
+
+/* Metrics */
+uint GPU_vertbuf_get_memory_usage(void);
+
+/* Macros */
+#define GPU_VERTBUF_DISCARD_SAFE(verts) do { \
+ if (verts != NULL) { \
+ GPU_vertbuf_discard(verts); \
+ verts = NULL; \
+ } \
+} while (0)
+
+#endif /* __GPU_VERTEX_BUFFER_H__ */
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
new file mode 100644
index 00000000000..7e0038e3473
--- /dev/null
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -0,0 +1,103 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_vertex_format.h
+ * \ingroup gpu
+ *
+ * GPU vertex format
+ */
+
+#ifndef __GPU_VERTEX_FORMAT_H__
+#define __GPU_VERTEX_FORMAT_H__
+
+#include "GPU_common.h"
+
+#define GPU_VERT_ATTR_MAX_LEN 16
+#define GPU_VERT_ATTR_MAX_NAMES 3
+#define GPU_VERT_ATTR_NAME_AVERAGE_LEN 11
+#define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN)
+
+typedef enum {
+ GPU_COMP_I8,
+ GPU_COMP_U8,
+ GPU_COMP_I16,
+ GPU_COMP_U16,
+ GPU_COMP_I32,
+ GPU_COMP_U32,
+
+ GPU_COMP_F32,
+
+ GPU_COMP_I10
+} GPUVertCompType;
+
+typedef enum {
+ GPU_FETCH_FLOAT,
+ GPU_FETCH_INT,
+ GPU_FETCH_INT_TO_FLOAT_UNIT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */
+ GPU_FETCH_INT_TO_FLOAT /* 127 (any int type) -> 127.0 */
+} GPUVertFetchMode;
+
+typedef struct GPUVertAttr {
+ GPUVertFetchMode fetch_mode;
+ GPUVertCompType comp_type;
+ uint gl_comp_type;
+ uint comp_len; /* 1 to 4 or 8 or 12 or 16 */
+ uint sz; /* size in bytes, 1 to 64 */
+ uint offset; /* from beginning of vertex, in bytes */
+ uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */
+ const char *name[GPU_VERT_ATTR_MAX_NAMES];
+} GPUVertAttr;
+
+typedef struct GPUVertFormat {
+ uint attr_len; /* 0 to 16 (GPU_VERT_ATTR_MAX_LEN) */
+ uint name_len; /* total count of active vertex attrib */
+ uint stride; /* stride in bytes, 1 to 256 */
+ uint name_offset;
+ bool packed;
+ char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
+ GPUVertAttr attribs[GPU_VERT_ATTR_MAX_LEN]; /* TODO: variable-size attribs array */
+} GPUVertFormat;
+
+void GPU_vertformat_clear(GPUVertFormat *);
+void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src);
+
+uint GPU_vertformat_attr_add(
+ GPUVertFormat *, const char *name,
+ GPUVertCompType, uint comp_len, GPUVertFetchMode);
+void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
+
+/* format conversion */
+
+typedef struct GPUPackedNormal {
+ int x : 10;
+ int y : 10;
+ int z : 10;
+ int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */
+} GPUPackedNormal;
+
+GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]);
+GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3]);
+
+#endif /* __GPU_VERTEX_FORMAT_H__ */
diff --git a/source/blender/gpu/intern/gpu_attr_binding.c b/source/blender/gpu/intern/gpu_attr_binding.c
new file mode 100644
index 00000000000..398b97c7f9d
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_attr_binding.c
@@ -0,0 +1,85 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_attr_binding.c
+ * \ingroup gpu
+ *
+ * GPU vertex attribute binding
+ */
+
+#include "GPU_attr_binding.h"
+#include "gpu_attr_binding_private.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#if GPU_VERT_ATTR_MAX_LEN != 16
+# error "attrib binding code assumes GPU_VERT_ATTR_MAX_LEN = 16"
+#endif
+
+void AttribBinding_clear(GPUAttrBinding *binding)
+{
+ binding->loc_bits = 0;
+ binding->enabled_bits = 0;
+}
+
+uint read_attrib_location(const GPUAttrBinding *binding, uint a_idx)
+{
+#if TRUST_NO_ONE
+ assert(a_idx < GPU_VERT_ATTR_MAX_LEN);
+ assert(binding->enabled_bits & (1 << a_idx));
+#endif
+ return (binding->loc_bits >> (4 * a_idx)) & 0xF;
+}
+
+static void write_attrib_location(GPUAttrBinding *binding, uint a_idx, uint location)
+{
+#if TRUST_NO_ONE
+ assert(a_idx < GPU_VERT_ATTR_MAX_LEN);
+ assert(location < GPU_VERT_ATTR_MAX_LEN);
+#endif
+ const uint shift = 4 * a_idx;
+ const uint64_t mask = ((uint64_t)0xF) << shift;
+ /* overwrite this attrib's previous location */
+ binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
+ /* mark this attrib as enabled */
+ binding->enabled_bits |= 1 << a_idx;
+}
+
+void get_attrib_locations(const GPUVertFormat *format, GPUAttrBinding *binding, const GPUShaderInterface *shaderface)
+{
+ AttribBinding_clear(binding);
+
+ for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) {
+ const GPUVertAttr *a = format->attribs + a_idx;
+ for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
+ const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]);
+#if TRUST_NO_ONE
+ assert(input != NULL);
+ /* TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program */
+#endif
+ write_attrib_location(binding, a_idx, input->location);
+ }
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_attr_binding_private.h b/source/blender/gpu/intern/gpu_attr_binding_private.h
new file mode 100644
index 00000000000..cb338b10aa4
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_attr_binding_private.h
@@ -0,0 +1,45 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_attr_binding_private.h
+ * \ingroup gpu
+ *
+ * GPU vertex attribute binding
+ */
+
+#ifndef __GPU_ATTR_BINDING_PRIVATE_H__
+#define __GPU_ATTR_BINDING_PRIVATE_H__
+
+#include "GPU_vertex_format.h"
+#include "GPU_shader_interface.h"
+
+void AttribBinding_clear(GPUAttrBinding *binding);
+
+void get_attrib_locations(
+ const GPUVertFormat *format, GPUAttrBinding *binding, const GPUShaderInterface *shaderface);
+unsigned read_attrib_location(
+ const GPUAttrBinding *binding, unsigned a_idx);
+
+#endif /* __GPU_ATTR_BINDING_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index b720bed2d0c..1b7b1ecf85a 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -82,7 +82,8 @@ const GLubyte stipple_halftone[128] = {
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
- 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
+};
const GLubyte stipple_quarttone[128] = {
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
@@ -92,7 +93,8 @@ const GLubyte stipple_quarttone[128] = {
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
- 136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
+ 136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
+};
const GLubyte stipple_diag_stripes_pos[128] = {
0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
@@ -110,7 +112,8 @@ const GLubyte stipple_diag_stripes_pos[128] = {
0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
- 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
+ 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
+};
const GLubyte stipple_diag_stripes_neg[128] = {
0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
@@ -128,7 +131,8 @@ const GLubyte stipple_diag_stripes_neg[128] = {
0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
- 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
+ 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
+};
const GLubyte stipple_checker_8px[128] = {
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
@@ -138,7 +142,8 @@ const GLubyte stipple_checker_8px[128] = {
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
- 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
+ 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+};
const GLubyte stipple_hexagon[128] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
@@ -156,7 +161,8 @@ const GLubyte stipple_hexagon[128] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+};
/* ********************************************* */
/* Init / exit */
@@ -237,7 +243,8 @@ static GPUShader *gpu_basic_shader(int options)
datatoc_gpu_shader_basic_frag_glsl,
geom_glsl,
NULL,
- defines);
+ defines,
+ __func__);
if (shader) {
/* set texture map to first texture unit */
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 5bfd20e3c8b..87ea112148c 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -15,40 +15,646 @@
* 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) 2016 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
- * Contributor(s): Mike Erwin
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/gpu/intern/gpu_batch.c
* \ingroup gpu
+ *
+ * GPU geometry batch
+ * Contains VAOs + VBOs + Shader representing a drawable entity.
*/
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
-#include "BLI_rect.h"
-#include "BLI_math.h"
-#include "BLI_polyfill_2d.h"
-#include "BLI_sort_utils.h"
-
-#include "GPU_batch.h" /* own include */
+#include "GPU_batch.h"
#include "GPU_batch_presets.h"
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+
+#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
+#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
+#include <stdlib.h>
+#include <string.h>
+
+static void batch_update_program_bindings(GPUBatch *batch, uint v_first);
+
+void GPU_batch_vao_cache_clear(GPUBatch *batch)
+{
+ if (batch->context == NULL) {
+ return;
+ }
+ if (batch->is_dynamic_vao_count) {
+ for (int i = 0; i < batch->dynamic_vaos.count; ++i) {
+ if (batch->dynamic_vaos.vao_ids[i]) {
+ GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context);
+ }
+ if (batch->dynamic_vaos.interfaces[i]) {
+ GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->dynamic_vaos.interfaces[i], batch);
+ }
+ }
+ MEM_freeN(batch->dynamic_vaos.interfaces);
+ MEM_freeN(batch->dynamic_vaos.vao_ids);
+ }
+ else {
+ for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) {
+ if (batch->static_vaos.vao_ids[i]) {
+ GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context);
+ }
+ if (batch->static_vaos.interfaces[i]) {
+ GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->static_vaos.interfaces[i], batch);
+ }
+ }
+ }
+ batch->is_dynamic_vao_count = false;
+ for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) {
+ batch->static_vaos.vao_ids[i] = 0;
+ batch->static_vaos.interfaces[i] = NULL;
+ }
+ gpu_context_remove_batch(batch->context, batch);
+ batch->context = NULL;
+}
+
+GPUBatch *GPU_batch_create_ex(
+ GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem,
+ uint owns_flag)
+{
+ GPUBatch *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+ GPU_batch_init_ex(batch, prim_type, verts, elem, owns_flag);
+ return batch;
+}
+
+void GPU_batch_init_ex(
+ GPUBatch *batch, GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem,
+ uint owns_flag)
+{
+#if TRUST_NO_ONE
+ assert(verts != NULL);
+#endif
+
+ batch->verts[0] = verts;
+ for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) {
+ batch->verts[v] = NULL;
+ }
+ batch->inst = NULL;
+ batch->elem = elem;
+ batch->gl_prim_type = convert_prim_type_to_gl(prim_type);
+ batch->phase = GPU_BATCH_READY_TO_DRAW;
+ batch->is_dynamic_vao_count = false;
+ batch->owns_flag = owns_flag;
+ batch->free_callback = NULL;
+}
+
+/* This will share the VBOs with the new batch. */
+GPUBatch *GPU_batch_duplicate(GPUBatch *batch_src)
+{
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, batch_src->verts[0], batch_src->elem, 0);
+
+ batch->gl_prim_type = batch_src->gl_prim_type;
+ for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) {
+ batch->verts[v] = batch_src->verts[v];
+ }
+ return batch;
+}
+
+void GPU_batch_discard(GPUBatch *batch)
+{
+ if (batch->owns_flag & GPU_BATCH_OWNS_INDEX) {
+ GPU_indexbuf_discard(batch->elem);
+ }
+ if (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES) {
+ GPU_vertbuf_discard(batch->inst);
+ }
+ if ((batch->owns_flag & ~GPU_BATCH_OWNS_INDEX) != 0) {
+ for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) {
+ if (batch->verts[v] == NULL) {
+ break;
+ }
+ if (batch->owns_flag & (1 << v)) {
+ GPU_vertbuf_discard(batch->verts[v]);
+ }
+ }
+ }
+ GPU_batch_vao_cache_clear(batch);
+
+ if (batch->free_callback) {
+ batch->free_callback(batch, batch->callback_data);
+ }
+ MEM_freeN(batch);
+}
+
+void GPU_batch_callback_free_set(GPUBatch *batch, void (*callback)(GPUBatch *, void *), void *user_data)
+{
+ batch->free_callback = callback;
+ batch->callback_data = user_data;
+}
+
+void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
+{
+#if TRUST_NO_ONE
+ assert(inst != NULL);
+#endif
+ /* redo the bindings */
+ GPU_batch_vao_cache_clear(batch);
+
+ if (batch->inst != NULL && (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES)) {
+ GPU_vertbuf_discard(batch->inst);
+ }
+ batch->inst = inst;
+
+ if (own_vbo) {
+ batch->owns_flag |= GPU_BATCH_OWNS_INSTANCES;
+ }
+ else {
+ batch->owns_flag &= ~GPU_BATCH_OWNS_INSTANCES;
+ }
+}
+
+/* Returns the index of verts in the batch. */
+int GPU_batch_vertbuf_add_ex(
+ GPUBatch *batch, GPUVertBuf *verts,
+ bool own_vbo)
+{
+ /* redo the bindings */
+ GPU_batch_vao_cache_clear(batch);
+
+ for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) {
+ if (batch->verts[v] == NULL) {
+#if TRUST_NO_ONE
+ /* for now all VertexBuffers must have same vertex_len */
+ assert(verts->vertex_len == batch->verts[0]->vertex_len);
+#endif
+ batch->verts[v] = verts;
+ /* TODO: mark dirty so we can keep attrib bindings up-to-date */
+ if (own_vbo)
+ batch->owns_flag |= (1 << v);
+ return v;
+ }
+ }
+
+ /* we only make it this far if there is no room for another GPUVertBuf */
+#if TRUST_NO_ONE
+ assert(false);
+#endif
+ return -1;
+}
+
+static GLuint batch_vao_get(GPUBatch *batch)
+{
+ /* Search through cache */
+ if (batch->is_dynamic_vao_count) {
+ for (int i = 0; i < batch->dynamic_vaos.count; ++i)
+ if (batch->dynamic_vaos.interfaces[i] == batch->interface)
+ return batch->dynamic_vaos.vao_ids[i];
+ }
+ else {
+ for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i)
+ if (batch->static_vaos.interfaces[i] == batch->interface)
+ return batch->static_vaos.vao_ids[i];
+ }
+
+ /* Set context of this batch.
+ * It will be bound to it until GPU_batch_vao_cache_clear is called.
+ * Until then it can only be drawn with this context. */
+ if (batch->context == NULL) {
+ batch->context = GPU_context_active_get();
+ gpu_context_add_batch(batch->context, batch);
+ }
+#if TRUST_NO_ONE
+ else {
+ /* Make sure you are not trying to draw this batch in another context. */
+ assert(batch->context == GPU_context_active_get());
+ }
+#endif
+
+ /* Cache miss, time to add a new entry! */
+ GLuint new_vao = 0;
+ if (!batch->is_dynamic_vao_count) {
+ int i; /* find first unused slot */
+ for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i)
+ if (batch->static_vaos.vao_ids[i] == 0)
+ break;
+
+ if (i < GPU_BATCH_VAO_STATIC_LEN) {
+ batch->static_vaos.interfaces[i] = batch->interface;
+ batch->static_vaos.vao_ids[i] = new_vao = GPU_vao_alloc();
+ }
+ else {
+ /* Not enough place switch to dynamic. */
+ batch->is_dynamic_vao_count = true;
+ /* Erase previous entries, they will be added back if drawn again. */
+ for (int j = 0; j < GPU_BATCH_VAO_STATIC_LEN; ++j) {
+ GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->static_vaos.interfaces[j], batch);
+ GPU_vao_free(batch->static_vaos.vao_ids[j], batch->context);
+ }
+ /* Init dynamic arrays and let the branch below set the values. */
+ batch->dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT;
+ batch->dynamic_vaos.interfaces = MEM_callocN(batch->dynamic_vaos.count * sizeof(GPUShaderInterface *), "dyn vaos interfaces");
+ batch->dynamic_vaos.vao_ids = MEM_callocN(batch->dynamic_vaos.count * sizeof(GLuint), "dyn vaos ids");
+ }
+ }
+
+ if (batch->is_dynamic_vao_count) {
+ int i; /* find first unused slot */
+ for (i = 0; i < batch->dynamic_vaos.count; ++i)
+ if (batch->dynamic_vaos.vao_ids[i] == 0)
+ break;
+
+ if (i == batch->dynamic_vaos.count) {
+ /* Not enough place, realloc the array. */
+ i = batch->dynamic_vaos.count;
+ batch->dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT;
+ batch->dynamic_vaos.interfaces = MEM_recallocN(batch->dynamic_vaos.interfaces, sizeof(GPUShaderInterface *) * batch->dynamic_vaos.count);
+ batch->dynamic_vaos.vao_ids = MEM_recallocN(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count);
+ }
+ batch->dynamic_vaos.interfaces[i] = batch->interface;
+ batch->dynamic_vaos.vao_ids[i] = new_vao = GPU_vao_alloc();
+ }
+
+ GPU_shaderinterface_add_batch_ref((GPUShaderInterface *)batch->interface, batch);
+
+#if TRUST_NO_ONE
+ assert(new_vao != 0);
+#endif
+
+ /* We just got a fresh VAO we need to initialize it. */
+ glBindVertexArray(new_vao);
+ batch_update_program_bindings(batch, 0);
+ glBindVertexArray(0);
+
+ return new_vao;
+}
+
+void GPU_batch_program_set_no_use(GPUBatch *batch, uint32_t program, const GPUShaderInterface *shaderface)
+{
+#if TRUST_NO_ONE
+ assert(glIsProgram(shaderface->program));
+ assert(batch->program_in_use == 0);
+#endif
+ batch->interface = shaderface;
+ batch->program = program;
+ batch->vao_id = batch_vao_get(batch);
+}
+
+void GPU_batch_program_set(GPUBatch *batch, uint32_t program, const GPUShaderInterface *shaderface)
+{
+ GPU_batch_program_set_no_use(batch, program, shaderface);
+ GPU_batch_program_use_begin(batch); /* hack! to make Batch_Uniform* simpler */
+}
+
+void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface)
+{
+ if (batch->is_dynamic_vao_count) {
+ for (int i = 0; i < batch->dynamic_vaos.count; ++i) {
+ if (batch->dynamic_vaos.interfaces[i] == interface) {
+ GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context);
+ batch->dynamic_vaos.vao_ids[i] = 0;
+ batch->dynamic_vaos.interfaces[i] = NULL;
+ break; /* cannot have duplicates */
+ }
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) {
+ if (batch->static_vaos.interfaces[i] == interface) {
+ GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context);
+ batch->static_vaos.vao_ids[i] = 0;
+ batch->static_vaos.interfaces[i] = NULL;
+ break; /* cannot have duplicates */
+ }
+ }
+ }
+}
+
+static void create_bindings(
+ GPUVertBuf *verts, const GPUShaderInterface *interface,
+ uint v_first, const bool use_instancing)
+{
+ const GPUVertFormat *format = &verts->format;
+
+ const uint attr_len = format->attr_len;
+ const uint stride = format->stride;
+
+ GPU_vertbuf_use(verts);
+
+ for (uint a_idx = 0; a_idx < attr_len; ++a_idx) {
+ const GPUVertAttr *a = format->attribs + a_idx;
+ const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride;
+
+ for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
+ const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]);
+
+ if (input == NULL) continue;
+
+ if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) {
+#if TRUST_NO_ONE
+ assert(a->fetch_mode == GPU_FETCH_FLOAT);
+ assert(a->gl_comp_type == GL_FLOAT);
+#endif
+ for (int i = 0; i < a->comp_len / 4; ++i) {
+ glEnableVertexAttribArray(input->location + i);
+ glVertexAttribDivisor(input->location + i, (use_instancing) ? 1 : 0);
+ glVertexAttribPointer(input->location + i, 4, a->gl_comp_type, GL_FALSE, stride,
+ (const GLubyte *)pointer + i * 16);
+ }
+ }
+ else {
+ glEnableVertexAttribArray(input->location);
+ glVertexAttribDivisor(input->location, (use_instancing) ? 1 : 0);
+
+ switch (a->fetch_mode) {
+ case GPU_FETCH_FLOAT:
+ case GPU_FETCH_INT_TO_FLOAT:
+ glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer);
+ break;
+ case GPU_FETCH_INT_TO_FLOAT_UNIT:
+ glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer);
+ break;
+ case GPU_FETCH_INT:
+ glVertexAttribIPointer(input->location, a->comp_len, a->gl_comp_type, stride, pointer);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void batch_update_program_bindings(GPUBatch *batch, uint v_first)
+{
+ for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) {
+ create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
+ }
+ if (batch->inst) {
+ create_bindings(batch->inst, batch->interface, v_first, true);
+ }
+ if (batch->elem) {
+ GPU_indexbuf_use(batch->elem);
+ }
+}
+
+void GPU_batch_program_use_begin(GPUBatch *batch)
+{
+ /* NOTE: use_program & done_using_program are fragile, depend on staying in sync with
+ * the GL context's active program. use_program doesn't mark other programs as "not used". */
+ /* TODO: make not fragile (somehow) */
+
+ if (!batch->program_in_use) {
+ glUseProgram(batch->program);
+ batch->program_in_use = true;
+ }
+}
+
+void GPU_batch_program_use_end(GPUBatch *batch)
+{
+ if (batch->program_in_use) {
+#if PROGRAM_NO_OPTI
+ glUseProgram(0);
+#endif
+ batch->program_in_use = false;
+ }
+}
+
+#if TRUST_NO_ONE
+# define GET_UNIFORM const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); assert(uniform);
+#else
+# define GET_UNIFORM const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name);
+#endif
+
+void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, int value)
+{
+ GET_UNIFORM
+ glUniform1ui(uniform->location, value);
+}
+
+void GPU_batch_uniform_1i(GPUBatch *batch, const char *name, int value)
+{
+ GET_UNIFORM
+ glUniform1i(uniform->location, value);
+}
+
+void GPU_batch_uniform_1b(GPUBatch *batch, const char *name, bool value)
+{
+ GET_UNIFORM
+ glUniform1i(uniform->location, value ? GL_TRUE : GL_FALSE);
+}
+
+void GPU_batch_uniform_2f(GPUBatch *batch, const char *name, float x, float y)
+{
+ GET_UNIFORM
+ glUniform2f(uniform->location, x, y);
+}
+
+void GPU_batch_uniform_3f(GPUBatch *batch, const char *name, float x, float y, float z)
+{
+ GET_UNIFORM
+ glUniform3f(uniform->location, x, y, z);
+}
+
+void GPU_batch_uniform_4f(GPUBatch *batch, const char *name, float x, float y, float z, float w)
+{
+ GET_UNIFORM
+ glUniform4f(uniform->location, x, y, z, w);
+}
+
+void GPU_batch_uniform_1f(GPUBatch *batch, const char *name, float x)
+{
+ GET_UNIFORM
+ glUniform1f(uniform->location, x);
+}
+
+void GPU_batch_uniform_2fv(GPUBatch *batch, const char *name, const float data[2])
+{
+ GET_UNIFORM
+ glUniform2fv(uniform->location, 1, data);
+}
+
+void GPU_batch_uniform_3fv(GPUBatch *batch, const char *name, const float data[3])
+{
+ GET_UNIFORM
+ glUniform3fv(uniform->location, 1, data);
+}
+
+void GPU_batch_uniform_4fv(GPUBatch *batch, const char *name, const float data[4])
+{
+ GET_UNIFORM
+ glUniform4fv(uniform->location, 1, data);
+}
+
+void GPU_batch_uniform_2fv_array(GPUBatch *batch, const char *name, const int len, const float *data)
+{
+ GET_UNIFORM
+ glUniform2fv(uniform->location, len, data);
+}
+
+void GPU_batch_uniform_4fv_array(GPUBatch *batch, const char *name, const int len, const float *data)
+{
+ GET_UNIFORM
+ glUniform4fv(uniform->location, len, data);
+}
+
+void GPU_batch_uniform_mat4(GPUBatch *batch, const char *name, const float data[4][4])
+{
+ GET_UNIFORM
+ glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data);
+}
+
+static void primitive_restart_enable(const GPUIndexBuf *el)
+{
+ // TODO(fclem) Replace by GL_PRIMITIVE_RESTART_FIXED_INDEX when we have ogl 4.3
+ glEnable(GL_PRIMITIVE_RESTART);
+ GLuint restart_index = (GLuint)0xFFFFFFFF;
+
+#if GPU_TRACK_INDEX_RANGE
+ if (el->index_type == GPU_INDEX_U8)
+ restart_index = (GLuint)0xFF;
+ else if (el->index_type == GPU_INDEX_U16)
+ restart_index = (GLuint)0xFFFF;
+#endif
+
+ glPrimitiveRestartIndex(restart_index);
+}
+
+static void primitive_restart_disable(void)
+{
+ glDisable(GL_PRIMITIVE_RESTART);
+}
+
+void GPU_batch_draw(GPUBatch *batch)
+{
+#if TRUST_NO_ONE
+ assert(batch->phase == GPU_BATCH_READY_TO_DRAW);
+ assert(batch->verts[0]->vbo_id != 0);
+#endif
+ GPU_batch_program_use_begin(batch);
+ GPU_matrix_bind(batch->interface); // external call.
+
+ GPU_batch_draw_range_ex(batch, 0, 0, false);
+
+ GPU_batch_program_use_end(batch);
+}
+
+void GPU_batch_draw_range_ex(GPUBatch *batch, int v_first, int v_count, bool force_instance)
+{
+#if TRUST_NO_ONE
+ assert(!(force_instance && (batch->inst == NULL)) || v_count > 0); // we cannot infer length if force_instance
+#endif
+ const bool do_instance = (force_instance || batch->inst);
+
+ // If using offset drawing, use the default VAO and redo bindings.
+ if (v_first != 0 && (do_instance || batch->elem)) {
+ glBindVertexArray(GPU_vao_default());
+ batch_update_program_bindings(batch, v_first);
+ }
+ else {
+ glBindVertexArray(batch->vao_id);
+ }
+
+ if (do_instance) {
+ /* Infer length if vertex count is not given */
+ if (v_count == 0) {
+ v_count = batch->inst->vertex_len;
+ }
+
+ if (batch->elem) {
+ const GPUIndexBuf *el = batch->elem;
+
+ if (el->use_prim_restart) {
+ primitive_restart_enable(el);
+ }
+#if GPU_TRACK_INDEX_RANGE
+ glDrawElementsInstancedBaseVertex(batch->gl_prim_type,
+ el->index_len,
+ el->gl_index_type,
+ 0,
+ v_count,
+ el->base_index);
+#else
+ glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count);
+#endif
+ if (el->use_prim_restart) {
+ primitive_restart_disable();
+ }
+ }
+ else {
+ glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count);
+ }
+ }
+ else {
+ /* Infer length if vertex count is not given */
+ if (v_count == 0) {
+ v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len;
+ }
+
+ if (batch->elem) {
+ const GPUIndexBuf *el = batch->elem;
+
+ if (el->use_prim_restart) {
+ primitive_restart_enable(el);
+ }
+
+#if GPU_TRACK_INDEX_RANGE
+ if (el->base_index) {
+ glDrawRangeElementsBaseVertex(
+ batch->gl_prim_type,
+ el->min_index,
+ el->max_index,
+ v_count,
+ el->gl_index_type,
+ 0,
+ el->base_index);
+ }
+ else {
+ glDrawRangeElements(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0);
+ }
+#else
+ glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, 0);
+#endif
+ if (el->use_prim_restart) {
+ primitive_restart_disable();
+ }
+ }
+ else {
+ glDrawArrays(batch->gl_prim_type, v_first, v_count);
+ }
+ }
+
+ /* Performance hog if you are drawing with the same vao multiple time.
+ * Only activate for debugging. */
+ // glBindVertexArray(0);
+}
+
+/* just draw some vertices and let shader place them where we want. */
+void GPU_draw_primitive(GPUPrimType prim_type, int v_count)
+{
+ /* we cannot draw without vao ... annoying ... */
+ glBindVertexArray(GPU_vao_default());
+
+ GLenum type = convert_prim_type_to_gl(prim_type);
+ glDrawArrays(type, 0, v_count);
+
+ /* Performance hog if you are drawing with the same vao multiple time.
+ * Only activate for debugging.*/
+ // glBindVertexArray(0);
+}
+
+
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
-void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id)
+void GPU_batch_program_set_builtin(GPUBatch *batch, GPUBuiltinShader shader_id)
{
GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
- GWN_batch_program_set(batch, shader->program, shader->interface);
+ GPU_batch_program_set(batch, shader->program, shader->interface);
}
/** \} */
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index fb696fd09a5..83287c57441 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -45,14 +45,14 @@
/* Struct to store 3D Batches and their format */
static struct {
struct {
- Gwn_Batch *sphere_high;
- Gwn_Batch *sphere_med;
- Gwn_Batch *sphere_low;
- Gwn_Batch *sphere_wire_low;
- Gwn_Batch *sphere_wire_med;
+ GPUBatch *sphere_high;
+ GPUBatch *sphere_med;
+ GPUBatch *sphere_low;
+ GPUBatch *sphere_wire_low;
+ GPUBatch *sphere_wire_med;
} batch;
- Gwn_VertFormat format;
+ GPUVertFormat format;
struct {
uint pos, nor;
@@ -66,28 +66,28 @@ static ListBase presets_list = {NULL, NULL};
/** \name 3D Primitives
* \{ */
-static Gwn_VertFormat *preset_3d_format(void)
+static GPUVertFormat *preset_3d_format(void)
{
if (g_presets_3d.format.attr_len == 0) {
- Gwn_VertFormat *format = &g_presets_3d.format;
- g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = &g_presets_3d.format;
+ g_presets_3d.attr_id.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ g_presets_3d.attr_id.nor = GPU_vertformat_attr_add(format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
return &g_presets_3d.format;
}
static void batch_sphere_lat_lon_vert(
- Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step,
+ GPUVertBufRaw *pos_step, GPUVertBufRaw *nor_step,
float lat, float lon)
{
float pos[3];
pos[0] = sinf(lat) * cosf(lon);
pos[1] = cosf(lat);
pos[2] = sinf(lat) * sinf(lon);
- copy_v3_v3(GWN_vertbuf_raw_step(pos_step), pos);
- copy_v3_v3(GWN_vertbuf_raw_step(nor_step), pos);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), pos);
+ copy_v3_v3(GPU_vertbuf_raw_step(nor_step), pos);
}
-Gwn_Batch *GPU_batch_preset_sphere(int lod)
+GPUBatch *GPU_batch_preset_sphere(int lod)
{
BLI_assert(lod >= 0 && lod <= 2);
BLI_assert(BLI_thread_is_main());
@@ -103,7 +103,7 @@ Gwn_Batch *GPU_batch_preset_sphere(int lod)
}
}
-Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
+GPUBatch *GPU_batch_preset_sphere_wire(int lod)
{
BLI_assert(lod >= 0 && lod <= 1);
BLI_assert(BLI_thread_is_main());
@@ -123,19 +123,19 @@ Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
* \{ */
/* Replacement for gluSphere */
-Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res)
+GPUBatch *gpu_batch_sphere(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;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3d_format());
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format());
const uint vbo_len = (lat_res - 1) * lon_res * 6;
- GWN_vertbuf_data_alloc(vbo, vbo_len);
+ GPU_vertbuf_data_alloc(vbo, vbo_len);
- Gwn_VertBufRaw pos_step, nor_step;
- GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
- GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
+ GPUVertBufRaw pos_step, nor_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
lon = 0.0f;
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
@@ -155,25 +155,25 @@ Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res)
}
}
- BLI_assert(vbo_len == GWN_vertbuf_raw_used(&pos_step));
- BLI_assert(vbo_len == GWN_vertbuf_raw_used(&nor_step));
+ BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step));
- return GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
-static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
+static GPUBatch *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;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3d_format());
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format());
const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2);
- GWN_vertbuf_data_alloc(vbo, vbo_len);
+ GPU_vertbuf_data_alloc(vbo, vbo_len);
- Gwn_VertBufRaw pos_step, nor_step;
- GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
- GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
+ GPUVertBufRaw pos_step, nor_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
lon = 0.0f;
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
@@ -189,10 +189,10 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
}
}
- BLI_assert(vbo_len == GWN_vertbuf_raw_used(&pos_step));
- BLI_assert(vbo_len == GWN_vertbuf_raw_used(&nor_step));
+ BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step));
- return GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
/** \} */
@@ -216,7 +216,7 @@ void gpu_batch_presets_init(void)
gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med);
}
-void gpu_batch_presets_register(Gwn_Batch *preset_batch)
+void gpu_batch_presets_register(GPUBatch *preset_batch)
{
BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch));
}
@@ -227,8 +227,8 @@ void gpu_batch_presets_reset(void)
* This way they will draw correctly for each window. */
LinkData *link = presets_list.first;
for (link = presets_list.first; link; link = link->next) {
- Gwn_Batch *preset = link->data;
- gwn_batch_vao_cache_clear(preset);
+ GPUBatch *preset = link->data;
+ GPU_batch_vao_cache_clear(preset);
}
}
@@ -236,8 +236,8 @@ void gpu_batch_presets_exit(void)
{
LinkData *link;
while ((link = BLI_pophead(&presets_list))) {
- Gwn_Batch *preset = link->data;
- GWN_batch_discard(preset);
+ GPUBatch *preset = link->data;
+ GPU_batch_discard(preset);
MEM_freeN(link);
}
}
diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h
new file mode 100644
index 00000000000..3a05e243065
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_batch_private.h
@@ -0,0 +1,50 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_batch_private.h
+ * \ingroup gpu
+ *
+ * GPU geometry batch
+ * Contains VAOs + VBOs + Shader representing a drawable entity.
+ */
+
+#ifndef __GPU_BATCH_PRIVATE_H__
+#define __GPU_BATCH_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "GPU_batch.h"
+#include "GPU_context.h"
+#include "GPU_shader_interface.h"
+
+void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_BATCH_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_batch_utils.c b/source/blender/gpu/intern/gpu_batch_utils.c
index d6d82ac18b6..0a7f1ca901d 100644
--- a/source/blender/gpu/intern/gpu_batch_utils.c
+++ b/source/blender/gpu/intern/gpu_batch_utils.c
@@ -47,7 +47,7 @@
* \param polys_flat_len: Length of the array (must be an even number).
* \param rect: Optional region to map the byte 0..255 coords to. When not set use -1..1.
*/
-Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
+GPUBatch *GPU_batch_tris_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
{
const uchar (*polys)[2] = (const void *)polys_flat;
@@ -103,41 +103,41 @@ Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
}
/* We have vertices and tris, make a batch from this. */
- static Gwn_VertFormat format = {0};
+ static GPUVertFormat format = {0};
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
const uint verts_len = (verts_step - verts);
const uint tris_len = (tris_step - tris);
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, verts_len);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, verts_len);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
for (uint i = 0; i < verts_len; i++) {
- copy_v2_v2(GWN_vertbuf_raw_step(&pos_step), verts[i]);
+ copy_v2_v2(GPU_vertbuf_raw_step(&pos_step), verts[i]);
}
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tris_len, verts_len);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tris_len, verts_len);
for (uint i = 0; i < tris_len; i++) {
- GWN_indexbuf_add_tri_verts(&elb, UNPACK3(tris[i]));
+ GPU_indexbuf_add_tri_verts(&elb, UNPACK3(tris[i]));
}
- Gwn_IndexBuf *indexbuf = GWN_indexbuf_build(&elb);
+ GPUIndexBuf *indexbuf = GPU_indexbuf_build(&elb);
MEM_freeN(tris);
MEM_freeN(verts);
- return GWN_batch_create_ex(
- GWN_PRIM_TRIS, vbo,
+ return GPU_batch_create_ex(
+ GPU_PRIM_TRIS, vbo,
indexbuf,
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
-Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
+GPUBatch *GPU_batch_wire_from_poly_2d_encoded(
const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
{
const uchar (*polys)[2] = (const void *)polys_flat;
@@ -206,18 +206,18 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
}
/* We have vertices and tris, make a batch from this. */
- static Gwn_VertFormat format = {0};
+ static GPUVertFormat format = {0};
static struct { uint pos; } attr_id;
if (format.attr_len == 0) {
- attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
const uint vbo_len_capacity = lines_len * 2;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- Gwn_VertBufRaw pos_step;
- GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPUVertBufRaw pos_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
for (uint i = 0; i < lines_len; i++) {
union {
@@ -226,18 +226,18 @@ Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
} data;
data.as_u32 = lines[i];
for (uint k = 0; k < 2; k++) {
- float *pos_v2 = GWN_vertbuf_raw_step(&pos_step);
+ float *pos_v2 = GPU_vertbuf_raw_step(&pos_step);
for (uint j = 0; j < 2; j++) {
pos_v2[j] = min_uchar[j] + ((float)data.as_u8_pair[k][j] * range_uchar[j]);
}
}
}
- BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
MEM_freeN(lines);
- return GWN_batch_create_ex(
- GWN_PRIM_LINES, vbo,
+ return GPU_batch_create_ex(
+ GPU_PRIM_LINES, vbo,
NULL,
- GWN_BATCH_OWNS_VBO);
+ GPU_BATCH_OWNS_VBO);
}
/** \} */
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 1a4750652cc..16590785af6 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -62,7 +62,7 @@ static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
/* multires global buffer, can be used for many grids having the same grid size */
typedef struct GridCommonGPUBuffer {
- Gwn_IndexBuf *mres_buffer;
+ GPUIndexBuf *mres_buffer;
int mres_prev_gridsize;
unsigned mres_prev_totquad;
} GridCommonGPUBuffer;
@@ -71,11 +71,11 @@ typedef struct GridCommonGPUBuffer {
* drawing and doesn't interact at all with the buffer code above */
struct GPU_PBVH_Buffers {
- Gwn_IndexBuf *index_buf, *index_buf_fast;
- Gwn_VertBuf *vert_buf;
+ GPUIndexBuf *index_buf, *index_buf_fast;
+ GPUVertBuf *vert_buf;
- Gwn_Batch *triangles;
- Gwn_Batch *triangles_fast;
+ GPUBatch *triangles;
+ GPUBatch *triangles_fast;
/* mesh pointers in case buffer allocation fails */
const MPoly *mpoly;
@@ -132,23 +132,23 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int v
/* Initialize vertex buffer */
/* match 'VertexBufferFormat' */
- static Gwn_VertFormat format = {0};
+ static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ g_vbo_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ g_vbo_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
#if 0
- buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC);
- GWN_vertbuf_data_alloc(buffers->vert_buf, vert_len);
+ buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DYNAMIC);
+ GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
}
else if (vert_len != buffers->vert_buf->vertex_len) {
- GWN_vertbuf_data_resize(buffers->vert_buf, vert_len);
+ GPU_vertbuf_data_resize(buffers->vert_buf, vert_len);
}
#else
- buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
}
- GWN_vertbuf_data_alloc(buffers->vert_buf, vert_len);
+ GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
#endif
return buffers->vert_buf->data != NULL;
}
@@ -157,19 +157,19 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
{
/* force flushing to the GPU */
if (buffers->vert_buf->data) {
- GWN_vertbuf_use(buffers->vert_buf);
+ GPU_vertbuf_use(buffers->vert_buf);
}
if (buffers->triangles == NULL) {
- buffers->triangles = GWN_batch_create(
- GWN_PRIM_TRIS, buffers->vert_buf,
+ buffers->triangles = GPU_batch_create(
+ GPU_PRIM_TRIS, buffers->vert_buf,
/* can be NULL */
buffers->index_buf);
}
if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) {
- buffers->triangles_fast = GWN_batch_create(
- GWN_PRIM_TRIS, buffers->vert_buf,
+ buffers->triangles_fast = GPU_batch_create(
+ GPU_PRIM_TRIS, buffers->vert_buf,
/* can be NULL */
buffers->index_buf_fast);
}
@@ -245,8 +245,8 @@ void GPU_pbvh_mesh_buffers_update(
if (buffers->smooth) {
for (uint i = 0; i < totvert; ++i) {
const MVert *v = &mvert[vert_indices[i]];
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
}
for (uint i = 0; i < buffers->face_indices_len; i++) {
@@ -257,10 +257,10 @@ void GPU_pbvh_mesh_buffers_update(
int v_index = buffers->mloop[lt->tri[j]].v;
uchar color_ub[3];
gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
}
else {
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
}
}
}
@@ -303,9 +303,9 @@ void GPU_pbvh_mesh_buffers_update(
for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
vbo_index++;
}
@@ -367,8 +367,8 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
if (buffers->smooth) {
/* Fill the triangle buffer */
buffers->index_buf = NULL;
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, INT_MAX);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, INT_MAX);
for (i = 0; i < face_indices_len; ++i) {
const MLoopTri *lt = &looptri[face_indices[i]];
@@ -377,13 +377,13 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
if (paint_is_face_hidden(lt, mvert, mloop))
continue;
- GWN_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
+ GPU_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
}
- buffers->index_buf = GWN_indexbuf_build(&elb);
+ buffers->index_buf = GPU_indexbuf_build(&elb);
}
else {
if (!buffers->is_index_buf_global) {
- GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
buffers->index_buf = NULL;
buffers->is_index_buf_global = false;
@@ -438,12 +438,12 @@ void GPU_pbvh_grid_buffers_update(
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
if (buffers->smooth) {
short no_short[3];
normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -454,7 +454,7 @@ void GPU_pbvh_grid_buffers_update(
else {
unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
vbo_index += 1;
@@ -481,7 +481,7 @@ void GPU_pbvh_grid_buffers_update(
vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
short no_short[3];
normal_float_to_short_v3(no_short, fno);
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -497,7 +497,7 @@ void GPU_pbvh_grid_buffers_update(
else {
unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
}
@@ -522,47 +522,47 @@ void GPU_pbvh_grid_buffers_update(
/* Build the element array buffer of grid indices using either
* unsigned shorts or unsigned ints. */
#define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_) \
- { \
- int offset = 0; \
- int i, j, k; \
+ { \
+ int offset = 0; \
+ int i, j, k; \
\
- Gwn_IndexBufBuilder elb; \
- GWN_indexbuf_init( \
- &elb, GWN_PRIM_TRIS, tot_quad_ * 2, max_vert_); \
+ GPUIndexBufBuilder elb; \
+ GPU_indexbuf_init( \
+ &elb, GPU_PRIM_TRIS, tot_quad_ * 2, max_vert_); \
\
- /* Fill the buffer */ \
- for (i = 0; i < totgrid; ++i) { \
- BLI_bitmap *gh = NULL; \
- if (grid_hidden) \
- gh = grid_hidden[(grid_indices)[i]]; \
+ /* Fill the buffer */ \
+ for (i = 0; i < totgrid; ++i) { \
+ BLI_bitmap *gh = NULL; \
+ if (grid_hidden) \
+ gh = grid_hidden[(grid_indices)[i]]; \
\
- for (j = 0; j < gridsize - 1; ++j) { \
- for (k = 0; k < gridsize - 1; ++k) { \
- /* Skip hidden grid face */ \
- if (gh && paint_is_grid_face_hidden( \
- gh, gridsize, k, j)) \
- { \
- continue; \
- } \
- GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
- GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \
- GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
- \
- GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \
- GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
- GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
- } \
- } \
+ for (j = 0; j < gridsize - 1; ++j) { \
+ for (k = 0; k < gridsize - 1; ++k) { \
+ /* Skip hidden grid face */ \
+ if (gh && paint_is_grid_face_hidden( \
+ gh, gridsize, k, j)) \
+ { \
+ continue; \
+ } \
+ GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \
+ GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
\
- offset += gridsize * gridsize; \
- } \
- buffer_ = GWN_indexbuf_build(&elb); \
- } (void)0
+ GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \
+ GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
+ } \
+ } \
+ \
+ offset += gridsize * gridsize; \
+ } \
+ buffer_ = GPU_indexbuf_build(&elb); \
+ } (void)0
/* end FILL_QUAD_BUFFER */
-static Gwn_IndexBuf *gpu_get_grid_buffer(
+static GPUIndexBuf *gpu_get_grid_buffer(
int gridsize, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer,
- /* remove this arg when gawain gets base-vertex support! */
+ /* remove this arg when GPU gets base-vertex support! */
int totgrid)
{
/* used in the FILL_QUAD_BUFFER macro */
@@ -586,7 +586,7 @@ static Gwn_IndexBuf *gpu_get_grid_buffer(
}
/* we can't reuse old, delete the existing buffer */
else if (gridbuff->mres_buffer) {
- GWN_indexbuf_discard(gridbuff->mres_buffer);
+ GPU_indexbuf_discard(gridbuff->mres_buffer);
gridbuff->mres_buffer = NULL;
}
@@ -603,17 +603,17 @@ static Gwn_IndexBuf *gpu_get_grid_buffer(
#define FILL_FAST_BUFFER() \
{ \
- Gwn_IndexBufBuilder elb; \
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, 6 * totgrid, INT_MAX); \
+ GPUIndexBufBuilder elb; \
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 6 * totgrid, INT_MAX); \
for (int i = 0; i < totgrid; i++) { \
- GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
- GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \
- GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
- GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \
- GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
- GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
+ GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \
+ GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
+ GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \
+ GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
} \
- buffers->index_buf_fast = GWN_indexbuf_build(&elb); \
+ buffers->index_buf_fast = GPU_indexbuf_build(&elb); \
} (void)0
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
@@ -684,7 +684,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
*/
static void gpu_bmesh_vert_to_buffer_copy__gwn(
BMVert *v,
- Gwn_VertBuf *vert_buf,
+ GPUVertBuf *vert_buf,
int *v_index,
const float fno[3],
const float *fmask,
@@ -695,12 +695,12 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
/* Set coord, normal, and mask */
- GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
{
short no_short[3];
normal_float_to_short_v3(no_short, fno ? fno : v->no);
- GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
}
{
@@ -718,7 +718,7 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
effective_mask,
diffuse_color,
color_ub);
- GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
}
/* Assign index for use in the triangle index buffer */
@@ -792,7 +792,7 @@ void GPU_pbvh_bmesh_buffers_update(
if (buffers->smooth) {
/* Smooth needs to recreate index buffer, so we have to invalidate the batch. */
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
/* Count visible vertices */
totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
}
@@ -893,8 +893,8 @@ void GPU_pbvh_bmesh_buffers_update(
if (buffers->smooth) {
/* Fill the triangle buffer */
buffers->index_buf = NULL;
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert);
/* Initialize triangle index buffer */
buffers->is_index_buf_global = false;
@@ -911,24 +911,24 @@ void GPU_pbvh_bmesh_buffers_update(
BMVert *v[3];
BM_face_as_array_vert_tri(f, v);
- GWN_indexbuf_add_tri_verts(
- &elb, BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2]));
+ GPU_indexbuf_add_tri_verts(
+ &elb, BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2]));
}
}
buffers->tot_tri = tottri;
if (buffers->index_buf == NULL) {
- buffers->index_buf = GWN_indexbuf_build(&elb);
+ buffers->index_buf = GPU_indexbuf_build(&elb);
}
else {
- GWN_indexbuf_build_in_place(&elb, buffers->index_buf);
+ GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
}
}
}
else if (buffers->index_buf) {
if (!buffers->is_index_buf_global) {
- GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
buffers->index_buf = NULL;
buffers->is_index_buf_global = false;
@@ -950,7 +950,7 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
return buffers;
}
-Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
+GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
{
return (fast && buffers->triangles_fast) ?
buffers->triangles_fast : buffers->triangles;
@@ -1003,13 +1003,13 @@ bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask)
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
- GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast);
if (!buffers->is_index_buf_global) {
- GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
- GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
+ GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
#ifdef USE_BASE_ELEM
if (buffers->baseelemarray)
@@ -1029,7 +1029,7 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer
if (gridbuff) {
if (gridbuff->mres_buffer) {
BLI_mutex_lock(&buffer_mutex);
- GWN_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer);
+ GPU_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer);
BLI_mutex_unlock(&buffer_mutex);
}
MEM_freeN(gridbuff);
@@ -1049,7 +1049,7 @@ void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos)
* could keep a static batch & index buffer, change the VBO contents per draw
*/
- immBegin(GWN_PRIM_LINES, 24);
+ immBegin(GPU_PRIM_LINES, 24);
/* top */
immVertex3f(pos, min[0], min[1], max[2]);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index a450b551d4a..289befe674e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -257,6 +257,9 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
if (!type && gpu_str_prefix(code, "sampler2DShadow")) {
type = GPU_SHADOW2D;
}
+ if (!type && gpu_str_prefix(code, "sampler1DArray")) {
+ type = GPU_TEX1D_ARRAY;
+ }
if (!type && gpu_str_prefix(code, "sampler2D")) {
type = GPU_TEX2D;
}
@@ -615,10 +618,12 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
/* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex) {
- BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
- (input->textype == GPU_TEX2D) ? "sampler2D" :
- (input->textype == GPU_TEXCUBE) ? "samplerCube" : "sampler2DShadow",
- input->texid);
+ BLI_dynstr_appendf(
+ ds, "uniform %s samp%d;\n",
+ (input->textype == GPU_TEX1D_ARRAY) ? "sampler1DArray" :
+ (input->textype == GPU_TEX2D) ? "sampler2D" :
+ (input->textype == GPU_TEXCUBE) ? "samplerCube" : "sampler2DShadow",
+ input->texid);
}
}
else if (input->source == GPU_SOURCE_BUILTIN) {
@@ -635,13 +640,15 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
}
}
else if (gpu_str_prefix(name, "unf")) {
- BLI_dynstr_appendf(ds, "uniform %s %s;\n",
- GPU_DATATYPE_STR[input->type], name);
+ BLI_dynstr_appendf(
+ ds, "uniform %s %s;\n",
+ GPU_DATATYPE_STR[input->type], name);
}
else {
- BLI_dynstr_appendf(ds, "%s %s %s;\n",
- GLEW_VERSION_3_0 ? "in" : "varying",
- GPU_DATATYPE_STR[input->type], name);
+ BLI_dynstr_appendf(
+ ds, "%s %s %s;\n",
+ GLEW_VERSION_3_0 ? "in" : "varying",
+ GPU_DATATYPE_STR[input->type], name);
}
}
}
@@ -658,12 +665,14 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
}
else if (input->dynamicvec) {
/* only create uniforms for dynamic vectors */
- BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
- GPU_DATATYPE_STR[input->type], input->id);
+ BLI_dynstr_appendf(
+ ds, "uniform %s unf%d;\n",
+ GPU_DATATYPE_STR[input->type], input->id);
}
else {
- BLI_dynstr_appendf(ds, "const %s cons%d = ",
- GPU_DATATYPE_STR[input->type], input->id);
+ BLI_dynstr_appendf(
+ ds, "const %s cons%d = ",
+ GPU_DATATYPE_STR[input->type], input->id);
codegen_print_datatype(ds, input->type, input->vec);
BLI_dynstr_append(ds, ";\n");
}
@@ -675,9 +684,10 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
}
#endif
- BLI_dynstr_appendf(ds, "%s %s var%d;\n",
- GLEW_VERSION_3_0 ? "in" : "varying",
- GPU_DATATYPE_STR[input->type], input->attribid);
+ BLI_dynstr_appendf(
+ ds, "%s %s var%d;\n",
+ GLEW_VERSION_3_0 ? "in" : "varying",
+ GPU_DATATYPE_STR[input->type], input->attribid);
#ifdef WITH_OPENSUBDIV
if (skip_opensubdiv) {
BLI_dynstr_appendf(ds, "#endif\n");
@@ -696,8 +706,9 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
for (LinkData *link = ubo_inputs.first; link; link = link->next) {
input = link->data;
- BLI_dynstr_appendf(ds, "\t%s unf%d;\n",
- GPU_DATATYPE_STR[input->type], input->id);
+ BLI_dynstr_appendf(
+ ds, "\t%s unf%d;\n",
+ GPU_DATATYPE_STR[input->type], input->id);
}
BLI_dynstr_append(ds, "};\n");
BLI_freelistN(&ubo_inputs);
@@ -719,9 +730,11 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX_PIXEL) {
if (codegen_input_has_texture(input) && input->definetex) {
- BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
- BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
- input->texid, input->texid);
+ BLI_dynstr_appendf(
+ ds, "\tvec4 tex%d = texture2D(", input->texid);
+ BLI_dynstr_appendf(
+ ds, "samp%d, gl_TexCoord[%d].st);\n",
+ input->texid, input->texid);
}
}
}
@@ -729,11 +742,13 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
/* declare temporary variables for node output storage */
for (output = node->outputs.first; output; output = output->next) {
if (output->type == GPU_CLOSURE) {
- BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id);
+ BLI_dynstr_appendf(
+ ds, "\tClosure tmp%d;\n", output->id);
}
else {
- BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
- GPU_DATATYPE_STR[output->type], output->id);
+ BLI_dynstr_appendf(
+ ds, "\t%s tmp%d;\n",
+ GPU_DATATYPE_STR[output->type], output->id);
}
}
}
@@ -757,8 +772,9 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
}
else if (input->source == GPU_SOURCE_TEX_PIXEL) {
- codegen_convert_datatype(ds, input->link->output->type, input->type,
- "tmp", input->link->output->id);
+ codegen_convert_datatype(
+ ds, input->link->output->type, input->type,
+ "tmp", input->link->output->id);
}
else if (input->source == GPU_SOURCE_BUILTIN) {
if (input->builtin == GPU_INVERSE_VIEW_MATRIX)
@@ -862,10 +878,12 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_TANGENT) {
- BLI_dynstr_appendf(ds, "#ifdef USE_OPENSUBDIV\n");
- BLI_dynstr_appendf(ds, "\t%s var%d;\n",
- GPU_DATATYPE_STR[input->type],
- input->attribid);
+ BLI_dynstr_appendf(
+ ds, "#ifdef USE_OPENSUBDIV\n");
+ BLI_dynstr_appendf(
+ ds, "\t%s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
if (has_tangent == false) {
BLI_dynstr_appendf(ds, "\tvec3 Q1 = dFdx(inpt.v.position.xyz);\n");
BLI_dynstr_appendf(ds, "\tvec3 Q2 = dFdy(inpt.v.position.xyz);\n");
@@ -917,7 +935,7 @@ static const char *attrib_prefix_get(CustomDataType type)
case CD_TANGENT: return "t";
case CD_MCOL: return "c";
case CD_AUTO_FROM_NAME: return "a";
- default: BLI_assert(false && "Gwn_VertAttr Prefix type not found : This should not happen!"); return "";
+ default: BLI_assert(false && "GPUVertAttr Prefix type not found : This should not happen!"); return "";
}
}
@@ -929,12 +947,13 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
char *code;
/* Hairs uv and col attribs are passed by bufferTextures. */
- BLI_dynstr_append(ds,
- "#ifdef HAIR_SHADER\n"
- "#define DEFINE_ATTRIB(type, attr) uniform samplerBuffer attr\n"
- "#else\n"
- "#define DEFINE_ATTRIB(type, attr) in type attr\n"
- "#endif\n"
+ BLI_dynstr_append(
+ ds,
+ "#ifdef HAIR_SHADER\n"
+ "#define DEFINE_ATTRIB(type, attr) uniform samplerBuffer attr\n"
+ "#else\n"
+ "#define DEFINE_ATTRIB(type, attr) in type attr\n"
+ "#endif\n"
);
for (node = nodes->first; node; node = node->next) {
@@ -952,10 +971,12 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
}
else {
unsigned int hash = BLI_ghashutil_strhash_p(input->attribname);
- BLI_dynstr_appendf(ds, "DEFINE_ATTRIB(%s, %s%u);\n",
- GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash);
- BLI_dynstr_appendf(ds, "#define att%d %s%u\n",
- input->attribid, attrib_prefix_get(input->attribtype), hash);
+ BLI_dynstr_appendf(
+ ds, "DEFINE_ATTRIB(%s, %s%u);\n",
+ GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash);
+ BLI_dynstr_appendf(
+ ds, "#define att%d %s%u\n",
+ input->attribid, attrib_prefix_get(input->attribtype), hash);
/* Auto attrib can be vertex color byte buffer.
* We need to know and convert them to linear space in VS. */
if (!use_geom && input->attribtype == CD_AUTO_FROM_NAME) {
@@ -963,33 +984,36 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attribid, hash);
}
}
- BLI_dynstr_appendf(ds, "out %s var%d%s;\n",
- GPU_DATATYPE_STR[input->type], input->attribid, use_geom ? "g" : "");
+ BLI_dynstr_appendf(
+ ds, "out %s var%d%s;\n",
+ GPU_DATATYPE_STR[input->type], input->attribid, use_geom ? "g" : "");
}
}
}
BLI_dynstr_append(ds, "\n");
- BLI_dynstr_append(ds,
- "#define ATTRIB\n"
- "uniform mat3 NormalMatrix;\n"
- "uniform mat4 ModelMatrixInverse;\n"
- "vec3 srgb_to_linear_attrib(vec3 c) {\n"
- "\tc = max(c, vec3(0.0));\n"
- "\tvec3 c1 = c * (1.0 / 12.92);\n"
- "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n"
- "\treturn mix(c1, c2, step(vec3(0.04045), c));\n"
- "}\n\n"
+ BLI_dynstr_append(
+ ds,
+ "#define ATTRIB\n"
+ "uniform mat3 NormalMatrix;\n"
+ "uniform mat4 ModelMatrixInverse;\n"
+ "vec3 srgb_to_linear_attrib(vec3 c) {\n"
+ "\tc = max(c, vec3(0.0));\n"
+ "\tvec3 c1 = c * (1.0 / 12.92);\n"
+ "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n"
+ "\treturn mix(c1, c2, step(vec3(0.04045), c));\n"
+ "}\n\n"
);
/* Prototype because defined later. */
- BLI_dynstr_append(ds,
- "vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
- "vec3 hair_get_customdata_vec3(const samplerBuffer);\n"
- "vec4 hair_get_customdata_vec4(const samplerBuffer);\n"
- "vec3 hair_get_strand_pos(void);\n"
- "\n"
+ BLI_dynstr_append(
+ ds,
+ "vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
+ "vec3 hair_get_customdata_vec3(const samplerBuffer);\n"
+ "vec4 hair_get_customdata_vec4(const samplerBuffer);\n"
+ "vec3 hair_get_strand_pos(void);\n"
+ "\n"
);
BLI_dynstr_append(ds, "void pass_attrib(in vec3 position) {\n");
@@ -1001,16 +1025,19 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_TANGENT) {
/* Not supported by hairs */
- BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n",
- input->attribid, use_geom ? "g" : "");
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = vec4(0.0);\n",
+ input->attribid, use_geom ? "g" : "");
}
else if (input->attribtype == CD_ORCO) {
- BLI_dynstr_appendf(ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n",
- input->attribid, use_geom ? "g" : "");
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n",
+ input->attribid, use_geom ? "g" : "");
}
else {
- BLI_dynstr_appendf(ds, "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
- input->attribid, use_geom ? "g" : "", GPU_DATATYPE_STR[input->type], input->attribid);
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
+ input->attribid, use_geom ? "g" : "", GPU_DATATYPE_STR[input->type], input->attribid);
}
}
}
@@ -1030,21 +1057,25 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
input->attribid, use_geom ? "g" : "", input->attribid);
}
else if (input->attribtype == CD_ORCO) {
- BLI_dynstr_appendf(ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
- input->attribid, use_geom ? "g" : "");
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
+ input->attribid, use_geom ? "g" : "");
}
else if (input->attribtype == CD_MCOL) {
- BLI_dynstr_appendf(ds, "\tvar%d%s = srgb_to_linear_attrib(att%d);\n",
- input->attribid, use_geom ? "g" : "", input->attribid);
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = srgb_to_linear_attrib(att%d);\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
}
else if (input->attribtype == CD_AUTO_FROM_NAME) {
- BLI_dynstr_appendf(ds, "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attrib(att%d) : att%d;\n",
- input->attribid, use_geom ? "g" : "",
- input->attribid, input->attribid, input->attribid);
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attrib(att%d) : att%d;\n",
+ input->attribid, use_geom ? "g" : "",
+ input->attribid, input->attribid, input->attribid);
}
else {
- BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n",
- input->attribid, use_geom ? "g" : "", input->attribid);
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s = att%d;\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
}
}
}
@@ -1083,12 +1114,14 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code)
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
- BLI_dynstr_appendf(ds, "in %s var%dg[];\n",
- GPU_DATATYPE_STR[input->type],
- input->attribid);
- BLI_dynstr_appendf(ds, "out %s var%d;\n",
- GPU_DATATYPE_STR[input->type],
- input->attribid);
+ BLI_dynstr_appendf(
+ ds, "in %s var%dg[];\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ BLI_dynstr_appendf(
+ ds, "out %s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
}
}
}
@@ -1301,15 +1334,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
/* small texture created on the fly, like for colorbands */
input->type = GPU_VEC4;
input->source = GPU_SOURCE_TEX;
- input->textype = type;
-
-#if 0
- input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
-#endif
- input->tex = GPU_texture_create_2D(link->texturesize, 1, GPU_RGBA8, link->ptr1, NULL);
- input->textarget = GL_TEXTURE_2D;
-
- MEM_freeN(link->ptr1);
+ input->textype = GPU_TEX1D_ARRAY;
+ input->tex = link->ptr1; /* HACK ptr1 is actually a (GPUTexture **). */
+ input->textarget = GL_TEXTURE_1D_ARRAY;
MEM_freeN(link);
}
else if (link->image) {
@@ -1382,8 +1409,8 @@ static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
case SOCK_RGBA:
return "set_rgba";
default:
- BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
- return NULL;
+ BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
+ return NULL;
}
}
@@ -1553,8 +1580,9 @@ void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
attribs->layer[a].type = input->attribtype;
attribs->layer[a].attribid = input->attribid;
- BLI_strncpy(attribs->layer[a].name, input->attribname,
- sizeof(attribs->layer[a].name));
+ BLI_strncpy(
+ attribs->layer[a].name, input->attribname,
+ sizeof(attribs->layer[a].name));
}
else {
input->attribid = attribs->layer[a].attribid;
@@ -1657,13 +1685,14 @@ GPUNodeLink *GPU_image_preview(PreviewImage *prv)
}
-GPUNodeLink *GPU_texture(int size, float *pixels)
+GPUNodeLink *GPU_texture_ramp(GPUMaterial *mat, int size, float *pixels, float *row)
{
GPUNodeLink *link = GPU_node_link_create();
link->texture = true;
- link->texturesize = size;
- link->ptr1 = pixels;
+ link->ptr1 = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
+
+ MEM_freeN(pixels);
return link;
}
@@ -1864,9 +1893,8 @@ void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
static bool gpu_pass_is_valid(GPUPass *pass)
{
- /* Shader is not null if compilation is successful,
- * refcount is positive if compilation as not yet been done. */
- return (pass->shader != NULL || pass->refcount > 0);
+ /* Shader is not null if compilation is successful. */
+ return (pass->compiled == false || pass->shader != NULL);
}
GPUPass *GPU_generate_pass_new(
@@ -1963,14 +1991,16 @@ GPUPass *GPU_generate_pass_new(
return pass;
}
-void GPU_pass_compile(GPUPass *pass)
+void GPU_pass_compile(GPUPass *pass, const char *shname)
{
if (!pass->compiled) {
- pass->shader = GPU_shader_create(pass->vertexcode,
- pass->fragmentcode,
- pass->geometrycode,
- NULL,
- pass->defines);
+ pass->shader = GPU_shader_create(
+ pass->vertexcode,
+ pass->fragmentcode,
+ pass->geometrycode,
+ NULL,
+ pass->defines,
+ shname);
pass->compiled = true;
}
}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 278843fc948..77e6e5cf4ef 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -184,7 +184,7 @@ void GPU_nodes_extract_dynamic_inputs(struct GPUShader *shader, ListBase *inputs
void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs);
void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink);
-void GPU_pass_compile(GPUPass *pass);
+void GPU_pass_compile(GPUPass *pass, const char *shname);
void GPU_pass_release(GPUPass *pass);
void GPU_pass_free_nodes(ListBase *nodes);
@@ -197,6 +197,7 @@ void gpu_codegen_exit(void);
const char *GPU_builtin_name(GPUBuiltin builtin);
void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
+struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row);
int GPU_link_changed(struct GPUNodeLink *link);
#endif
diff --git a/source/blender/gpu/intern/gpu_context.cpp b/source/blender/gpu/intern/gpu_context.cpp
new file mode 100644
index 00000000000..ce3eb64fa37
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_context.cpp
@@ -0,0 +1,329 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Clément Foucault
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_context.cpp
+ * \ingroup gpu
+ *
+ * Manage GL vertex array IDs in a thread-safe way
+ * Use these instead of glGenBuffers & its friends
+ * - alloc must be called from a thread that is bound
+ * to the context that will be used for drawing with
+ * this vao.
+ * - free can be called from any thread
+ */
+
+#include "BLI_assert.h"
+#include "BLI_utildefines.h"
+
+#include "GPU_context.h"
+#include "GPU_framebuffer.h"
+
+#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
+
+#include <vector>
+#include <string.h>
+#include <pthread.h>
+#include <mutex>
+#include <unordered_set>
+
+#if TRUST_NO_ONE
+#if 0
+extern "C" {
+extern int BLI_thread_is_main(void); /* Blender-specific function */
+}
+
+static bool thread_is_main() {
+ /* "main" here means the GL context's thread */
+ return BLI_thread_is_main();
+}
+#endif
+#endif
+
+static std::vector<GLuint> orphaned_buffer_ids;
+static std::vector<GLuint> orphaned_texture_ids;
+
+static std::mutex orphans_mutex;
+
+struct GPUContext {
+ GLuint default_vao;
+ GPUFrameBuffer *current_fbo;
+ std::unordered_set<GPUBatch *> batches; /* Batches that have VAOs from this context */
+#ifdef DEBUG
+ std::unordered_set<GPUFrameBuffer *> framebuffers; /* Framebuffers that have FBO from this context */
+#endif
+ std::vector<GLuint> orphaned_vertarray_ids;
+ std::vector<GLuint> orphaned_framebuffer_ids;
+ std::mutex orphans_mutex; /* todo: try spinlock instead */
+#if TRUST_NO_ONE
+ pthread_t thread; /* Thread on which this context is active. */
+ bool thread_is_used;
+
+ GPUContext() {
+ thread_is_used = false;
+ current_fbo = 0;
+ }
+#endif
+};
+
+#if defined(_MSC_VER) && (_MSC_VER == 1800)
+#define thread_local __declspec(thread)
+thread_local GPUContext *active_ctx = NULL;
+#else
+static thread_local GPUContext *active_ctx = NULL;
+#endif
+
+static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, GLuint id)
+{
+ std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex;
+
+ mutex->lock();
+ orphan_list->emplace_back(id);
+ mutex->unlock();
+}
+
+static void orphans_clear(GPUContext *ctx)
+{
+ BLI_assert(ctx); /* need at least an active context */
+ BLI_assert(pthread_equal(pthread_self(), ctx->thread)); /* context has been activated by another thread! */
+
+ ctx->orphans_mutex.lock();
+ if (!ctx->orphaned_vertarray_ids.empty()) {
+ uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size();
+ glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data());
+ ctx->orphaned_vertarray_ids.clear();
+ }
+ if (!ctx->orphaned_framebuffer_ids.empty()) {
+ uint orphan_len = (uint)ctx->orphaned_framebuffer_ids.size();
+ glDeleteFramebuffers(orphan_len, ctx->orphaned_framebuffer_ids.data());
+ ctx->orphaned_framebuffer_ids.clear();
+ }
+
+ ctx->orphans_mutex.unlock();
+
+ orphans_mutex.lock();
+ if (!orphaned_buffer_ids.empty()) {
+ uint orphan_len = (uint)orphaned_buffer_ids.size();
+ glDeleteBuffers(orphan_len, orphaned_buffer_ids.data());
+ orphaned_buffer_ids.clear();
+ }
+ if (!orphaned_texture_ids.empty()) {
+ uint orphan_len = (uint)orphaned_texture_ids.size();
+ glDeleteTextures(orphan_len, orphaned_texture_ids.data());
+ orphaned_texture_ids.clear();
+ }
+ orphans_mutex.unlock();
+}
+
+GPUContext *GPU_context_create(void)
+{
+ /* BLI_assert(thread_is_main()); */
+ GPUContext *ctx = new GPUContext;
+ glGenVertexArrays(1, &ctx->default_vao);
+ GPU_context_active_set(ctx);
+ return ctx;
+}
+
+/* to be called after GPU_context_active_set(ctx_to_destroy) */
+void GPU_context_discard(GPUContext *ctx)
+{
+ /* Make sure no other thread has locked it. */
+ BLI_assert(ctx == active_ctx);
+ BLI_assert(pthread_equal(pthread_self(), ctx->thread));
+ BLI_assert(ctx->orphaned_vertarray_ids.empty());
+#ifdef DEBUG
+ /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */
+ BLI_assert(ctx->framebuffers.empty());
+#endif
+ /* delete remaining vaos */
+ while (!ctx->batches.empty()) {
+ /* this removes the array entry */
+ GPU_batch_vao_cache_clear(*ctx->batches.begin());
+ }
+ glDeleteVertexArrays(1, &ctx->default_vao);
+ delete ctx;
+ active_ctx = NULL;
+}
+
+/* ctx can be NULL */
+void GPU_context_active_set(GPUContext *ctx)
+{
+#if TRUST_NO_ONE
+ if (active_ctx) {
+ active_ctx->thread_is_used = false;
+ }
+ /* Make sure no other context is already bound to this thread. */
+ if (ctx) {
+ /* Make sure no other thread has locked it. */
+ assert(ctx->thread_is_used == false);
+ ctx->thread = pthread_self();
+ ctx->thread_is_used = true;
+ }
+#endif
+ if (ctx) {
+ orphans_clear(ctx);
+ }
+ active_ctx = ctx;
+}
+
+GPUContext *GPU_context_active_get(void)
+{
+ return active_ctx;
+}
+
+GLuint GPU_vao_default(void)
+{
+ BLI_assert(active_ctx); /* need at least an active context */
+ BLI_assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */
+ return active_ctx->default_vao;
+}
+
+GLuint GPU_vao_alloc(void)
+{
+ GLuint new_vao_id = 0;
+ orphans_clear(active_ctx);
+ glGenVertexArrays(1, &new_vao_id);
+ return new_vao_id;
+}
+
+GLuint GPU_fbo_alloc(void)
+{
+ GLuint new_fbo_id = 0;
+ orphans_clear(active_ctx);
+ glGenFramebuffers(1, &new_fbo_id);
+ return new_fbo_id;
+}
+
+GLuint GPU_buf_alloc(void)
+{
+ GLuint new_buffer_id = 0;
+ orphans_clear(active_ctx);
+ glGenBuffers(1, &new_buffer_id);
+ return new_buffer_id;
+}
+
+GLuint GPU_tex_alloc(void)
+{
+ GLuint new_texture_id = 0;
+ orphans_clear(active_ctx);
+ glGenTextures(1, &new_texture_id);
+ return new_texture_id;
+}
+
+void GPU_vao_free(GLuint vao_id, GPUContext *ctx)
+{
+ BLI_assert(ctx);
+ if (ctx == active_ctx) {
+ glDeleteVertexArrays(1, &vao_id);
+ }
+ else {
+ orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id);
+ }
+}
+
+void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx)
+{
+ BLI_assert(ctx);
+ if (ctx == active_ctx) {
+ glDeleteFramebuffers(1, &fbo_id);
+ }
+ else {
+ orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id);
+ }
+}
+
+void GPU_buf_free(GLuint buf_id)
+{
+ if (active_ctx) {
+ glDeleteBuffers(1, &buf_id);
+ }
+ else {
+ orphans_add(NULL, &orphaned_buffer_ids, buf_id);
+ }
+}
+
+void GPU_tex_free(GLuint tex_id)
+{
+ if (active_ctx) {
+ glDeleteTextures(1, &tex_id);
+ }
+ else {
+ orphans_add(NULL, &orphaned_texture_ids, tex_id);
+ }
+}
+
+/* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices
+ * which are not shared across contexts. So we need to keep track of
+ * ownership. */
+
+void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch)
+{
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->batches.emplace(batch);
+ ctx->orphans_mutex.unlock();
+}
+
+void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch)
+{
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->batches.erase(batch);
+ ctx->orphans_mutex.unlock();
+}
+
+void gpu_context_add_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->framebuffers.emplace(fb);
+ ctx->orphans_mutex.unlock();
+#else
+ UNUSED_VARS(ctx, fb);
+#endif
+}
+
+void gpu_context_remove_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->framebuffers.erase(fb);
+ ctx->orphans_mutex.unlock();
+#else
+ UNUSED_VARS(ctx, fb);
+#endif
+}
+
+void gpu_context_active_framebuffer_set(GPUContext *ctx, GPUFrameBuffer *fb)
+{
+ ctx->current_fbo = fb;
+}
+
+GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx)
+{
+ return ctx->current_fbo;
+}
diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h
new file mode 100644
index 00000000000..762d9ff10c0
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_context_private.h
@@ -0,0 +1,71 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_context_private.h
+ * \ingroup gpu
+ *
+ * This interface allow GPU to manage GL objects for mutiple context and threads.
+ */
+
+#ifndef __GPU_CONTEXT_PRIVATE_H__
+#define __GPU_CONTEXT_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "GPU_context.h"
+
+struct GPUFrameBuffer;
+
+GLuint GPU_vao_default(void);
+
+/* These require a gl ctx bound. */
+GLuint GPU_buf_alloc(void);
+GLuint GPU_tex_alloc(void);
+GLuint GPU_vao_alloc(void);
+GLuint GPU_fbo_alloc(void);
+
+/* These can be called any threads even without gl ctx. */
+void GPU_buf_free(GLuint buf_id);
+void GPU_tex_free(GLuint tex_id);
+/* These two need the ctx the id was created with. */
+void GPU_vao_free(GLuint vao_id, GPUContext *ctx);
+void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx);
+
+void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch);
+void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch);
+
+void gpu_context_add_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb);
+void gpu_context_remove_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb);
+
+void gpu_context_active_framebuffer_set(GPUContext *ctx, struct GPUFrameBuffer *fb);
+struct GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_CONTEXT_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7383868843d..965caba0955 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -107,7 +107,7 @@ static bool is_over_resolution_limit(GLenum textarget, int w, int h)
int size = (textarget == GL_TEXTURE_2D) ?
GPU_max_texture_size() : GPU_max_cube_map_size();
int reslimit = (U.glreslimit != 0) ?
- min_ii(U.glreslimit, size) : size;
+ min_ii(U.glreslimit, size) : size;
return (w > reslimit || h > reslimit);
}
@@ -239,42 +239,48 @@ typedef struct VerifyThreadData {
float *srgb_frect;
} VerifyThreadData;
-static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect,
- ImBuf *ibuf,
- const int start_line,
- const int height)
+static void gpu_verify_high_bit_srgb_buffer_slice(
+ float *srgb_frect,
+ ImBuf *ibuf,
+ const int start_line,
+ const int height)
{
size_t offset = ibuf->channels * start_line * ibuf->x;
float *current_srgb_frect = srgb_frect + offset;
float *current_rect_float = ibuf->rect_float + offset;
- IMB_buffer_float_from_float(current_srgb_frect,
- current_rect_float,
- ibuf->channels,
- IB_PROFILE_SRGB,
- IB_PROFILE_LINEAR_RGB, true,
- ibuf->x, height,
- ibuf->x, ibuf->x);
+ IMB_buffer_float_from_float(
+ current_srgb_frect,
+ current_rect_float,
+ ibuf->channels,
+ IB_PROFILE_SRGB,
+ IB_PROFILE_LINEAR_RGB, true,
+ ibuf->x, height,
+ ibuf->x, ibuf->x);
IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height);
}
-static void verify_thread_do(void *data_v,
- int start_scanline,
- int num_scanlines)
+static void verify_thread_do(
+ void *data_v,
+ int start_scanline,
+ int num_scanlines)
{
VerifyThreadData *data = (VerifyThreadData *)data_v;
- gpu_verify_high_bit_srgb_buffer_slice(data->srgb_frect,
- data->ibuf,
- start_scanline,
- num_scanlines);
+ gpu_verify_high_bit_srgb_buffer_slice(
+ data->srgb_frect,
+ data->ibuf,
+ start_scanline,
+ num_scanlines);
}
-static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect,
- ImBuf *ibuf)
+static void gpu_verify_high_bit_srgb_buffer(
+ float *srgb_frect,
+ ImBuf *ibuf)
{
if (ibuf->y < 64) {
- gpu_verify_high_bit_srgb_buffer_slice(srgb_frect,
- ibuf,
- 0, ibuf->y);
+ gpu_verify_high_bit_srgb_buffer_slice(
+ srgb_frect,
+ ibuf,
+ 0, ibuf->y);
}
else {
VerifyThreadData data;
@@ -284,11 +290,12 @@ static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect,
}
}
-GPUTexture *GPU_texture_from_blender(Image *ima,
- ImageUser *iuser,
- int textarget,
- bool is_data,
- double UNUSED(time))
+GPUTexture *GPU_texture_from_blender(
+ Image *ima,
+ ImageUser *iuser,
+ int textarget,
+ bool is_data,
+ double UNUSED(time))
{
if (ima == NULL) {
return NULL;
@@ -363,11 +370,14 @@ GPUTexture *GPU_texture_from_blender(Image *ima,
const bool mipmap = GPU_get_mipmap();
#ifdef WITH_DDS
- if (ibuf->ftype == IMB_FTYPE_DDS)
+ if (ibuf->ftype == IMB_FTYPE_DDS) {
GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf);
+ }
else
#endif
+ {
GPU_create_gl_tex(&bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima);
+ }
/* mark as non-color data texture */
if (bindcode) {
@@ -556,8 +566,9 @@ void GPU_create_gl_tex(
if (mip_cube_map) {
for (int j = 0; j < 6; j++) {
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i,
- informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
+ glTexImage2D(
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i,
+ informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
}
}
gpu_del_cube_map(mip_cube_map);
@@ -639,8 +650,9 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize;
- glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height,
- 0, size, ibuf->dds_data.data + offset);
+ glCompressedTexImage2D(
+ GL_TEXTURE_2D, i, format, width, height,
+ 0, size, ibuf->dds_data.data + offset);
offset += size;
width >>= 1;
@@ -755,8 +767,9 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h);
IMB_scaleImBuf(ibuf_scale, rectw, recth);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
- GL_FLOAT, ibuf_scale->rect_float);
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
+ GL_FLOAT, ibuf_scale->rect_float);
IMB_freeImBuf(ibuf_scale);
}
@@ -775,8 +788,9 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
}
}
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
- GL_UNSIGNED_BYTE, scalerect);
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
+ GL_UNSIGNED_BYTE, scalerect);
MEM_freeN(scalerect);
}
@@ -860,8 +874,9 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
- GL_UNSIGNED_BYTE, ibuf->rect);
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
+ GL_UNSIGNED_BYTE, ibuf->rect);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
@@ -913,8 +928,9 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
- GPU_R8, smoke_get_density(sds->fluid), NULL);
+ sds->tex = GPU_texture_create_3D(
+ sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, smoke_get_density(sds->fluid), NULL);
/* Swizzle the RGBA components to read the Red channel so
* that the shader stay the same for colored and non color
@@ -926,10 +942,12 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
GPU_texture_unbind(sds->tex);
}
- sds->tex_flame = (smoke_has_fuel(sds->fluid)) ?
- GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
- GPU_R8, smoke_get_flame(sds->fluid), NULL) :
- NULL;
+ sds->tex_flame = (
+ smoke_has_fuel(sds->fluid) ?
+ GPU_texture_create_3D(
+ sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, smoke_get_flame(sds->fluid), NULL) :
+ NULL);
}
else if (!sds->tex && highres) {
/* rgba texture for color + density */
@@ -941,8 +959,9 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
- GPU_R8, smoke_turbulence_get_density(sds->wt), NULL);
+ sds->tex = GPU_texture_create_3D(
+ sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
+ GPU_R8, smoke_turbulence_get_density(sds->wt), NULL);
/* Swizzle the RGBA components to read the Red channel so
* that the shader stay the same for colored and non color
@@ -954,14 +973,17 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
GPU_texture_unbind(sds->tex);
}
- sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ?
- GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
- GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL) :
- NULL;
+ sds->tex_flame = (
+ smoke_turbulence_has_fuel(sds->wt) ?
+ GPU_texture_create_3D(
+ sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
+ GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL) :
+ NULL);
}
- sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
- GPU_R8, sds->shadow, NULL);
+ sds->tex_shadow = GPU_texture_create_3D(
+ sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, sds->shadow, NULL);
}
#else // WITH_SMOKE
(void)highres;
@@ -971,6 +993,52 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
#endif // WITH_SMOKE
}
+void GPU_create_smoke_velocity(SmokeModifierData *smd)
+{
+#ifdef WITH_SMOKE
+ if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+ SmokeDomainSettings *sds = smd->domain;
+
+ const float *vel_x = smoke_get_velocity_x(sds->fluid);
+ const float *vel_y = smoke_get_velocity_y(sds->fluid);
+ const float *vel_z = smoke_get_velocity_z(sds->fluid);
+
+ if (ELEM(NULL, vel_x, vel_y, vel_z)) {
+ return;
+ }
+
+ if (!sds->tex_velocity_x) {
+ sds->tex_velocity_x = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_x, NULL);
+ sds->tex_velocity_y = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_y, NULL);
+ sds->tex_velocity_z = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_z, NULL);
+ }
+ }
+#else // WITH_SMOKE
+ smd->domain->tex_velocity_x = NULL;
+ smd->domain->tex_velocity_y = NULL;
+ smd->domain->tex_velocity_z = NULL;
+#endif // WITH_SMOKE
+}
+
+/* TODO Unify with the other GPU_free_smoke. */
+void GPU_free_smoke_velocity(SmokeModifierData *smd)
+{
+ if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
+ if (smd->domain->tex_velocity_x)
+ GPU_texture_free(smd->domain->tex_velocity_x);
+
+ if (smd->domain->tex_velocity_y)
+ GPU_texture_free(smd->domain->tex_velocity_y);
+
+ if (smd->domain->tex_velocity_z)
+ GPU_texture_free(smd->domain->tex_velocity_z);
+
+ smd->domain->tex_velocity_x = NULL;
+ smd->domain->tex_velocity_y = NULL;
+ smd->domain->tex_velocity_z = NULL;
+ }
+}
+
static LinkNode *image_free_queue = NULL;
static void gpu_queue_image_for_free(Image *ima)
@@ -1255,10 +1323,10 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
{
#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
for (i = size; i--; col++) { \
- if ((c = *col)) { \
- *col = INDEX_FROM_BUF_BITS(c); \
- } \
- } ((void)0)
+ if ((c = *col)) { \
+ *col = INDEX_FROM_BUF_BITS(c); \
+ } \
+ } ((void)0)
if (size > 0) {
unsigned int i, c;
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
new file mode 100644
index 00000000000..56a0c90d5b5
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -0,0 +1,311 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_element.c
+ * \ingroup gpu
+ *
+ * GPU element list (AKA index buffer)
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_element.h"
+
+#include "gpu_context_private.h"
+
+#include <stdlib.h>
+
+#define KEEP_SINGLE_COPY 1
+
+static GLenum convert_index_type_to_gl(GPUIndexBufType type)
+{
+ static const GLenum table[] = {
+ [GPU_INDEX_U8] = GL_UNSIGNED_BYTE, /* GL has this, Vulkan does not */
+ [GPU_INDEX_U16] = GL_UNSIGNED_SHORT,
+ [GPU_INDEX_U32] = GL_UNSIGNED_INT
+ };
+ return table[type];
+}
+
+uint GPU_indexbuf_size_get(const GPUIndexBuf *elem)
+{
+#if GPU_TRACK_INDEX_RANGE
+ static const uint table[] = {
+ [GPU_INDEX_U8] = sizeof(GLubyte), /* GL has this, Vulkan does not */
+ [GPU_INDEX_U16] = sizeof(GLushort),
+ [GPU_INDEX_U32] = sizeof(GLuint)
+ };
+ return elem->index_len * table[elem->index_type];
+#else
+ return elem->index_len * sizeof(GLuint);
+#endif
+}
+
+void GPU_indexbuf_init_ex(
+ GPUIndexBufBuilder *builder, GPUPrimType prim_type,
+ uint index_len, uint vertex_len, bool use_prim_restart)
+{
+ builder->use_prim_restart = use_prim_restart;
+ builder->max_allowed_index = vertex_len - 1;
+ builder->max_index_len = index_len;
+ builder->index_len = 0; // start empty
+ builder->prim_type = prim_type;
+ builder->data = MEM_callocN(builder->max_index_len * sizeof(uint), "GPUIndexBuf data");
+}
+
+void GPU_indexbuf_init(GPUIndexBufBuilder *builder, GPUPrimType prim_type, uint prim_len, uint vertex_len)
+{
+ uint verts_per_prim = 0;
+ switch (prim_type) {
+ case GPU_PRIM_POINTS:
+ verts_per_prim = 1;
+ break;
+ case GPU_PRIM_LINES:
+ verts_per_prim = 2;
+ break;
+ case GPU_PRIM_TRIS:
+ verts_per_prim = 3;
+ break;
+ case GPU_PRIM_LINES_ADJ:
+ verts_per_prim = 4;
+ break;
+ default:
+#if TRUST_NO_ONE
+ assert(false);
+#endif
+ return;
+ }
+
+ GPU_indexbuf_init_ex(builder, prim_type, prim_len * verts_per_prim, vertex_len, false);
+}
+
+void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *builder, uint v)
+{
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+ assert(builder->index_len < builder->max_index_len);
+ assert(v <= builder->max_allowed_index);
+#endif
+ builder->data[builder->index_len++] = v;
+}
+
+void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *builder)
+{
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+ assert(builder->index_len < builder->max_index_len);
+ assert(builder->use_prim_restart);
+#endif
+ builder->data[builder->index_len++] = GPU_PRIM_RESTART;
+}
+
+void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *builder, uint v)
+{
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GPU_PRIM_POINTS);
+#endif
+ GPU_indexbuf_add_generic_vert(builder, v);
+}
+
+void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *builder, uint v1, uint v2)
+{
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GPU_PRIM_LINES);
+ assert(v1 != v2);
+#endif
+ GPU_indexbuf_add_generic_vert(builder, v1);
+ GPU_indexbuf_add_generic_vert(builder, v2);
+}
+
+void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *builder, uint v1, uint v2, uint v3)
+{
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GPU_PRIM_TRIS);
+ assert(v1 != v2 && v2 != v3 && v3 != v1);
+#endif
+ GPU_indexbuf_add_generic_vert(builder, v1);
+ GPU_indexbuf_add_generic_vert(builder, v2);
+ GPU_indexbuf_add_generic_vert(builder, v3);
+}
+
+void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *builder, uint v1, uint v2, uint v3, uint v4)
+{
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GPU_PRIM_LINES_ADJ);
+ assert(v2 != v3); /* only the line need diff indices */
+#endif
+ GPU_indexbuf_add_generic_vert(builder, v1);
+ GPU_indexbuf_add_generic_vert(builder, v2);
+ GPU_indexbuf_add_generic_vert(builder, v3);
+ GPU_indexbuf_add_generic_vert(builder, v4);
+}
+
+#if GPU_TRACK_INDEX_RANGE
+/* Everything remains 32 bit while building to keep things simple.
+ * Find min/max after, then convert to smallest index type possible. */
+
+static uint index_range(const uint values[], uint value_len, uint *min_out, uint *max_out)
+{
+ if (value_len == 0) {
+ *min_out = 0;
+ *max_out = 0;
+ return 0;
+ }
+ uint min_value = values[0];
+ uint max_value = values[0];
+ for (uint i = 1; i < value_len; ++i) {
+ const uint value = values[i];
+ if (value == GPU_PRIM_RESTART)
+ continue;
+ else if (value < min_value)
+ min_value = value;
+ else if (value > max_value)
+ max_value = value;
+ }
+ *min_out = min_value;
+ *max_out = max_value;
+ return max_value - min_value;
+}
+
+static void squeeze_indices_byte(GPUIndexBufBuilder *builder, GPUIndexBuf *elem)
+{
+ const uint *values = builder->data;
+ const uint index_len = elem->index_len;
+
+ /* data will never be *larger* than builder->data...
+ * converting in place to avoid extra allocation */
+ GLubyte *data = (GLubyte *)builder->data;
+
+ if (elem->max_index > 0xFF) {
+ const uint base = elem->min_index;
+ elem->base_index = base;
+ elem->min_index = 0;
+ elem->max_index -= base;
+ for (uint i = 0; i < index_len; ++i) {
+ data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base);
+ }
+ }
+ else {
+ elem->base_index = 0;
+ for (uint i = 0; i < index_len; ++i) {
+ data[i] = (GLubyte)(values[i]);
+ }
+ }
+}
+
+static void squeeze_indices_short(GPUIndexBufBuilder *builder, GPUIndexBuf *elem)
+{
+ const uint *values = builder->data;
+ const uint index_len = elem->index_len;
+
+ /* data will never be *larger* than builder->data...
+ * converting in place to avoid extra allocation */
+ GLushort *data = (GLushort *)builder->data;
+
+ if (elem->max_index > 0xFFFF) {
+ const uint base = elem->min_index;
+ elem->base_index = base;
+ elem->min_index = 0;
+ elem->max_index -= base;
+ for (uint i = 0; i < index_len; ++i) {
+ data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base);
+ }
+ }
+ else {
+ elem->base_index = 0;
+ for (uint i = 0; i < index_len; ++i) {
+ data[i] = (GLushort)(values[i]);
+ }
+ }
+}
+
+#endif /* GPU_TRACK_INDEX_RANGE */
+
+GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *builder)
+{
+ GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+ GPU_indexbuf_build_in_place(builder, elem);
+ return elem;
+}
+
+void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, GPUIndexBuf *elem)
+{
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+#endif
+ elem->index_len = builder->index_len;
+ elem->use_prim_restart = builder->use_prim_restart;
+
+#if GPU_TRACK_INDEX_RANGE
+ uint range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index);
+
+ /* count the primitive restart index. */
+ if (elem->use_prim_restart) {
+ range += 1;
+ }
+
+ if (range <= 0xFF) {
+ elem->index_type = GPU_INDEX_U8;
+ squeeze_indices_byte(builder, elem);
+ }
+ else if (range <= 0xFFFF) {
+ elem->index_type = GPU_INDEX_U16;
+ squeeze_indices_short(builder, elem);
+ }
+ else {
+ elem->index_type = GPU_INDEX_U32;
+ elem->base_index = 0;
+ }
+ elem->gl_index_type = convert_index_type_to_gl(elem->index_type);
+#endif
+
+ if (elem->vbo_id == 0) {
+ elem->vbo_id = GPU_buf_alloc();
+ }
+ /* send data to GPU */
+ /* GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound,
+ * so we use the GL_ARRAY_BUFFER here to create a buffer without
+ * interfering in the VAO state. */
+ glBindBuffer(GL_ARRAY_BUFFER, elem->vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, GPU_indexbuf_size_get(elem), builder->data, GL_STATIC_DRAW);
+
+ /* discard builder (one-time use) */
+ MEM_freeN(builder->data);
+ builder->data = NULL;
+ /* other fields are safe to leave */
+}
+
+void GPU_indexbuf_use(GPUIndexBuf *elem)
+{
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id);
+}
+
+void GPU_indexbuf_discard(GPUIndexBuf *elem)
+{
+ if (elem->vbo_id) {
+ GPU_buf_free(elem->vbo_id);
+ }
+ MEM_freeN(elem);
+}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index dff6cfb74a8..43081154e89 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -66,6 +66,7 @@
static struct GPUGlobal {
GLint maxtexsize;
+ GLint maxtexlayers;
GLint maxcubemapsize;
GLint maxtextures;
GLint maxubosize;
@@ -96,6 +97,11 @@ int GPU_max_texture_size(void)
return GG.maxtexsize;
}
+int GPU_max_texture_layers(void)
+{
+ return GG.maxtexlayers;
+}
+
int GPU_max_textures(void)
{
return GG.maxtextures;
@@ -142,6 +148,7 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
+ glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
if (GLEW_EXT_texture_filter_anisotropic)
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index ffc72718e42..56abe040f32 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -42,9 +42,8 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "intern/gpu_private.h"
-
-static ThreadLocal(void *) g_currentfb;
+#include "gpu_private.h"
+#include "gpu_context_private.h"
typedef enum {
GPU_FB_DEPTH_ATTACHMENT = 0,
@@ -69,6 +68,7 @@ typedef enum {
#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
+ GPUContext *ctx;
GLuint object;
GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
uint16_t dirty_flag;
@@ -121,7 +121,7 @@ static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
else
- return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;;
+ return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;
}
static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
@@ -167,22 +167,29 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
void gpu_framebuffer_module_init(void)
{
- BLI_thread_local_create(g_currentfb);
}
void gpu_framebuffer_module_exit(void)
{
- BLI_thread_local_delete(g_currentfb);
}
-static uint gpu_framebuffer_current_get(void)
+GPUFrameBuffer *GPU_framebuffer_active_get(void)
{
- return GET_UINT_FROM_POINTER(BLI_thread_local_get(g_currentfb));
+ GPUContext *ctx = GPU_context_active_get();
+ if (ctx) {
+ return gpu_context_active_framebuffer_get(ctx);
+ }
+ else {
+ return 0;
+ }
}
-static void gpu_framebuffer_current_set(uint object)
+static void gpu_framebuffer_current_set(GPUFrameBuffer *fb)
{
- BLI_thread_local_set(g_currentfb, SET_UINT_IN_POINTER(object));
+ GPUContext *ctx = GPU_context_active_get();
+ if (ctx) {
+ gpu_context_active_framebuffer_set(ctx, fb);
+ }
}
/* GPUFrameBuffer */
@@ -196,7 +203,9 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
static void gpu_framebuffer_init(GPUFrameBuffer *fb)
{
- glGenFramebuffers(1, &fb->object);
+ fb->object = GPU_fbo_alloc();
+ fb->ctx = GPU_context_active_get();
+ gpu_context_add_framebuffer(fb->ctx, fb);
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
@@ -207,11 +216,14 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
}
}
- /* This restores the framebuffer if it was bound */
- glDeleteFramebuffers(1, &fb->object);
+ if (fb->object != 0) {
+ /* This restores the framebuffer if it was bound */
+ GPU_fbo_free(fb->object, fb->ctx);
+ gpu_context_remove_framebuffer(fb->ctx, fb);
+ }
- if (gpu_framebuffer_current_get() == fb->object) {
- gpu_framebuffer_current_set(0);
+ if (GPU_framebuffer_active_get() == fb) {
+ gpu_framebuffer_current_set(NULL);
}
MEM_freeN(fb);
@@ -340,8 +352,9 @@ static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachme
if (attach->layer > -1) {
if (GPU_texture_cube(attach->tex)) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
- tex_bind, attach->mip);
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind, attach->mip);
}
else {
glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
@@ -363,7 +376,7 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
int numslots = 0;
- BLI_assert(gpu_framebuffer_current_get() == fb->object);
+ BLI_assert(GPU_framebuffer_active_get() == fb);
/* Update attachments */
for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
@@ -407,10 +420,10 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
if (fb->object == 0)
gpu_framebuffer_init(fb);
- if (gpu_framebuffer_current_get() != fb->object)
+ if (GPU_framebuffer_active_get() != fb)
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- gpu_framebuffer_current_set(fb->object);
+ gpu_framebuffer_current_set(fb);
if (fb->dirty_flag != 0)
gpu_framebuffer_update_attachments(fb);
@@ -431,20 +444,15 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_restore(void)
{
- if (gpu_framebuffer_current_get() != 0) {
+ if (GPU_framebuffer_active_get() != NULL) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- gpu_framebuffer_current_set(0);
+ gpu_framebuffer_current_set(NULL);
}
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- return (fb->object == gpu_framebuffer_current_get()) && (fb->object != 0);
-}
-
-unsigned int GPU_framebuffer_current_get(void)
-{
- return gpu_framebuffer_current_get();
+ return (fb == GPU_framebuffer_active_get()) && (fb->object != 0);
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
@@ -518,7 +526,7 @@ void GPU_framebuffer_read_color(
case 1: type = GL_RED; break;
case 2: type = GL_RG; break;
case 3: type = GL_RGB; break;
- case 4: type = GL_RGBA; break;
+ case 4: type = GL_RGBA; break;
default:
BLI_assert(false && "wrong number of read channels");
return;
@@ -535,7 +543,7 @@ void GPU_framebuffer_blit(
{
BLI_assert(blit_buffers != 0);
- GLuint prev_fb = gpu_framebuffer_current_get();
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
/* Framebuffers must be up to date. This simplify this function. */
if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
@@ -549,12 +557,14 @@ void GPU_framebuffer_blit(
const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
- GPUTexture *read_tex = (do_depth || do_stencil)
- ? framebuffer_get_depth_tex(fb_read)
- : framebuffer_get_color_tex(fb_read, read_slot);
- GPUTexture *write_tex = (do_depth || do_stencil)
- ? framebuffer_get_depth_tex(fb_write)
- : framebuffer_get_color_tex(fb_write, read_slot);
+ GPUTexture *read_tex = (
+ (do_depth || do_stencil) ?
+ framebuffer_get_depth_tex(fb_read) :
+ framebuffer_get_color_tex(fb_read, read_slot));
+ GPUTexture *write_tex = (
+ (do_depth || do_stencil) ?
+ framebuffer_get_depth_tex(fb_write) :
+ framebuffer_get_color_tex(fb_write, read_slot));
if (do_depth) {
BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
@@ -585,16 +595,17 @@ void GPU_framebuffer_blit(
GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
- glBlitFramebuffer(0, 0, fb_read->width, fb_read->height,
- 0, 0, fb_write->width, fb_write->height,
- mask, GL_NEAREST);
+ glBlitFramebuffer(
+ 0, 0, fb_read->width, fb_read->height,
+ 0, 0, fb_write->width, fb_write->height,
+ mask, GL_NEAREST);
/* Restore previous framebuffer */
- if (fb_write->object == prev_fb) {
+ if (fb_write == prev_fb) {
GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
}
else {
- glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object);
gpu_framebuffer_current_set(prev_fb);
}
}
@@ -608,13 +619,13 @@ void GPU_framebuffer_recursive_downsample(
void (*callback)(void *userData, int level), void *userData)
{
/* Framebuffer must be up to date and bound. This simplify this function. */
- if (gpu_framebuffer_current_get() != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
+ if (GPU_framebuffer_active_get() != fb || fb->dirty_flag != 0 || fb->object == 0) {
GPU_framebuffer_bind(fb);
}
/* HACK: We make the framebuffer appear not bound in order to
* not trigger any error in GPU_texture_bind(). */
- GLuint prev_fb = gpu_framebuffer_current_get();
- gpu_framebuffer_current_set(0);
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
+ gpu_framebuffer_current_set(NULL);
int i;
int current_dim[2] = {fb->width, fb->height};
@@ -679,7 +690,8 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool dept
ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->color = GPU_texture_create_2D_multisample(width, height,
+ ofs->color = GPU_texture_create_2D_multisample(
+ width, height,
(high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
if (depth) {
@@ -776,14 +788,16 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
/* create texture for new 'fbo_blit' */
glGenTextures(1, &tex_blit);
glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
- w, h, 0, GL_RGBA, type, 0);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
+ w, h, 0, GL_RGBA, type, 0);
/* write into new single-sample buffer */
glGenFramebuffers(1, &fbo_blit);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index 5f22b7f9279..9674cf0b9f7 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -15,22 +15,144 @@
* 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) 2016 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
- * Contributor(s): Mike Erwin
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
-#include "GPU_immediate.h"
-#include "GPU_matrix.h"
+/** \file blender/gpu/intern/gpu_immediate.c
+ * \ingroup gpu
+ *
+ * GPU immediate mode work-alike
+ */
+
#include "UI_resources.h"
-#include "BLI_utildefines.h"
+#include "GPU_attr_binding.h"
+#include "GPU_immediate.h"
+
+#include "gpu_attr_binding_private.h"
+#include "gpu_context_private.h"
+#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
+#include "gpu_vertex_format_private.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+/* necessary functions from matrix API */
+extern void GPU_matrix_bind(const GPUShaderInterface *);
+extern bool GPU_matrix_dirty_get(void);
+
+typedef struct {
+ /* TODO: organize this struct by frequency of change (run-time) */
+
+ GPUBatch *batch;
+ GPUContext *context;
+
+ /* current draw call */
+ GLubyte *buffer_data;
+ uint buffer_offset;
+ uint buffer_bytes_mapped;
+ uint vertex_len;
+ bool strict_vertex_len;
+ GPUPrimType prim_type;
+
+ GPUVertFormat vertex_format;
+
+ /* current vertex */
+ uint vertex_idx;
+ GLubyte *vertex_data;
+ uint16_t unassigned_attrib_bits; /* which attributes of current vertex have not been given values? */
+
+ GLuint vbo_id;
+ GLuint vao_id;
+
+ GLuint bound_program;
+ const GPUShaderInterface *shader_interface;
+ GPUAttrBinding attrib_binding;
+ uint16_t prev_enabled_attrib_bits; /* <-- only affects this VAO, so we're ok */
+} Immediate;
+
+/* size of internal buffer -- make this adjustable? */
+#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
+
+static bool initialized = false;
+static Immediate imm;
+
+void immInit(void)
+{
+#if TRUST_NO_ONE
+ assert(!initialized);
+#endif
+ memset(&imm, 0, sizeof(Immediate));
+
+ imm.vbo_id = GPU_buf_alloc();
+ glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
+
+ imm.prim_type = GPU_PRIM_NONE;
+ imm.strict_vertex_len = true;
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ initialized = true;
+}
+
+void immActivate(void)
+{
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */
+ assert(imm.vao_id == 0);
+#endif
+ imm.vao_id = GPU_vao_alloc();
+ imm.context = GPU_context_active_get();
+}
+
+void immDeactivate(void)
+{
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */
+ assert(imm.vao_id != 0);
+#endif
+ GPU_vao_free(imm.vao_id, imm.context);
+ imm.vao_id = 0;
+ imm.prev_enabled_attrib_bits = 0;
+}
+
+void immDestroy(void)
+{
+ GPU_buf_free(imm.vbo_id);
+ initialized = false;
+}
+
+GPUVertFormat *immVertexFormat(void)
+{
+ GPU_vertformat_clear(&imm.vertex_format);
+ return &imm.vertex_format;
+}
+
+void immBindProgram(GLuint program, const GPUShaderInterface *shaderface)
+{
+#if TRUST_NO_ONE
+ assert(imm.bound_program == 0);
+ assert(glIsProgram(program));
+#endif
+
+ imm.bound_program = program;
+ imm.shader_interface = shaderface;
+
+ if (!imm.vertex_format.packed)
+ VertexFormat_pack(&imm.vertex_format);
+
+ glUseProgram(program);
+ get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, shaderface);
+ GPU_matrix_bind(shaderface);
+}
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
{
@@ -38,6 +160,718 @@ void immBindBuiltinProgram(GPUBuiltinShader shader_id)
immBindProgram(shader->program, shader->interface);
}
+void immUnbindProgram(void)
+{
+#if TRUST_NO_ONE
+ assert(imm.bound_program != 0);
+#endif
+#if PROGRAM_NO_OPTI
+ glUseProgram(0);
+#endif
+ imm.bound_program = 0;
+}
+
+#if TRUST_NO_ONE
+static bool vertex_count_makes_sense_for_primitive(uint vertex_len, GPUPrimType prim_type)
+{
+ /* does vertex_len make sense for this primitive type? */
+ if (vertex_len == 0) {
+ return false;
+ }
+
+ switch (prim_type) {
+ case GPU_PRIM_POINTS:
+ return true;
+ case GPU_PRIM_LINES:
+ return vertex_len % 2 == 0;
+ case GPU_PRIM_LINE_STRIP:
+ case GPU_PRIM_LINE_LOOP:
+ return vertex_len >= 2;
+ case GPU_PRIM_LINE_STRIP_ADJ:
+ return vertex_len >= 4;
+ case GPU_PRIM_TRIS:
+ return vertex_len % 3 == 0;
+ case GPU_PRIM_TRI_STRIP:
+ case GPU_PRIM_TRI_FAN:
+ return vertex_len >= 3;
+ default:
+ return false;
+ }
+}
+#endif
+
+void immBegin(GPUPrimType prim_type, uint vertex_len)
+{
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */
+ assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
+#endif
+ imm.prim_type = prim_type;
+ imm.vertex_len = vertex_len;
+ imm.vertex_idx = 0;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+
+ /* how many bytes do we need for this draw call? */
+ const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len);
+
+#if TRUST_NO_ONE
+ assert(bytes_needed <= IMM_BUFFER_SIZE);
+#endif
+
+ glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
+
+ /* does the current buffer have enough room? */
+ const uint available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset;
+ /* ensure vertex data is aligned */
+ const uint pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); /* might waste a little space, but it's safe */
+ if ((bytes_needed + pre_padding) <= available_bytes) {
+ imm.buffer_offset += pre_padding;
+ }
+ else {
+ /* orphan this buffer & start with a fresh one */
+ /* this method works on all platforms, old & new */
+ glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
+
+ imm.buffer_offset = 0;
+ }
+
+/* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */
+
+ imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed,
+ GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
+
+#if TRUST_NO_ONE
+ assert(imm.buffer_data != NULL);
+#endif
+
+ imm.buffer_bytes_mapped = bytes_needed;
+ imm.vertex_data = imm.buffer_data;
+}
+
+void immBeginAtMost(GPUPrimType prim_type, uint vertex_len)
+{
+#if TRUST_NO_ONE
+ assert(vertex_len > 0);
+#endif
+
+ imm.strict_vertex_len = false;
+ immBegin(prim_type, vertex_len);
+}
+
+
+GPUBatch *immBeginBatch(GPUPrimType prim_type, uint vertex_len)
+{
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */
+ assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
+#endif
+ imm.prim_type = prim_type;
+ imm.vertex_len = vertex_len;
+ imm.vertex_idx = 0;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+
+ GPUVertBuf *verts = GPU_vertbuf_create_with_format(&imm.vertex_format);
+ GPU_vertbuf_data_alloc(verts, vertex_len);
+
+ imm.buffer_bytes_mapped = GPU_vertbuf_size_get(verts);
+ imm.vertex_data = verts->data;
+
+ imm.batch = GPU_batch_create_ex(prim_type, verts, NULL, GPU_BATCH_OWNS_VBO);
+ imm.batch->phase = GPU_BATCH_BUILDING;
+
+ return imm.batch;
+}
+
+GPUBatch *immBeginBatchAtMost(GPUPrimType prim_type, uint vertex_len)
+{
+ imm.strict_vertex_len = false;
+ return immBeginBatch(prim_type, vertex_len);
+}
+
+static void immDrawSetup(void)
+{
+ /* set up VAO -- can be done during Begin or End really */
+ glBindVertexArray(imm.vao_id);
+
+ /* enable/disable vertex attribs as needed */
+ if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits) {
+ for (uint loc = 0; loc < GPU_VERT_ATTR_MAX_LEN; ++loc) {
+ bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc);
+ bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc);
+
+ if (is_enabled && !was_enabled) {
+ glEnableVertexAttribArray(loc);
+ }
+ else if (was_enabled && !is_enabled) {
+ glDisableVertexAttribArray(loc);
+ }
+ }
+
+ imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits;
+ }
+
+ const uint stride = imm.vertex_format.stride;
+
+ for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) {
+ const GPUVertAttr *a = imm.vertex_format.attribs + a_idx;
+
+ const uint offset = imm.buffer_offset + a->offset;
+ const GLvoid *pointer = (const GLubyte *)0 + offset;
+
+ const uint loc = read_attrib_location(&imm.attrib_binding, a_idx);
+
+ switch (a->fetch_mode) {
+ case GPU_FETCH_FLOAT:
+ case GPU_FETCH_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer);
+ break;
+ case GPU_FETCH_INT_TO_FLOAT_UNIT:
+ glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer);
+ break;
+ case GPU_FETCH_INT:
+ glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer);
+ }
+ }
+
+ if (GPU_matrix_dirty_get()) {
+ GPU_matrix_bind(imm.shader_interface);
+ }
+}
+
+void immEnd(void)
+{
+#if TRUST_NO_ONE
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+
+ uint buffer_bytes_used;
+ if (imm.strict_vertex_len) {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx == imm.vertex_len); /* with all vertices defined */
+#endif
+ buffer_bytes_used = imm.buffer_bytes_mapped;
+ }
+ else {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx <= imm.vertex_len);
+#endif
+ if (imm.vertex_idx == imm.vertex_len) {
+ buffer_bytes_used = imm.buffer_bytes_mapped;
+ }
+ else {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type));
+#endif
+ imm.vertex_len = imm.vertex_idx;
+ buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len);
+ /* unused buffer bytes are available to the next immBegin */
+ }
+ /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used);
+ }
+
+ if (imm.batch) {
+ if (buffer_bytes_used != imm.buffer_bytes_mapped) {
+ GPU_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len);
+ /* TODO: resize only if vertex count is much smaller */
+ }
+ GPU_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface);
+ imm.batch->phase = GPU_BATCH_READY_TO_DRAW;
+ imm.batch = NULL; /* don't free, batch belongs to caller */
+ }
+ else {
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ if (imm.vertex_len > 0) {
+ immDrawSetup();
+ glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ /* prep for next immBegin */
+ imm.buffer_offset += buffer_bytes_used;
+ }
+
+ /* prep for next immBegin */
+ imm.prim_type = GPU_PRIM_NONE;
+ imm.strict_vertex_len = true;
+}
+
+static void setAttribValueBit(uint attrib_id)
+{
+ uint16_t mask = 1 << attrib_id;
+#if TRUST_NO_ONE
+ assert(imm.unassigned_attrib_bits & mask); /* not already set */
+#endif
+ imm.unassigned_attrib_bits &= ~mask;
+}
+
+
+/* --- generic attribute functions --- */
+
+void immAttrib1f(uint attrib_id, float x)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_F32);
+ assert(attrib->comp_len == 1);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ float *data = (float *)(imm.vertex_data + attrib->offset);
+/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */
+
+ data[0] = x;
+}
+
+void immAttrib2f(uint attrib_id, float x, float y)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_F32);
+ assert(attrib->comp_len == 2);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ float *data = (float *)(imm.vertex_data + attrib->offset);
+/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */
+
+ data[0] = x;
+ data[1] = y;
+}
+
+void immAttrib3f(uint attrib_id, float x, float y, float z)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_F32);
+ assert(attrib->comp_len == 3);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ float *data = (float *)(imm.vertex_data + attrib->offset);
+/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */
+
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+}
+
+void immAttrib4f(uint attrib_id, float x, float y, float z, float w)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_F32);
+ assert(attrib->comp_len == 4);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ float *data = (float *)(imm.vertex_data + attrib->offset);
+/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */
+
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+ data[3] = w;
+}
+
+void immAttrib1u(uint attrib_id, uint x)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_U32);
+ assert(attrib->comp_len == 1);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ uint *data = (uint *)(imm.vertex_data + attrib->offset);
+
+ data[0] = x;
+}
+
+void immAttrib2i(uint attrib_id, int x, int y)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_I32);
+ assert(attrib->comp_len == 2);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ int *data = (int *)(imm.vertex_data + attrib->offset);
+
+ data[0] = x;
+ data[1] = y;
+}
+
+void immAttrib2s(uint attrib_id, short x, short y)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_I16);
+ assert(attrib->comp_len == 2);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ short *data = (short *)(imm.vertex_data + attrib->offset);
+
+ data[0] = x;
+ data[1] = y;
+}
+
+void immAttrib2fv(uint attrib_id, const float data[2])
+{
+ immAttrib2f(attrib_id, data[0], data[1]);
+}
+
+void immAttrib3fv(uint attrib_id, const float data[3])
+{
+ immAttrib3f(attrib_id, data[0], data[1], data[2]);
+}
+
+void immAttrib4fv(uint attrib_id, const float data[4])
+{
+ immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]);
+}
+
+void immAttrib3ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_U8);
+ assert(attrib->comp_len == 3);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ GLubyte *data = imm.vertex_data + attrib->offset;
+/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */
+
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+}
+
+void immAttrib4ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ GPUVertAttr *attrib = imm.vertex_format.attribs + attrib_id;
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(attrib->comp_type == GPU_COMP_U8);
+ assert(attrib->comp_len == 4);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+
+ GLubyte *data = imm.vertex_data + attrib->offset;
+/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */
+
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ data[3] = a;
+}
+
+void immAttrib3ubv(uint attrib_id, const unsigned char data[3])
+{
+ immAttrib3ub(attrib_id, data[0], data[1], data[2]);
+}
+
+void immAttrib4ubv(uint attrib_id, const unsigned char data[4])
+{
+ immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]);
+}
+
+void immSkipAttrib(uint attrib_id)
+{
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attr_len);
+ assert(imm.vertex_idx < imm.vertex_len);
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+#endif
+ setAttribValueBit(attrib_id);
+}
+
+static void immEndVertex(void) /* and move on to the next vertex */
+{
+#if TRUST_NO_ONE
+ assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+ assert(imm.vertex_idx < imm.vertex_len);
+#endif
+
+ /* have all attribs been assigned values?
+ * if not, copy value from previous vertex */
+ if (imm.unassigned_attrib_bits) {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx > 0); /* first vertex must have all attribs specified */
+#endif
+ for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) {
+ if ((imm.unassigned_attrib_bits >> a_idx) & 1) {
+ const GPUVertAttr *a = imm.vertex_format.attribs + a_idx;
+
+/* printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx); */
+
+ GLubyte *data = imm.vertex_data + a->offset;
+ memcpy(data, data - imm.vertex_format.stride, a->sz);
+ /* TODO: consolidate copy of adjacent attributes */
+ }
+ }
+ }
+
+ imm.vertex_idx++;
+ imm.vertex_data += imm.vertex_format.stride;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+}
+
+void immVertex2f(uint attrib_id, float x, float y)
+{
+ immAttrib2f(attrib_id, x, y);
+ immEndVertex();
+}
+
+void immVertex3f(uint attrib_id, float x, float y, float z)
+{
+ immAttrib3f(attrib_id, x, y, z);
+ immEndVertex();
+}
+
+void immVertex4f(uint attrib_id, float x, float y, float z, float w)
+{
+ immAttrib4f(attrib_id, x, y, z, w);
+ immEndVertex();
+}
+
+void immVertex2i(uint attrib_id, int x, int y)
+{
+ immAttrib2i(attrib_id, x, y);
+ immEndVertex();
+}
+
+void immVertex2s(uint attrib_id, short x, short y)
+{
+ immAttrib2s(attrib_id, x, y);
+ immEndVertex();
+}
+
+void immVertex2fv(uint attrib_id, const float data[2])
+{
+ immAttrib2f(attrib_id, data[0], data[1]);
+ immEndVertex();
+}
+
+void immVertex3fv(uint attrib_id, const float data[3])
+{
+ immAttrib3f(attrib_id, data[0], data[1], data[2]);
+ immEndVertex();
+}
+
+void immVertex2iv(uint attrib_id, const int data[2])
+{
+ immAttrib2i(attrib_id, data[0], data[1]);
+ immEndVertex();
+}
+
+
+/* --- generic uniform functions --- */
+
+#if 0
+# if TRUST_NO_ONE
+# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); assert(uniform);
+# else
+# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform(imm.shader_interface, name);
+# endif
+#else
+ /* NOTE: It is possible to have uniform fully optimized out from the shader.
+ * In this case we can't assert failure or allow NULL-pointer dereference.
+ * TODO(sergey): How can we detect existing-but-optimized-out uniform but still
+ * catch typos in uniform names passed to immUniform*() functions? */
+# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); if (uniform == NULL) return;
+#endif
+
+void immUniform1f(const char *name, float x)
+{
+ GET_UNIFORM
+ glUniform1f(uniform->location, x);
+}
+
+void immUniform2f(const char *name, float x, float y)
+{
+ GET_UNIFORM
+ glUniform2f(uniform->location, x, y);
+}
+
+void immUniform2fv(const char *name, const float data[2])
+{
+ GET_UNIFORM
+ glUniform2fv(uniform->location, 1, data);
+}
+
+void immUniform3f(const char *name, float x, float y, float z)
+{
+ GET_UNIFORM
+ glUniform3f(uniform->location, x, y, z);
+}
+
+void immUniform3fv(const char *name, const float data[3])
+{
+ GET_UNIFORM
+ glUniform3fv(uniform->location, 1, data);
+}
+
+/* can increase this limit or move to another file */
+#define MAX_UNIFORM_NAME_LEN 60
+
+void immUniformArray3fv(const char *bare_name, const float *data, int count)
+{
+ /* look up "name[0]" when given "name" */
+ const size_t len = strlen(bare_name);
+#if TRUST_NO_ONE
+ assert(len <= MAX_UNIFORM_NAME_LEN);
+#endif
+ char name[MAX_UNIFORM_NAME_LEN];
+ strcpy(name, bare_name);
+ name[len + 0] = '[';
+ name[len + 1] = '0';
+ name[len + 2] = ']';
+ name[len + 3] = '\0';
+
+ GET_UNIFORM
+ glUniform3fv(uniform->location, count, data);
+}
+
+void immUniform4f(const char *name, float x, float y, float z, float w)
+{
+ GET_UNIFORM
+ glUniform4f(uniform->location, x, y, z, w);
+}
+
+void immUniform4fv(const char *name, const float data[4])
+{
+ GET_UNIFORM
+ glUniform4fv(uniform->location, 1, data);
+}
+
+void immUniformArray4fv(const char *bare_name, const float *data, int count)
+{
+ /* look up "name[0]" when given "name" */
+ const size_t len = strlen(bare_name);
+#if TRUST_NO_ONE
+ assert(len <= MAX_UNIFORM_NAME_LEN);
+#endif
+ char name[MAX_UNIFORM_NAME_LEN];
+ strcpy(name, bare_name);
+ name[len + 0] = '[';
+ name[len + 1] = '0';
+ name[len + 2] = ']';
+ name[len + 3] = '\0';
+
+ GET_UNIFORM
+ glUniform4fv(uniform->location, count, data);
+}
+
+void immUniformMatrix4fv(const char *name, const float data[4][4])
+{
+ GET_UNIFORM
+ glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data);
+}
+
+void immUniform1i(const char *name, int x)
+{
+ GET_UNIFORM
+ glUniform1i(uniform->location, x);
+}
+
+void immUniform4iv(const char *name, const int data[4])
+{
+ GET_UNIFORM
+ glUniform4iv(uniform->location, 1, data);
+}
+
+/* --- convenience functions for setting "uniform vec4 color" --- */
+
+void immUniformColor4f(float r, float g, float b, float a)
+{
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(imm.shader_interface, GPU_UNIFORM_COLOR);
+#if TRUST_NO_ONE
+ assert(uniform != NULL);
+#endif
+ glUniform4f(uniform->location, r, g, b, a);
+}
+
+void immUniformColor4fv(const float rgba[4])
+{
+ immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
+}
+
+void immUniformColor3f(float r, float g, float b)
+{
+ immUniformColor4f(r, g, b, 1.0f);
+}
+
+void immUniformColor3fv(const float rgb[3])
+{
+ immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f);
+}
+
+void immUniformColor3fvAlpha(const float rgb[3], float a)
+{
+ immUniformColor4f(rgb[0], rgb[1], rgb[2], a);
+}
+
+/* TODO: v-- treat as sRGB? --v */
+
+void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
+{
+ const float scale = 1.0f / 255.0f;
+ immUniformColor4f(scale * r, scale * g, scale * b, 1.0f);
+}
+
+void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ const float scale = 1.0f / 255.0f;
+ immUniformColor4f(scale * r, scale * g, scale * b, scale * a);
+}
+
+void immUniformColor3ubv(const unsigned char rgb[3])
+{
+ immUniformColor3ub(rgb[0], rgb[1], rgb[2]);
+}
+
+void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char alpha)
+{
+ immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha);
+}
+
+void immUniformColor4ubv(const unsigned char rgba[4])
+{
+ immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]);
+}
+
void immUniformThemeColor(int color_id)
{
float color[4];
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
index 30672af9c02..8384ef3b5d0 100644
--- a/source/blender/gpu/intern/gpu_immediate_util.c
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -18,8 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file source/blender/gpu/intern/gpu_immediate_util.c
+/** \file blender/gpu/intern/gpu_immediate_util.c
* \ingroup gpu
+ *
+ * GPU immediate mode drawing utilities
*/
#include <stdio.h>
@@ -66,6 +68,72 @@ static const int cube_line_index[12][2] = {
{6, 7},
};
+void immRectf(uint pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ immEnd();
+}
+
+void immRecti(uint pos, int x1, int y1, int x2, int y2)
+{
+ immBegin(GPU_PRIM_TRI_FAN, 4);
+ immVertex2i(pos, x1, y1);
+ immVertex2i(pos, x2, y1);
+ immVertex2i(pos, x2, y2);
+ immVertex2i(pos, x1, y2);
+ immEnd();
+}
+
+void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4])
+{
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y2);
+}
+
+void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4])
+{
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x2, y1);
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x2, y2);
+
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x2, y2);
+ immAttrib4fv(col, color);
+ immVertex2i(pos, x1, y2);
+}
+
+#if 0 /* more complete version in case we want that */
+void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = add_attrib(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ immRecti(pos, x1, y1, x2, y2);
+ immUnbindProgram();
+}
+#endif
+
/**
* Pack color into 3 bytes
*
@@ -85,7 +153,7 @@ void imm_cpack(unsigned int x)
}
static void imm_draw_circle(
- Gwn_PrimType prim_type, const uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+ GPUPrimType prim_type, const uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
{
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; ++i) {
@@ -107,7 +175,7 @@ static void imm_draw_circle(
*/
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
{
- imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments);
+ imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments);
}
/**
@@ -122,23 +190,23 @@ void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nse
*/
void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
{
- imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments);
+ imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments);
}
void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
{
- imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments);
+ imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments);
}
void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
{
- imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments);
+ imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments);
}
/**
* \note We could have `imm_draw_lined_disk_partial` but currently there is no need.
*/
static void imm_draw_disk_partial(
- Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ GPUPrimType 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 */
@@ -175,11 +243,11 @@ void imm_draw_disk_partial_fill_2d(
unsigned pos, float x, float y,
float rad_inner, float rad_outer, int nsegments, float start, float sweep)
{
- imm_draw_disk_partial(GWN_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep);
+ imm_draw_disk_partial(GPU_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep);
}
static void imm_draw_circle_3D(
- Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ GPUPrimType prim_type, unsigned pos, float x, float y,
float rad, int nsegments)
{
immBegin(prim_type, nsegments);
@@ -192,26 +260,26 @@ static void imm_draw_circle_3D(
void imm_draw_circle_wire_3d(unsigned pos, float x, float y, float rad, int nsegments)
{
- imm_draw_circle_3D(GWN_PRIM_LINE_LOOP, pos, x, y, rad, nsegments);
+ imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, rad, nsegments);
}
void imm_draw_circle_fill_3d(unsigned pos, float x, float y, float rad, int nsegments)
{
- imm_draw_circle_3D(GWN_PRIM_TRI_FAN, pos, x, y, rad, nsegments);
+ imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, rad, nsegments);
}
/**
-* Draw a lined box.
-*
-* \param pos The vertex attribute number for position.
-* \param x1 left.
-* \param y1 bottom.
-* \param x2 right.
-* \param y2 top.
-*/
+ * Draw a lined box.
+ *
+ * \param pos The vertex attribute number for position.
+ * \param x1 left.
+ * \param y1 bottom.
+ * \param x2 right.
+ * \param y2 top.
+ */
void imm_draw_box_wire_2d(unsigned pos, float x1, float y1, float x2, float y2)
{
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x1, y2);
immVertex2f(pos, x2, y2);
@@ -221,8 +289,8 @@ void imm_draw_box_wire_2d(unsigned pos, float x1, float y1, float x2, float y2)
void imm_draw_box_wire_3d(unsigned pos, float x1, float y1, float x2, float y2)
{
- /* use this version when Gwn_VertFormat has a vec3 position */
- immBegin(GWN_PRIM_LINE_LOOP, 4);
+ /* use this version when GPUVertFormat has a vec3 position */
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex3f(pos, x1, y1, 0.0f);
immVertex3f(pos, x1, y2, 0.0f);
immVertex3f(pos, x2, y2, 0.0f);
@@ -235,7 +303,7 @@ void imm_draw_box_wire_3d(unsigned pos, float x1, float y1, float x2, float y2)
*/
void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
{
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f);
@@ -255,7 +323,7 @@ void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
}
- immBegin(GWN_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
+ immBegin(GPU_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) {
immVertex3fv(pos, coords[cube_quad_index[i][0]]);
immVertex3fv(pos, coords[cube_quad_index[i][1]]);
@@ -276,7 +344,7 @@ void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
}
- immBegin(GWN_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
+ immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
immVertex3fv(pos, coords[cube_line_index[i][0]]);
immVertex3fv(pos, coords[cube_line_index[i][1]]);
@@ -285,21 +353,21 @@ void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
}
/**
-* 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.
-*/
+ * 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_draw_cylinder_fill_normal_3d(
unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
{
- immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ immBegin(GPU_PRIM_TRIS, 6 * slices * stacks);
for (int i = 0; i < slices; ++i) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
@@ -316,10 +384,10 @@ void imm_draw_cylinder_fill_normal_3d(
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 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 */
@@ -350,7 +418,7 @@ void imm_draw_cylinder_fill_normal_3d(
void imm_draw_cylinder_wire_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
{
- immBegin(GWN_PRIM_LINES, 6 * slices * stacks);
+ immBegin(GPU_PRIM_LINES, 6 * slices * stacks);
for (int i = 0; i < slices; ++i) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
@@ -387,7 +455,7 @@ void imm_draw_cylinder_wire_3d(unsigned int pos, float base, float top, float he
void imm_draw_cylinder_fill_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
{
- immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ immBegin(GPU_PRIM_TRIS, 6 * slices * stacks);
for (int i = 0; i < slices; ++i) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 78d4f491b66..55d0466c929 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -57,8 +57,6 @@ void GPU_init(void)
gpu_extensions_init(); /* must come first */
- GPU_texture_orphans_init();
- GPU_material_orphans_init();
gpu_codegen_init();
gpu_framebuffer_module_init();
@@ -84,9 +82,6 @@ void GPU_exit(void)
gpu_batch_exit();
- GPU_texture_orphans_exit();
- GPU_material_orphans_exit();
-
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index bd0e35f5ab6..b03df2c643c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -36,32 +36,19 @@
#include "MEM_guardedalloc.h"
-#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_rand.h"
-#include "BLI_threads.h"
-
-#include "BKE_anim.h"
-#include "BKE_colorband.h"
-#include "BKE_colortools.h"
-#include "BKE_global.h"
-#include "BKE_image.h"
-#include "BKE_layer.h"
+#include "BLI_string.h"
+
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
-#include "IMB_imbuf_types.h"
-
-#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -75,10 +62,13 @@
# include "BKE_DerivedMesh.h"
#endif
-static ListBase g_orphaned_mat = {NULL, NULL};
-static ThreadMutex g_orphan_lock;
-
/* Structs */
+#define MAX_COLOR_BAND 128
+
+typedef struct GPUColorBandBuilder {
+ float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
+ int current_layer;
+} GPUColorBandBuilder;
struct GPUMaterial {
Scene *scene; /* DEPRECATED was only usefull for lamps */
@@ -125,6 +115,9 @@ struct GPUMaterial {
*/
int domain;
+ /* Only used by Eevee to know which bsdf are used. */
+ int flag;
+
/* Used by 2.8 pipeline */
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
@@ -137,6 +130,13 @@ struct GPUMaterial {
short int sss_falloff;
float sss_sharpness;
bool sss_dirty;
+
+ GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
+ GPUColorBandBuilder *coba_builder;
+
+#ifndef NDEBUG
+ char name[64];
+#endif
};
enum {
@@ -147,6 +147,47 @@ enum {
/* Functions */
+/* Returns the adress of the future pointer to coba_tex */
+GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row)
+{
+ /* In order to put all the colorbands into one 1D array texture,
+ * we need them to be the same size. */
+ BLI_assert(size == CM_TABLE + 1);
+
+ if (mat->coba_builder == NULL) {
+ mat->coba_builder = MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder");
+ mat->coba_builder->current_layer = 0;
+ }
+
+ int layer = mat->coba_builder->current_layer;
+ *row = (float)layer;
+
+ if (*row == MAX_COLOR_BAND) {
+ printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n");
+ }
+ else {
+ float *dst = (float *)mat->coba_builder->pixels[layer];
+ memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4);
+ mat->coba_builder->current_layer += 1;
+ }
+
+ return &mat->coba_tex;
+}
+
+static void gpu_material_ramp_texture_build(GPUMaterial *mat)
+{
+ if (mat->coba_builder == NULL)
+ return;
+
+ GPUColorBandBuilder *builder = mat->coba_builder;
+
+ mat->coba_tex = GPU_texture_create_1D_array(CM_TABLE + 1, builder->current_layer, GPU_RGBA16F,
+ (float *)builder->pixels, NULL);
+
+ MEM_freeN(builder);
+ mat->coba_builder = NULL;
+}
+
static void gpu_material_free_single(GPUMaterial *material)
{
/* Cancel / wait any pending lazy compilation. */
@@ -155,64 +196,33 @@ static void gpu_material_free_single(GPUMaterial *material)
GPU_pass_free_nodes(&material->nodes);
GPU_inputs_free(&material->inputs);
- if (material->pass)
+ if (material->pass != NULL) {
GPU_pass_release(material->pass);
-
+ }
if (material->ubo != NULL) {
GPU_uniformbuffer_free(material->ubo);
}
-
if (material->sss_tex_profile != NULL) {
GPU_texture_free(material->sss_tex_profile);
}
-
if (material->sss_profile != NULL) {
GPU_uniformbuffer_free(material->sss_profile);
}
+ if (material->coba_tex != NULL) {
+ GPU_texture_free(material->coba_tex);
+ }
}
void GPU_material_free(ListBase *gpumaterial)
{
for (LinkData *link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
-
- /* TODO(fclem): Check if the thread has an ogl context. */
- if (BLI_thread_is_main()) {
- gpu_material_free_single(material);
- MEM_freeN(material);
- }
- else {
- BLI_mutex_lock(&g_orphan_lock);
- BLI_addtail(&g_orphaned_mat, BLI_genericNodeN(material));
- BLI_mutex_unlock(&g_orphan_lock);
- }
+ gpu_material_free_single(material);
+ MEM_freeN(material);
}
BLI_freelistN(gpumaterial);
}
-void GPU_material_orphans_init(void)
-{
- BLI_mutex_init(&g_orphan_lock);
-}
-
-void GPU_material_orphans_delete(void)
-{
- BLI_mutex_lock(&g_orphan_lock);
- LinkData *link;
- while ((link = BLI_pophead(&g_orphaned_mat))) {
- gpu_material_free_single((GPUMaterial *)link->data);
- MEM_freeN(link->data);
- MEM_freeN(link);
- }
- BLI_mutex_unlock(&g_orphan_lock);
-}
-
-void GPU_material_orphans_exit(void)
-{
- GPU_material_orphans_delete();
- BLI_mutex_end(&g_orphan_lock);
-}
-
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
{
return material->builtins;
@@ -608,6 +618,16 @@ bool GPU_material_use_domain_volume(GPUMaterial *mat)
return (mat->domain & GPU_DOMAIN_VOLUME);
}
+void GPU_material_flag_set(GPUMaterial *mat, GPUMatFlag flag)
+{
+ mat->flag |= flag;
+}
+
+bool GPU_material_flag_get(GPUMaterial *mat, GPUMatFlag flag)
+{
+ return (mat->flag & flag);
+}
+
GPUMaterial *GPU_material_from_nodetree_find(
ListBase *gpumaterials, const void *engine_type, int options)
{
@@ -630,7 +650,7 @@ GPUMaterial *GPU_material_from_nodetree_find(
*/
GPUMaterial *GPU_material_from_nodetree(
Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, const char *name)
{
LinkData *link;
bool has_volume_output, has_surface_output;
@@ -643,8 +663,17 @@ GPUMaterial *GPU_material_from_nodetree(
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
+#ifndef NDEBUG
+ BLI_snprintf(mat->name, sizeof(mat->name), "%s", name);
+#else
+ UNUSED_VARS(name);
+#endif
+
+ /* localize tree to create links for reroute and mute */
+ bNodeTree *localtree = ntreeLocalize(ntree);
+ ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
- ntreeGPUMaterialNodes(ntree, mat, &has_surface_output, &has_volume_output);
+ gpu_material_ramp_texture_build(mat);
if (has_surface_output) {
mat->domain |= GPU_DOMAIN_SURFACE;
@@ -659,14 +688,15 @@ GPUMaterial *GPU_material_from_nodetree(
GPU_nodes_prune(&mat->nodes, mat->outlink);
GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
/* Create source code and search pass cache for an already compiled version. */
- mat->pass = GPU_generate_pass_new(mat,
- mat->outlink,
- &mat->attribs,
- &mat->nodes,
- vert_code,
- geom_code,
- frag_lib,
- defines);
+ mat->pass = GPU_generate_pass_new(
+ mat,
+ mat->outlink,
+ &mat->attribs,
+ &mat->nodes,
+ vert_code,
+ geom_code,
+ frag_lib,
+ defines);
if (mat->pass == NULL) {
/* We had a cache hit and the shader has already failed to compile. */
@@ -688,6 +718,11 @@ GPUMaterial *GPU_material_from_nodetree(
mat->status = GPU_MAT_FAILED;
}
+ /* Only free after GPU_pass_shader_get where GPUUniformBuffer
+ * read data from the local tree. */
+ ntreeFreeTree(localtree);
+ MEM_freeN(localtree);
+
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simply do not use
* the actual shader on drawing */
@@ -707,7 +742,12 @@ void GPU_material_compile(GPUMaterial *mat)
/* NOTE: The shader may have already been compiled here since we are
* sharing GPUShader across GPUMaterials. In this case it's a no-op. */
- GPU_pass_compile(mat->pass);
+#ifndef NDEBUG
+ GPU_pass_compile(mat->pass, mat->name);
+#else
+ GPU_pass_compile(mat->pass, __func__);
+#endif
+
GPUShader *sh = GPU_pass_shader_get(mat->pass);
if (sh != NULL) {
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index b6214f2778b..0fa4a158c00 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -29,7 +29,7 @@
* \ingroup gpu
*/
-#include "../../../intern/gawain/gawain/gwn_shader_interface.h"
+#include "GPU_shader_interface.h"
#define SUPPRESS_GENERIC_MATRIX_API
#define USE_GPU_PY_MATRIX_API /* only so values are declared */
@@ -86,7 +86,7 @@ static MatrixState state = {
#define ProjectionStack state.projection_stack
#define Projection ProjectionStack.stack[ProjectionStack.top]
-void gpuMatrixReset(void)
+void GPU_matrix_reset(void)
{
state.model_view_stack.top = 0;
state.projection_stack.top = 0;
@@ -110,7 +110,7 @@ static void checkmat(cosnt float *m)
}
}
-#define CHECKMAT(m) checkmat((const float*)m)
+#define CHECKMAT(m) checkmat((const float *)m)
#else
@@ -119,76 +119,76 @@ static void checkmat(cosnt float *m)
#endif
-void gpuPushMatrix(void)
+void GPU_matrix_push(void)
{
BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH);
ModelViewStack.top++;
copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]);
}
-void gpuPopMatrix(void)
+void GPU_matrix_pop(void)
{
BLI_assert(ModelViewStack.top > 0);
ModelViewStack.top--;
state.dirty = true;
}
-void gpuPushProjectionMatrix(void)
+void GPU_matrix_push_projection(void)
{
BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH);
ProjectionStack.top++;
copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]);
}
-void gpuPopProjectionMatrix(void)
+void GPU_matrix_pop_projection(void)
{
BLI_assert(ProjectionStack.top > 0);
ProjectionStack.top--;
state.dirty = true;
}
-void gpuLoadMatrix(const float m[4][4])
+void GPU_matrix_set(const float m[4][4])
{
copy_m4_m4(ModelView, m);
CHECKMAT(ModelView3D);
state.dirty = true;
}
-void gpuLoadIdentityProjectionMatrix(void)
+void GPU_matrix_identity_projection_set(void)
{
unit_m4(Projection);
CHECKMAT(Projection3D);
state.dirty = true;
}
-void gpuLoadProjectionMatrix(const float m[4][4])
+void GPU_matrix_projection_set(const float m[4][4])
{
copy_m4_m4(Projection, m);
CHECKMAT(Projection3D);
state.dirty = true;
}
-void gpuLoadIdentity(void)
+void GPU_matrix_identity_set(void)
{
unit_m4(ModelView);
state.dirty = true;
}
-void gpuTranslate2f(float x, float y)
+void GPU_matrix_translate_2f(float x, float y)
{
Mat4 m;
unit_m4(m);
m[3][0] = x;
m[3][1] = y;
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
}
-void gpuTranslate2fv(const float vec[2])
+void GPU_matrix_translate_2fv(const float vec[2])
{
- gpuTranslate2f(vec[0], vec[1]);
+ GPU_matrix_translate_2f(vec[0], vec[1]);
}
-void gpuTranslate3f(float x, float y, float z)
+void GPU_matrix_translate_3f(float x, float y, float z)
{
#if 1
translate_m4(ModelView, x, y, z);
@@ -199,61 +199,61 @@ void gpuTranslate3f(float x, float y, float z)
m[3][0] = x;
m[3][1] = y;
m[3][2] = z;
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
#endif
state.dirty = true;
}
-void gpuTranslate3fv(const float vec[3])
+void GPU_matrix_translate_3fv(const float vec[3])
{
- gpuTranslate3f(vec[0], vec[1], vec[2]);
+ GPU_matrix_translate_3f(vec[0], vec[1], vec[2]);
}
-void gpuScaleUniform(float factor)
+void GPU_matrix_scale_1f(float factor)
{
Mat4 m;
scale_m4_fl(m, factor);
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
}
-void gpuScale2f(float x, float y)
+void GPU_matrix_scale_2f(float x, float y)
{
Mat4 m = {{0.0f}};
m[0][0] = x;
m[1][1] = y;
m[2][2] = 1.0f;
m[3][3] = 1.0f;
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
}
-void gpuScale2fv(const float vec[2])
+void GPU_matrix_scale_2fv(const float vec[2])
{
- gpuScale2f(vec[0], vec[1]);
+ GPU_matrix_scale_2f(vec[0], vec[1]);
}
-void gpuScale3f(float x, float y, float z)
+void GPU_matrix_scale_3f(float x, float y, float z)
{
Mat4 m = {{0.0f}};
m[0][0] = x;
m[1][1] = y;
m[2][2] = z;
m[3][3] = 1.0f;
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
}
-void gpuScale3fv(const float vec[3])
+void GPU_matrix_scale_3fv(const float vec[3])
{
- gpuScale3f(vec[0], vec[1], vec[2]);
+ GPU_matrix_scale_3f(vec[0], vec[1], vec[2]);
}
-void gpuMultMatrix(const float m[4][4])
+void GPU_matrix_mul(const float m[4][4])
{
mul_m4_m4_post(ModelView, m);
CHECKMAT(ModelView);
state.dirty = true;
}
-void gpuRotate2D(float deg)
+void GPU_matrix_rotate_2d(float deg)
{
/* essentially RotateAxis('Z')
* TODO: simpler math for 2D case
@@ -261,20 +261,20 @@ void gpuRotate2D(float deg)
rotate_m4(ModelView, 'Z', DEG2RADF(deg));
}
-void gpuRotate3f(float deg, float x, float y, float z)
+void GPU_matrix_rotate_3f(float deg, float x, float y, float z)
{
const float axis[3] = {x, y, z};
- gpuRotate3fv(deg, axis);
+ GPU_matrix_rotate_3fv(deg, axis);
}
-void gpuRotate3fv(float deg, const float axis[3])
+void GPU_matrix_rotate_3fv(float deg, const float axis[3])
{
Mat4 m;
axis_angle_to_mat4(m, axis, DEG2RADF(deg));
- gpuMultMatrix(m);
+ GPU_matrix_mul(m);
}
-void gpuRotateAxis(float deg, char axis)
+void GPU_matrix_rotate_axis(float deg, char axis)
{
/* rotate_m4 works in place */
rotate_m4(ModelView, axis, DEG2RADF(deg));
@@ -398,14 +398,14 @@ static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3
state.dirty = true;
}
-void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
+void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far)
{
mat4_ortho_set(Projection, left, right, bottom, top, near, far);
CHECKMAT(Projection);
state.dirty = true;
}
-void gpuOrtho2D(float left, float right, float bottom, float top)
+void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top)
{
Mat4 m;
mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
@@ -413,21 +413,21 @@ void gpuOrtho2D(float left, float right, float bottom, float top)
state.dirty = true;
}
-void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
+void GPU_matrix_frustum_set(float left, float right, float bottom, float top, float near, float far)
{
mat4_frustum_set(Projection, left, right, bottom, top, near, far);
CHECKMAT(Projection);
state.dirty = true;
}
-void gpuPerspective(float fovy, float aspect, float near, float far)
+void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far)
{
float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near;
float half_width = half_height * aspect;
- gpuFrustum(-half_width, +half_width, -half_height, +half_height, near, far);
+ GPU_matrix_frustum_set(-half_width, +half_width, -half_height, +half_height, near, far);
}
-void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
+void GPU_matrix_look_at(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
{
Mat4 cm;
float lookdir[3];
@@ -439,11 +439,11 @@ void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY,
mat4_look_from_origin(cm, lookdir, camup);
- gpuMultMatrix(cm);
- gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
+ GPU_matrix_mul(cm);
+ GPU_matrix_translate_3f(-eyeX, -eyeY, -eyeZ);
}
-void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
+void GPU_matrix_project(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
{
float v[4];
@@ -459,7 +459,7 @@ void gpuProject(const float world[3], const float model[4][4], const float proj[
win[2] = (v[2] + 1) * 0.5f;
}
-bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3])
+bool GPU_matrix_unproject(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];
@@ -497,7 +497,7 @@ bool gpuUnProject(const float win[3], const float model[4][4], const float proj[
return true;
}
-const float (*gpuGetModelViewMatrix(float m[4][4]))[4]
+const float (*GPU_matrix_model_view_get(float m[4][4]))[4]
{
if (m) {
copy_m4_m4(m, ModelView);
@@ -508,7 +508,7 @@ const float (*gpuGetModelViewMatrix(float m[4][4]))[4]
}
}
-const float (*gpuGetProjectionMatrix(float m[4][4]))[4]
+const float (*GPU_matrix_projection_get(float m[4][4]))[4]
{
if (m) {
copy_m4_m4(m, Projection);
@@ -519,7 +519,7 @@ const float (*gpuGetProjectionMatrix(float m[4][4]))[4]
}
}
-const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4]
+const float (*GPU_matrix_model_view_projection_get(float m[4][4]))[4]
{
if (m == NULL) {
static Mat4 temp;
@@ -530,14 +530,14 @@ const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4]
return m;
}
-const float (*gpuGetNormalMatrix(float m[3][3]))[3]
+const float (*GPU_matrix_normal_get(float m[3][3]))[3]
{
if (m == NULL) {
static Mat3 temp3;
m = temp3;
}
- copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix(NULL));
+ copy_m3_m4(m, (const float (*)[4])GPU_matrix_model_view_get(NULL));
invert_m3(m);
transpose_m3(m);
@@ -545,40 +545,40 @@ const float (*gpuGetNormalMatrix(float m[3][3]))[3]
return m;
}
-const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3]
+const float (*GPU_matrix_normal_inverse_get(float m[3][3]))[3]
{
if (m == NULL) {
static Mat3 temp3;
m = temp3;
}
- gpuGetNormalMatrix(m);
+ GPU_matrix_normal_get(m);
invert_m3(m);
return m;
}
-void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
+void GPU_matrix_bind(const GPUShaderInterface *shaderface)
{
/* set uniform values to matrix stack values
* call this before a draw call if desired matrices are dirty
* call glUseProgram before this, as glUniform expects program to be bound
*/
- const Gwn_ShaderInput *MV = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW);
- const Gwn_ShaderInput *P = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION);
- const Gwn_ShaderInput *MVP = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MVP);
+ const GPUShaderInput *MV = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW);
+ const GPUShaderInput *P = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION);
+ const GPUShaderInput *MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP);
- const Gwn_ShaderInput *N = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_NORMAL);
- const Gwn_ShaderInput *MV_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW_INV);
- const Gwn_ShaderInput *P_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION_INV);
+ const GPUShaderInput *N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL);
+ const GPUShaderInput *MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW_INV);
+ const GPUShaderInput *P_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION_INV);
if (MV) {
#if DEBUG_MATRIX_BIND
puts("setting MV matrix");
#endif
- glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)gpuGetModelViewMatrix(NULL));
+ glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL));
}
if (P) {
@@ -586,7 +586,7 @@ void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
puts("setting P matrix");
#endif
- glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)gpuGetProjectionMatrix(NULL));
+ glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL));
}
if (MVP) {
@@ -594,7 +594,7 @@ void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
puts("setting MVP matrix");
#endif
- glUniformMatrix4fv(MVP->location, 1, GL_FALSE, (const float *)gpuGetModelViewProjectionMatrix(NULL));
+ glUniformMatrix4fv(MVP->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL));
}
if (N) {
@@ -602,19 +602,19 @@ void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
puts("setting normal matrix");
#endif
- glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)gpuGetNormalMatrix(NULL));
+ glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL));
}
if (MV_inv) {
Mat4 m;
- gpuGetModelViewMatrix(m);
+ GPU_matrix_model_view_get(m);
invert_m4(m);
glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m);
}
if (P_inv) {
Mat4 m;
- gpuGetProjectionMatrix(m);
+ GPU_matrix_projection_get(m);
invert_m4(m);
glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
}
@@ -622,7 +622,7 @@ void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
state.dirty = false;
}
-bool gpuMatricesDirty(void)
+bool GPU_matrix_dirty_get(void)
{
return state.dirty;
}
diff --git a/source/blender/gpu/intern/gpu_primitive.c b/source/blender/gpu/intern/gpu_primitive.c
new file mode 100644
index 00000000000..189d17f2dd2
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_primitive.c
@@ -0,0 +1,84 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_primitive.c
+ * \ingroup gpu
+ *
+ * GPU geometric primitives
+ */
+
+#include "GPU_primitive.h"
+#include "gpu_primitive_private.h"
+
+GPUPrimClass GPU_primtype_class(GPUPrimType prim_type)
+{
+ static const GPUPrimClass classes[] = {
+ [GPU_PRIM_POINTS] = GPU_PRIM_CLASS_POINT,
+ [GPU_PRIM_LINES] = GPU_PRIM_CLASS_LINE,
+ [GPU_PRIM_LINE_STRIP] = GPU_PRIM_CLASS_LINE,
+ [GPU_PRIM_LINE_LOOP] = GPU_PRIM_CLASS_LINE,
+ [GPU_PRIM_TRIS] = GPU_PRIM_CLASS_SURFACE,
+ [GPU_PRIM_TRI_STRIP] = GPU_PRIM_CLASS_SURFACE,
+ [GPU_PRIM_TRI_FAN] = GPU_PRIM_CLASS_SURFACE,
+
+ [GPU_PRIM_LINES_ADJ] = GPU_PRIM_CLASS_LINE,
+ [GPU_PRIM_LINE_STRIP_ADJ] = GPU_PRIM_CLASS_LINE,
+ [GPU_PRIM_TRIS_ADJ] = GPU_PRIM_CLASS_SURFACE,
+
+ [GPU_PRIM_NONE] = GPU_PRIM_CLASS_NONE
+ };
+
+ return classes[prim_type];
+}
+
+bool GPU_primtype_belongs_to_class(GPUPrimType prim_type, GPUPrimClass prim_class)
+{
+ if (prim_class == GPU_PRIM_CLASS_NONE && prim_type == GPU_PRIM_NONE) {
+ return true;
+ }
+ return prim_class & GPU_primtype_class(prim_type);
+}
+
+GLenum convert_prim_type_to_gl(GPUPrimType prim_type)
+{
+#if TRUST_NO_ONE
+ assert(prim_type != GPU_PRIM_NONE);
+#endif
+ static const GLenum table[] = {
+ [GPU_PRIM_POINTS] = GL_POINTS,
+ [GPU_PRIM_LINES] = GL_LINES,
+ [GPU_PRIM_LINE_STRIP] = GL_LINE_STRIP,
+ [GPU_PRIM_LINE_LOOP] = GL_LINE_LOOP,
+ [GPU_PRIM_TRIS] = GL_TRIANGLES,
+ [GPU_PRIM_TRI_STRIP] = GL_TRIANGLE_STRIP,
+ [GPU_PRIM_TRI_FAN] = GL_TRIANGLE_FAN,
+
+ [GPU_PRIM_LINES_ADJ] = GL_LINES_ADJACENCY,
+ [GPU_PRIM_LINE_STRIP_ADJ] = GL_LINE_STRIP_ADJACENCY,
+ [GPU_PRIM_TRIS_ADJ] = GL_TRIANGLES_ADJACENCY,
+ };
+
+ return table[prim_type];
+}
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner.h b/source/blender/gpu/intern/gpu_primitive_private.h
index b00f6a54201..d057f29fdc5 100644
--- a/intern/opensubdiv/opensubdiv_topology_refiner.h
+++ b/source/blender/gpu/intern/gpu_primitive_private.h
@@ -15,27 +15,23 @@
* 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) 2016 Blender Foundation.
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
* All rights reserved.
*
- * Contributor(s): Sergey Sharybin.
+ * Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __OPENSUBDIV_TOPOLOGY_REFINER_H__
-#define __OPENSUBDIV_TOPOLOGY_REFINER_H__
-
-#include <opensubdiv/far/topologyRefiner.h>
+/** \file blender/gpu/intern/gpu_primitive_private.h
+ * \ingroup gpu
+ *
+ * GPU geometric primitives
+ */
-typedef struct OpenSubdiv_TopologyRefinerDescr {
- OpenSubdiv::Far::TopologyRefiner *osd_refiner;
+#ifndef __GPU_PRIMITIVE_PRIVATE_H__
+#define __GPU_PRIMITIVE_PRIVATE_H__
- /* TODO(sergey): For now only, need to find better place
- * after revisiting whole OSD drawing pipeline and Blender
- * integration.
- */
- std::vector<float> uvs;
-} OpenSubdiv_TopologyRefinerDescr;
+GLenum convert_prim_type_to_gl(GPUPrimType);
-#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */
+#endif /* __GPU_PRIMITIVE_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index 996ba9c63a1..df55f7922b3 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -25,6 +25,9 @@
#ifndef __GPU_PRIVATE_H__
#define __GPU_PRIVATE_H__
+struct GPUContext;
+struct GPUFrameBuffer;
+
/* call this before running any of the functions below */
void gpu_extensions_init(void);
void gpu_extensions_exit(void);
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 7023e44d289..1c0e7ed4c1c 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -242,7 +242,7 @@ bool GPU_select_is_cached(void)
const uint *GPU_select_buffer_near(const uint *buffer, int hits)
{
const uint *buffer_near = NULL;
- uint depth_min = (uint)-1;
+ uint depth_min = (uint) - 1;
for (int i = 0; i < hits; i++) {
if (buffer[1] < depth_min) {
BLI_assert(buffer[3] != -1);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 8c978be81c1..67ae1414b66 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -31,6 +31,7 @@
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
#include "BKE_appdir.h"
#include "BKE_global.h"
@@ -38,6 +39,7 @@
#include "DNA_space_types.h"
#include "GPU_extensions.h"
+#include "GPU_context.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -161,9 +163,20 @@ 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_gpencil_stroke_vert_glsl[];
+extern char datatoc_gpu_shader_gpencil_stroke_frag_glsl[];
+extern char datatoc_gpu_shader_gpencil_stroke_geom_glsl[];
+
+extern char datatoc_gpu_shader_gpencil_fill_vert_glsl[];
+extern char datatoc_gpu_shader_gpencil_fill_frag_glsl[];
+
/* cache of built-in shaders (each is created on first use) */
static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
+#ifndef NDEBUG
+static uint g_shaderid = 0;
+#endif
+
typedef struct {
const char *vert;
const char *frag;
@@ -214,8 +227,9 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
}
}
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
- bool use_opensubdiv)
+static void gpu_shader_standard_defines(
+ char defines[MAX_DEFINE_LENGTH],
+ bool use_opensubdiv)
{
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
@@ -244,11 +258,12 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
* a global typedef which we don't have better place to define
* in yet.
*/
- strcat(defines, "struct VertexData {\n"
- " vec4 position;\n"
- " vec3 normal;\n"
- " vec2 uv;"
- "};\n");
+ strcat(defines,
+ "struct VertexData {\n"
+ " vec4 position;\n"
+ " vec3 normal;\n"
+ " vec2 uv;"
+ "};\n");
}
#else
UNUSED_VARS(use_opensubdiv);
@@ -257,21 +272,25 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
return;
}
-GPUShader *GPU_shader_create(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines)
+GPUShader *GPU_shader_create(
+ const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ const char *shname)
{
- return GPU_shader_create_ex(vertexcode,
- fragcode,
- geocode,
- libcode,
- defines,
- GPU_SHADER_FLAGS_NONE,
- GPU_SHADER_TFB_NONE,
- NULL,
- 0);
+ return GPU_shader_create_ex(
+ vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ GPU_SHADER_FLAGS_NONE,
+ GPU_SHADER_TFB_NONE,
+ NULL,
+ 0,
+ shname);
}
#define DEBUG_SHADER_NONE ""
@@ -321,15 +340,17 @@ static void gpu_dump_shaders(const char **code, const int num_shaders, const cha
printf("Shader file written to disk: %s\n", shader_path);
}
-GPUShader *GPU_shader_create_ex(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines,
- const int flags,
- const GPUShaderTFBType tf_type,
- const char **tf_names,
- const int tf_count)
+GPUShader *GPU_shader_create_ex(
+ const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ const int flags,
+ const GPUShaderTFBType tf_type,
+ const char **tf_names,
+ const int tf_count,
+ const char *shname)
{
#ifdef WITH_OPENSUBDIV
bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
@@ -347,6 +368,12 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
+#ifndef NDEBUG
+ BLI_snprintf(shader->name, sizeof(shader->name), "%s_%u", shname, g_shaderid++);
+#else
+ UNUSED_VARS(shname);
+#endif
+
if (vertexcode)
shader->vertex = glCreateShader(GL_VERTEX_SHADER);
if (fragcode)
@@ -366,8 +393,9 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
- gpu_shader_standard_defines(standard_defines,
- use_opensubdiv);
+ gpu_shader_standard_defines(
+ standard_defines,
+ use_opensubdiv);
gpu_shader_standard_extensions(standard_extensions);
if (vertexcode) {
@@ -410,12 +438,13 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Move to fragment shader source code generation. */
if (use_opensubdiv) {
- source[num_source++] =
+ source[num_source++] = (
"#ifdef USE_OPENSUBDIV\n"
"in block {\n"
" VertexData v;\n"
"} inpt;\n"
- "#endif\n";
+ "#endif\n"
+ );
}
#endif
@@ -496,24 +525,26 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
- shader->interface = GWN_shaderinterface_create(shader->program);
+ shader->interface = GPU_shaderinterface_create(shader->program);
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Find a better place for this. */
if (use_opensubdiv) {
if (GLEW_VERSION_4_1) {
- glProgramUniform1i(shader->program,
- GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location,
- 30); /* GL_TEXTURE30 */
-
- glProgramUniform1i(shader->program,
- GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location,
- 31); /* GL_TEXTURE31 */
+ glProgramUniform1i(
+ shader->program,
+ GPU_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location,
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(
+ shader->program,
+ GPU_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location,
+ 31); /* GL_TEXTURE31 */
}
else {
glUseProgram(shader->program);
- glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location, 30);
- glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location, 31);
+ glUniform1i(GPU_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location, 30);
+ glUniform1i(GPU_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location, 31);
glUseProgram(0);
}
}
@@ -532,7 +563,7 @@ void GPU_shader_bind(GPUShader *shader)
BLI_assert(shader && shader->program);
glUseProgram(shader->program);
- gpuBindMatrices(shader->interface);
+ GPU_matrix_bind(shader->interface);
}
void GPU_shader_unbind(void)
@@ -563,6 +594,10 @@ void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
void GPU_shader_free(GPUShader *shader)
{
+#if 0 /* Would be nice to have, but for now the Deferred compilation
+ * does not have a GPUContext. */
+ BLI_assert(GPU_context_active_get() != NULL);
+#endif
BLI_assert(shader);
if (shader->vertex)
@@ -575,7 +610,7 @@ void GPU_shader_free(GPUShader *shader)
glDeleteProgram(shader->program);
if (shader->interface)
- GWN_shaderinterface_discard(shader->interface);
+ GPU_shaderinterface_discard(shader->interface);
MEM_freeN(shader);
}
@@ -583,14 +618,14 @@ void GPU_shader_free(GPUShader *shader)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
- const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform(shader->interface, name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
return uniform ? uniform->location : -1;
}
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
{
BLI_assert(shader && shader->program);
- const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform_builtin(shader->interface, builtin);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin);
return uniform ? uniform->location : -1;
}
@@ -598,7 +633,7 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
- const Gwn_ShaderInput *ubo = GWN_shaderinterface_ubo(shader->interface, name);
+ const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
return ubo ? ubo->location : -1;
}
@@ -675,7 +710,7 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
- const Gwn_ShaderInput *attrib = GWN_shaderinterface_attr(shader->interface, name);
+ const GPUShaderInput *attrib = GPU_shaderinterface_attr(shader->interface, name);
return attrib ? attrib->location : -1;
}
@@ -727,6 +762,10 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
[GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
[GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
[GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_interlace_frag_glsl },
@@ -853,6 +892,13 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_2D_nodelink_frag_glsl },
[GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
datatoc_gpu_shader_2D_nodelink_frag_glsl },
+
+ [GPU_SHADER_GPENCIL_STROKE] = { datatoc_gpu_shader_gpencil_stroke_vert_glsl,
+ datatoc_gpu_shader_gpencil_stroke_frag_glsl,
+ datatoc_gpu_shader_gpencil_stroke_geom_glsl },
+
+ [GPU_SHADER_GPENCIL_FILL] = { datatoc_gpu_shader_gpencil_fill_vert_glsl,
+ datatoc_gpu_shader_gpencil_fill_frag_glsl },
};
if (builtin_shaders[shader] == NULL) {
@@ -862,15 +908,31 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2:
defines = "#define SAMPLES 2\n";
break;
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST:
+ defines = "#define SAMPLES 2\n"
+ "#define USE_DEPTH\n";
+ break;
case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4:
defines = "#define SAMPLES 4\n";
break;
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST:
+ defines = "#define SAMPLES 4\n"
+ "#define USE_DEPTH\n";
+ break;
case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8:
defines = "#define SAMPLES 8\n";
break;
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST:
+ defines = "#define SAMPLES 8\n"
+ "#define USE_DEPTH\n";
+ break;
case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16:
defines = "#define SAMPLES 16\n";
break;
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST:
+ defines = "#define SAMPLES 16\n"
+ "#define USE_DEPTH\n";
+ break;
case GPU_SHADER_2D_WIDGET_BASE_INST:
case GPU_SHADER_2D_NODELINK_INST:
defines = "#define USE_INSTANCE\n";
@@ -903,22 +965,25 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
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 };
+ 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;
}
if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR && !GLEW_VERSION_3_2) {
/* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */
/* TODO: remove after switch to core profile (maybe) */
- static const GPUShaderStages legacy_dashed_lines = { datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl,
- datatoc_gpu_shader_2D_line_dashed_frag_glsl };
+ static const GPUShaderStages legacy_dashed_lines = {
+ datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl,
+ };
stages = &legacy_dashed_lines;
}
/* common case */
- builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines);
+ builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines, __func__);
}
return builtin_shaders[shader];
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
new file mode 100644
index 00000000000..f6bbc228ae9
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -0,0 +1,368 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_shader_interface.c
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_shader_interface.h"
+
+#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#define DEBUG_SHADER_INTERFACE 0
+
+#if DEBUG_SHADER_INTERFACE
+# include <stdio.h>
+#endif
+
+static const char *BuiltinUniform_name(GPUUniformBuiltin u)
+{
+ static const char *names[] = {
+ [GPU_UNIFORM_NONE] = NULL,
+
+ [GPU_UNIFORM_MODEL] = "ModelMatrix",
+ [GPU_UNIFORM_VIEW] = "ViewMatrix",
+ [GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix",
+ [GPU_UNIFORM_PROJECTION] = "ProjectionMatrix",
+ [GPU_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix",
+ [GPU_UNIFORM_MVP] = "ModelViewProjectionMatrix",
+
+ [GPU_UNIFORM_MODEL_INV] = "ModelMatrixInverse",
+ [GPU_UNIFORM_VIEW_INV] = "ViewMatrixInverse",
+ [GPU_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse",
+ [GPU_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse",
+ [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse",
+
+ [GPU_UNIFORM_NORMAL] = "NormalMatrix",
+ [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix",
+ [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors",
+ [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors",
+
+ [GPU_UNIFORM_COLOR] = "color",
+ [GPU_UNIFORM_EYE] = "eye",
+ [GPU_UNIFORM_CALLID] = "callId",
+
+ [GPU_UNIFORM_CUSTOM] = NULL,
+ [GPU_NUM_UNIFORMS] = NULL,
+ };
+
+ return names[u];
+}
+
+GPU_INLINE bool match(const char *a, const char *b)
+{
+ return strcmp(a, b) == 0;
+}
+
+GPU_INLINE uint hash_string(const char *str)
+{
+ uint i = 0, c;
+ while ((c = *str++)) {
+ i = i * 37 + c;
+ }
+ return i;
+}
+
+GPU_INLINE void set_input_name(
+ GPUShaderInterface *shaderface, GPUShaderInput *input,
+ const char *name, uint32_t name_len)
+{
+ input->name_offset = shaderface->name_buffer_offset;
+ input->name_hash = hash_string(name);
+ shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */
+}
+
+GPU_INLINE void shader_input_to_bucket(
+ GPUShaderInput *input,
+ GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
+{
+ const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
+ input->next = buckets[bucket_index];
+ buckets[bucket_index] = input;
+}
+
+GPU_INLINE const GPUShaderInput *buckets_lookup(
+ GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS],
+ const char *name_buffer, const char *name)
+{
+ const uint name_hash = hash_string(name);
+ const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
+ const GPUShaderInput *input = buckets[bucket_index];
+ if (input == NULL) {
+ /* Requested uniform is not found at all. */
+ return NULL;
+ }
+ /* Optimization bit: if there is no hash collision detected when constructing shader interface
+ * it means we can only request the single possible uniform. Surely, it's possible we request
+ * uniform which causes hash collision, but that will be detected in debug builds. */
+ if (input->next == NULL) {
+ if (name_hash == input->name_hash) {
+#if TRUST_NO_ONE
+ assert(match(name_buffer + input->name_offset, name));
+#endif
+ return input;
+ }
+ return NULL;
+ }
+ /* Work through possible collisions. */
+ const GPUShaderInput *next = input;
+ while (next != NULL) {
+ input = next;
+ next = input->next;
+ if (input->name_hash != name_hash) {
+ continue;
+ }
+ if (match(name_buffer + input->name_offset, name)) {
+ return input;
+ }
+ }
+ return NULL; /* not found */
+}
+
+GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
+{
+ for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) {
+ GPUShaderInput *input = buckets[bucket_index];
+ while (input != NULL) {
+ GPUShaderInput *input_next = input->next;
+ MEM_freeN(input);
+ input = input_next;
+ }
+ }
+}
+
+static bool setup_builtin_uniform(GPUShaderInput *input, const char *name)
+{
+ /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */
+
+ /* detect built-in uniforms (name must match) */
+ for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) {
+ const char *builtin_name = BuiltinUniform_name(u);
+ if (match(name, builtin_name)) {
+ input->builtin_type = u;
+ return true;
+ }
+ }
+ input->builtin_type = GPU_UNIFORM_CUSTOM;
+ return false;
+}
+
+static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name)
+{
+ GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif");
+
+ input->location = glGetUniformLocation(shaderface->program, name);
+
+ uint name_len = strlen(name);
+ shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); /* include NULL terminator */
+ char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
+ strcpy(name_buffer, name);
+
+ set_input_name(shaderface, input, name, name_len);
+ setup_builtin_uniform(input, name);
+
+ shader_input_to_bucket(input, shaderface->uniform_buckets);
+ if (input->builtin_type != GPU_UNIFORM_NONE &&
+ input->builtin_type != GPU_UNIFORM_CUSTOM)
+ {
+ shaderface->builtin_uniforms[input->builtin_type] = input;
+ }
+#if DEBUG_SHADER_INTERFACE
+ printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n",
+ shaderface,
+ shaderface->program,
+ name,
+ input->location);
+#endif
+ return input;
+}
+
+GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
+{
+ GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface");
+ shaderface->program = program;
+
+#if DEBUG_SHADER_INTERFACE
+ printf("%s {\n", __func__); /* enter function */
+ printf("GPUShaderInterface %p, program %d\n", shaderface, program);
+#endif
+
+ GLint max_attrib_name_len, attr_len;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len);
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len);
+
+ GLint max_ubo_name_len, ubo_len;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
+
+ const uint32_t name_buffer_len = attr_len * max_attrib_name_len + ubo_len * max_ubo_name_len;
+ shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
+
+ /* Attributes */
+ for (uint32_t i = 0; i < attr_len; ++i) {
+ GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr");
+ GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
+ char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+
+ /* remove "[0]" from array name */
+ if (name[name_len - 1] == ']') {
+ name[name_len - 3] = '\0';
+ name_len -= 3;
+ }
+
+ /* TODO: reject DOUBLE gl_types */
+
+ input->location = glGetAttribLocation(program, name);
+
+ set_input_name(shaderface, input, name, name_len);
+
+ shader_input_to_bucket(input, shaderface->attrib_buckets);
+
+#if DEBUG_SHADER_INTERFACE
+ printf("attrib[%u] '%s' at location %d\n", i, name, input->location);
+#endif
+ }
+ /* Uniform Blocks */
+ for (uint32_t i = 0; i < ubo_len; ++i) {
+ GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO");
+ GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
+ char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
+
+ input->location = i;
+
+ set_input_name(shaderface, input, name, name_len);
+
+ shader_input_to_bucket(input, shaderface->ubo_buckets);
+
+#if DEBUG_SHADER_INTERFACE
+ printf("ubo '%s' at location %d\n", name, input->location);
+#endif
+ }
+ /* Builtin Uniforms */
+ for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) {
+ const char *builtin_name = BuiltinUniform_name(u);
+ if (glGetUniformLocation(program, builtin_name) != -1) {
+ add_uniform((GPUShaderInterface *)shaderface, builtin_name);
+ }
+ }
+ /* Batches ref buffer */
+ shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
+ shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), "GPUShaderInterface batches");
+
+ return shaderface;
+}
+
+void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
+{
+ /* Free memory used by buckets and has entries. */
+ buckets_free(shaderface->uniform_buckets);
+ buckets_free(shaderface->attrib_buckets);
+ buckets_free(shaderface->ubo_buckets);
+ /* Free memory used by name_buffer. */
+ MEM_freeN(shaderface->name_buffer);
+ /* Remove this interface from all linked Batches vao cache. */
+ for (int i = 0; i < shaderface->batches_len; ++i) {
+ if (shaderface->batches[i] != NULL) {
+ gpu_batch_remove_interface_ref(shaderface->batches[i], shaderface);
+ }
+ }
+ MEM_freeN(shaderface->batches);
+ /* Free memory used by shader interface by its self. */
+ MEM_freeN(shaderface);
+}
+
+const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, const char *name)
+{
+ /* TODO: Warn if we find a matching builtin, since these can be looked up much quicker. */
+ const GPUShaderInput *input = buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
+ /* If input is not found add it so it's found next time. */
+ if (input == NULL) {
+ input = add_uniform((GPUShaderInterface *)shaderface, name);
+ }
+ return (input->location != -1) ? input : NULL;
+}
+
+const GPUShaderInput *GPU_shaderinterface_uniform_builtin(
+ const GPUShaderInterface *shaderface, GPUUniformBuiltin builtin)
+{
+#if TRUST_NO_ONE
+ assert(builtin != GPU_UNIFORM_NONE);
+ assert(builtin != GPU_UNIFORM_CUSTOM);
+ assert(builtin != GPU_NUM_UNIFORMS);
+#endif
+ return shaderface->builtin_uniforms[builtin];
+}
+
+const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, const char *name)
+{
+ return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
+}
+
+const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, const char *name)
+{
+ return buckets_lookup(shaderface->attrib_buckets, shaderface->name_buffer, name);
+}
+
+void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
+{
+ int i; /* find first unused slot */
+ for (i = 0; i < shaderface->batches_len; ++i) {
+ if (shaderface->batches[i] == NULL) {
+ break;
+ }
+ }
+ if (i == shaderface->batches_len) {
+ /* Not enough place, realloc the array. */
+ i = shaderface->batches_len;
+ shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
+ shaderface->batches = MEM_recallocN(shaderface->batches, sizeof(GPUBatch *) * shaderface->batches_len);
+ }
+ shaderface->batches[i] = batch;
+}
+
+void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
+{
+ for (int i = 0; i < shaderface->batches_len; ++i) {
+ if (shaderface->batches[i] == batch) {
+ shaderface->batches[i] = NULL;
+ break; /* cannot have duplicates */
+ }
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
index de5439c5638..69c0c41cef4 100644
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -26,7 +26,7 @@
#define __GPU_SHADER_PRIVATE_H__
#include "GPU_glew.h"
-#include "gawain/gwn_shader_interface.h"
+#include "GPU_shader_interface.h"
struct GPUShader {
GLuint program; /* handle for full program (links shader stages below) */
@@ -35,9 +35,12 @@ struct GPUShader {
GLuint geometry; /* handle for geometry shader */
GLuint fragment; /* handle for fragment shader */
- Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
+ GPUShaderInterface *interface; /* cached uniform & attrib interface for shader */
int feedback_transform_type;
+#ifndef NDEBUG
+ char name[64];
+#endif
};
#endif /* __GPU_SHADER_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_state.c b/source/blender/gpu/intern/gpu_state.c
index 588d61640bd..68d846ccfba 100644
--- a/source/blender/gpu/intern/gpu_state.c
+++ b/source/blender/gpu/intern/gpu_state.c
@@ -66,10 +66,11 @@ void GPU_blend_set_func_separate(
GPUBlendFunction src_rgb, GPUBlendFunction dst_rgb,
GPUBlendFunction src_alpha, GPUBlendFunction dst_alpha)
{
- glBlendFuncSeparate(gpu_get_gl_blendfunction(src_rgb),
- gpu_get_gl_blendfunction(dst_rgb),
- gpu_get_gl_blendfunction(src_alpha),
- gpu_get_gl_blendfunction(dst_alpha));
+ glBlendFuncSeparate(
+ gpu_get_gl_blendfunction(src_rgb),
+ gpu_get_gl_blendfunction(dst_rgb),
+ gpu_get_gl_blendfunction(src_alpha),
+ gpu_get_gl_blendfunction(dst_alpha));
}
void GPU_depth_test(bool enable)
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index d9248e06dfb..2ccc9f10269 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -38,22 +38,22 @@
#include "BKE_global.h"
#include "GPU_batch.h"
+#include "GPU_context.h"
#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
#include "GPU_glew.h"
+#include "GPU_framebuffer.h"
#include "GPU_texture.h"
+#include "gpu_context_private.h"
+
static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
-static ListBase g_orphaned_tex = {NULL, NULL};
-static ThreadMutex g_orphan_lock;
-
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 8
@@ -160,9 +160,12 @@ static int gpu_get_component_count(GPUTextureFormat format)
/* Definitely not complete, edit according to the gl specification. */
static void gpu_validate_data_format(GPUTextureFormat tex_format, GPUDataFormat data_format)
{
- if (ELEM(tex_format, GPU_DEPTH_COMPONENT24,
- GPU_DEPTH_COMPONENT16,
- GPU_DEPTH_COMPONENT32F))
+ (void)data_format;
+
+ if (ELEM(tex_format,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+ GPU_DEPTH_COMPONENT32F))
{
BLI_assert(data_format == GPU_DATA_FLOAT);
}
@@ -196,9 +199,10 @@ static void gpu_validate_data_format(GPUTextureFormat tex_format, GPUDataFormat
static GPUDataFormat gpu_get_data_format_from_tex_format(GPUTextureFormat tex_format)
{
- if (ELEM(tex_format, GPU_DEPTH_COMPONENT24,
- GPU_DEPTH_COMPONENT16,
- GPU_DEPTH_COMPONENT32F))
+ if (ELEM(tex_format,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+ GPU_DEPTH_COMPONENT32F))
{
return GPU_DATA_FLOAT;
}
@@ -232,9 +236,10 @@ static GPUDataFormat gpu_get_data_format_from_tex_format(GPUTextureFormat tex_fo
/* Definitely not complete, edit according to the gl specification. */
static GLenum gpu_get_gl_dataformat(GPUTextureFormat data_type, GPUTextureFormatFlag *format_flag)
{
- if (ELEM(data_type, GPU_DEPTH_COMPONENT24,
- GPU_DEPTH_COMPONENT16,
- GPU_DEPTH_COMPONENT32F))
+ if (ELEM(data_type,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+ GPU_DEPTH_COMPONENT32F))
{
*format_flag |= GPU_FORMAT_DEPTH;
return GL_DEPTH_COMPONENT;
@@ -429,6 +434,11 @@ static bool gpu_texture_try_alloc(
glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, NULL);
break;
case GL_PROXY_TEXTURE_2D_ARRAY:
+ /* HACK: Some driver wrongly check GL_PROXY_TEXTURE_2D_ARRAY as a GL_PROXY_TEXTURE_3D
+ * checking all dimensions against GPU_max_texture_layers (see T55888). */
+ return (tex->w > 0) && (tex->w <= GPU_max_texture_size()) &&
+ (tex->h > 0) && (tex->h <= GPU_max_texture_size()) &&
+ (tex->d > 0) && (tex->d <= GPU_max_texture_layers());
case GL_PROXY_TEXTURE_3D:
glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, NULL);
break;
@@ -532,7 +542,7 @@ GPUTexture *GPU_texture_create_nD(
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
if (err_out)
@@ -665,7 +675,7 @@ static GPUTexture *GPU_texture_cube_create(
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
if (err_out)
@@ -749,7 +759,7 @@ GPUTexture *GPU_texture_create_buffer(GPUTextureFormat tex_format, const GLuint
}
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
fprintf(stderr, "GPUTexture: texture create failed\n");
@@ -861,6 +871,13 @@ GPUTexture *GPU_texture_create_1D(
return GPU_texture_create_nD(w, 0, 0, 1, pixels, tex_format, data_format, 0, false, err_out);
}
+GPUTexture *GPU_texture_create_1D_array(
+ int w, int h, GPUTextureFormat tex_format, const float *pixels, char err_out[256])
+{
+ GPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format);
+ return GPU_texture_create_nD(w, h, 0, 1, pixels, tex_format, data_format, 0, false, err_out);
+}
+
GPUTexture *GPU_texture_create_2D(
int w, int h, GPUTextureFormat tex_format, const float *pixels, char err_out[256])
{
@@ -911,28 +928,28 @@ GPUTexture *GPU_texture_create_cube(
tex_format, GPU_DATA_FLOAT, err_out);
}
-GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
+GPUTexture *GPU_texture_create_from_vertbuf(GPUVertBuf *vert)
{
- Gwn_VertFormat *format = &vert->format;
- Gwn_VertAttr *attr = &format->attribs[0];
+ GPUVertFormat *format = &vert->format;
+ GPUVertAttr *attr = &format->attribs[0];
/* Detect incompatible cases (not supported by texture buffers) */
BLI_assert(format->attr_len == 1 && vert->vbo_id != 0);
BLI_assert(attr->comp_len != 3); /* Not until OGL 4.0 */
- BLI_assert(attr->comp_type != GWN_COMP_I10);
- BLI_assert(attr->fetch_mode != GWN_FETCH_INT_TO_FLOAT);
+ BLI_assert(attr->comp_type != GPU_COMP_I10);
+ BLI_assert(attr->fetch_mode != GPU_FETCH_INT_TO_FLOAT);
unsigned int byte_per_comp = attr->sz / attr->comp_len;
- bool is_uint = ELEM(attr->comp_type, GWN_COMP_U8, GWN_COMP_U16, GWN_COMP_U32);
+ bool is_uint = ELEM(attr->comp_type, GPU_COMP_U8, GPU_COMP_U16, GPU_COMP_U32);
/* Cannot fetch signed int or 32bit ints as normalized float. */
- if (attr->fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT) {
+ if (attr->fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT) {
BLI_assert(is_uint || byte_per_comp <= 2);
}
GPUTextureFormat data_type;
switch (attr->fetch_mode) {
- case GWN_FETCH_FLOAT:
+ case GPU_FETCH_FLOAT:
switch (attr->comp_len) {
case 1: data_type = GPU_R32F; break;
case 2: data_type = GPU_RG32F; break;
@@ -940,7 +957,7 @@ GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
default: data_type = GPU_RGBA32F; break;
}
break;
- case GWN_FETCH_INT:
+ case GPU_FETCH_INT:
switch (attr->comp_len) {
case 1:
switch (byte_per_comp) {
@@ -965,7 +982,7 @@ GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
break;
}
break;
- case GWN_FETCH_INT_TO_FLOAT_UNIT:
+ case GPU_FETCH_INT_TO_FLOAT_UNIT:
switch (attr->comp_len) {
case 1: data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; break;
case 2: data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; break;
@@ -1161,8 +1178,9 @@ void GPU_texture_bind(GPUTexture *tex, int number)
if ((G.debug & G_DEBUG)) {
for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind "
- "texture attached to current framebuffer!\n");
+ fprintf(stderr,
+ "Feedback loop warning!: Attempting to bind "
+ "texture attached to current framebuffer!\n");
BLI_assert(0); /* Should never happen! */
break;
}
@@ -1297,17 +1315,6 @@ void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilte
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
}
-
-static void gpu_texture_delete(GPUTexture *tex)
-{
- if (tex->bindcode)
- glDeleteTextures(1, &tex->bindcode);
-
- gpu_texture_memory_footprint_remove(tex);
-
- MEM_freeN(tex);
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -1322,38 +1329,13 @@ void GPU_texture_free(GPUTexture *tex)
}
}
- /* TODO(fclem): Check if the thread has an ogl context. */
- if (BLI_thread_is_main()) {
- gpu_texture_delete(tex);
- }
- else {
- BLI_mutex_lock(&g_orphan_lock);
- BLI_addtail(&g_orphaned_tex, BLI_genericNodeN(tex));
- BLI_mutex_unlock(&g_orphan_lock);
- }
- }
-}
+ if (tex->bindcode)
+ GPU_tex_free(tex->bindcode);
-void GPU_texture_orphans_init(void)
-{
- BLI_mutex_init(&g_orphan_lock);
-}
+ gpu_texture_memory_footprint_remove(tex);
-void GPU_texture_orphans_delete(void)
-{
- BLI_mutex_lock(&g_orphan_lock);
- LinkData *link;
- while ((link = BLI_pophead(&g_orphaned_tex))) {
- gpu_texture_delete((GPUTexture *)link->data);
- MEM_freeN(link);
+ MEM_freeN(tex);
}
- BLI_mutex_unlock(&g_orphan_lock);
-}
-
-void GPU_texture_orphans_exit(void)
-{
- GPU_texture_orphans_delete();
- BLI_mutex_end(&g_orphan_lock);
}
void GPU_texture_ref(GPUTexture *tex)
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
index 1e39b2ea5b7..3f5706c1f7b 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.c
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -35,6 +35,7 @@
#include "BLI_blenlib.h"
#include "gpu_codegen.h"
+#include "gpu_context_private.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -88,7 +89,7 @@ GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_
ubo->bindpoint = -1;
/* Generate Buffer object */
- glGenBuffers(1, &ubo->bindcode);
+ ubo->bindcode = GPU_buf_alloc();
if (!ubo->bindcode) {
if (err_out)
@@ -127,7 +128,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
ubo->flag = GPU_UBO_FLAG_DIRTY;
/* Generate Buffer object. */
- glGenBuffers(1, &ubo->buffer.bindcode);
+ ubo->buffer.bindcode = GPU_buf_alloc();
if (!ubo->buffer.bindcode) {
if (err_out)
@@ -158,9 +159,8 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
float *offset = ubo->data;
for (LinkData *link = inputs->first; link; link = link->next) {
GPUInput *input = link->data;
- const GPUType gputype = get_padded_gpu_type(link);
- memcpy(offset, input->dynamicvec, gputype * sizeof(float));
- offset += gputype;
+ memcpy(offset, input->dynamicvec, input->type * sizeof(float));
+ offset += get_padded_gpu_type(link);
}
/* Note since we may create the UBOs in the CPU in a different thread than the main drawing one,
@@ -190,7 +190,7 @@ void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
gpu_uniformbuffer_dynamic_free(ubo);
}
- glDeleteBuffers(1, &ubo->bindcode);
+ GPU_buf_free(ubo->bindcode);
MEM_freeN(ubo);
}
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c
new file mode 100644
index 00000000000..05100b8a23f
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.c
@@ -0,0 +1,272 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Clément Foucault
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_vertex_buffer.c
+ * \ingroup gpu
+ *
+ * GPU vertex buffer
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_vertex_buffer.h"
+
+#include "gpu_context_private.h"
+#include "gpu_vertex_format_private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define KEEP_SINGLE_COPY 1
+
+static uint vbo_memory_usage;
+
+static GLenum convert_usage_type_to_gl(GPUUsageType type)
+{
+ static const GLenum table[] = {
+ [GPU_USAGE_STREAM] = GL_STREAM_DRAW,
+ [GPU_USAGE_STATIC] = GL_STATIC_DRAW,
+ [GPU_USAGE_DYNAMIC] = GL_DYNAMIC_DRAW
+ };
+ return table[type];
+}
+
+GPUVertBuf *GPU_vertbuf_create(GPUUsageType usage)
+{
+ GPUVertBuf *verts = MEM_mallocN(sizeof(GPUVertBuf), "GPUVertBuf");
+ GPU_vertbuf_init(verts, usage);
+ return verts;
+}
+
+GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *format, GPUUsageType usage)
+{
+ GPUVertBuf *verts = GPU_vertbuf_create(usage);
+ GPU_vertformat_copy(&verts->format, format);
+ if (!format->packed) {
+ VertexFormat_pack(&verts->format);
+ }
+ return verts;
+
+ /* this function might seem redundant, but there is potential for memory savings here... */
+ /* TODO: implement those memory savings */
+}
+
+void GPU_vertbuf_init(GPUVertBuf *verts, GPUUsageType usage)
+{
+ memset(verts, 0, sizeof(GPUVertBuf));
+ verts->usage = usage;
+ verts->dirty = true;
+}
+
+void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, const GPUVertFormat *format, GPUUsageType usage)
+{
+ GPU_vertbuf_init(verts, usage);
+ GPU_vertformat_copy(&verts->format, format);
+ if (!format->packed) {
+ VertexFormat_pack(&verts->format);
+ }
+}
+
+void GPU_vertbuf_discard(GPUVertBuf *verts)
+{
+ if (verts->vbo_id) {
+ GPU_buf_free(verts->vbo_id);
+#if VRAM_USAGE
+ vbo_memory_usage -= GPU_vertbuf_size_get(verts);
+#endif
+ }
+ if (verts->data) {
+ MEM_freeN(verts->data);
+ }
+ MEM_freeN(verts);
+}
+
+uint GPU_vertbuf_size_get(const GPUVertBuf *verts)
+{
+ return vertex_buffer_size(&verts->format, verts->vertex_len);
+}
+
+/* create a new allocation, discarding any existing data */
+void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len)
+{
+ GPUVertFormat *format = &verts->format;
+ if (!format->packed) {
+ VertexFormat_pack(format);
+ }
+#if TRUST_NO_ONE
+ /* catch any unnecessary use */
+ assert(verts->vertex_alloc != v_len || verts->data == NULL);
+#endif
+ /* only create the buffer the 1st time */
+ if (verts->vbo_id == 0) {
+ verts->vbo_id = GPU_buf_alloc();
+ }
+ /* discard previous data if any */
+ if (verts->data) {
+ MEM_freeN(verts->data);
+ }
+#if VRAM_USAGE
+ uint new_size = vertex_buffer_size(&verts->format, v_len);
+ vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts);
+#endif
+ verts->dirty = true;
+ verts->vertex_len = verts->vertex_alloc = v_len;
+ verts->data = MEM_mallocN(sizeof(GLubyte) * GPU_vertbuf_size_get(verts), "GPUVertBuf data");
+}
+
+/* resize buffer keeping existing data */
+void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len)
+{
+#if TRUST_NO_ONE
+ assert(verts->data != NULL);
+ assert(verts->vertex_alloc != v_len);
+#endif
+
+#if VRAM_USAGE
+ uint new_size = vertex_buffer_size(&verts->format, v_len);
+ vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts);
+#endif
+ verts->dirty = true;
+ verts->vertex_len = verts->vertex_alloc = v_len;
+ verts->data = MEM_reallocN(verts->data, sizeof(GLubyte) * GPU_vertbuf_size_get(verts));
+}
+
+/* Set vertex count but does not change allocation.
+ * Only this many verts will be uploaded to the GPU and rendered.
+ * This is usefull for streaming data. */
+void GPU_vertbuf_vertex_count_set(GPUVertBuf *verts, uint v_len)
+{
+#if TRUST_NO_ONE
+ assert(verts->data != NULL); /* only for dynamic data */
+ assert(v_len <= verts->vertex_alloc);
+#endif
+
+#if VRAM_USAGE
+ uint new_size = vertex_buffer_size(&verts->format, v_len);
+ vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts);
+#endif
+ verts->vertex_len = v_len;
+}
+
+void GPU_vertbuf_attr_set(GPUVertBuf *verts, uint a_idx, uint v_idx, const void *data)
+{
+ const GPUVertFormat *format = &verts->format;
+ const GPUVertAttr *a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attr_len);
+ assert(v_idx < verts->vertex_alloc);
+ assert(verts->data != NULL);
+#endif
+ verts->dirty = true;
+ memcpy((GLubyte *)verts->data + a->offset + v_idx * format->stride, data, a->sz);
+}
+
+void GPU_vertbuf_attr_fill(GPUVertBuf *verts, uint a_idx, const void *data)
+{
+ const GPUVertFormat *format = &verts->format;
+ const GPUVertAttr *a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attr_len);
+#endif
+ const uint stride = a->sz; /* tightly packed input data */
+
+ GPU_vertbuf_attr_fill_stride(verts, a_idx, stride, data);
+}
+
+void GPU_vertbuf_attr_fill_stride(GPUVertBuf *verts, uint a_idx, uint stride, const void *data)
+{
+ const GPUVertFormat *format = &verts->format;
+ const GPUVertAttr *a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attr_len);
+ assert(verts->data != NULL);
+#endif
+ verts->dirty = true;
+ const uint vertex_len = verts->vertex_len;
+
+ if (format->attr_len == 1 && stride == format->stride) {
+ /* we can copy it all at once */
+ memcpy(verts->data, data, vertex_len * a->sz);
+ }
+ else {
+ /* we must copy it per vertex */
+ for (uint v = 0; v < vertex_len; ++v) {
+ memcpy((GLubyte *)verts->data + a->offset + v * format->stride, (const GLubyte *)data + v * stride, a->sz);
+ }
+ }
+}
+
+void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts, uint a_idx, GPUVertBufRaw *access)
+{
+ const GPUVertFormat *format = &verts->format;
+ const GPUVertAttr *a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attr_len);
+ assert(verts->data != NULL);
+#endif
+
+ verts->dirty = true;
+
+ access->size = a->sz;
+ access->stride = format->stride;
+ access->data = (GLubyte *)verts->data + a->offset;
+ access->data_init = access->data;
+#if TRUST_NO_ONE
+ access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride);
+#endif
+}
+
+static void VertBuffer_upload_data(GPUVertBuf *verts)
+{
+ uint buffer_sz = GPU_vertbuf_size_get(verts);
+
+ /* orphan the vbo to avoid sync */
+ glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage));
+ /* upload data */
+ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data);
+
+ if (verts->usage == GPU_USAGE_STATIC) {
+ MEM_freeN(verts->data);
+ verts->data = NULL;
+ }
+ verts->dirty = false;
+}
+
+void GPU_vertbuf_use(GPUVertBuf *verts)
+{
+ glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+ if (verts->dirty) {
+ VertBuffer_upload_data(verts);
+ }
+}
+
+uint GPU_vertbuf_get_memory_usage(void)
+{
+ return vbo_memory_usage;
+}
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
new file mode 100644
index 00000000000..eef4945d9ef
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -0,0 +1,312 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Clément Foucault
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_vertex_format.c
+ * \ingroup gpu
+ *
+ * GPU vertex format
+ */
+
+#include "GPU_vertex_format.h"
+#include "gpu_vertex_format_private.h"
+#include <stddef.h>
+#include <string.h>
+
+#define PACK_DEBUG 0
+
+#if PACK_DEBUG
+# include <stdio.h>
+#endif
+
+void GPU_vertformat_clear(GPUVertFormat *format)
+{
+#if TRUST_NO_ONE
+ memset(format, 0, sizeof(GPUVertFormat));
+#else
+ format->attr_len = 0;
+ format->packed = false;
+ format->name_offset = 0;
+ format->name_len = 0;
+
+ for (unsigned i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) {
+ format->attribs[i].name_len = 0;
+ }
+#endif
+}
+
+void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src)
+{
+ /* copy regular struct fields */
+ memcpy(dest, src, sizeof(GPUVertFormat));
+
+ for (unsigned i = 0; i < dest->attr_len; i++) {
+ for (unsigned j = 0; j < dest->attribs[i].name_len; j++) {
+ dest->attribs[i].name[j] = (char *)dest + (src->attribs[i].name[j] - ((char *)src));
+ }
+ }
+}
+
+static GLenum convert_comp_type_to_gl(GPUVertCompType type)
+{
+ static const GLenum table[] = {
+ [GPU_COMP_I8] = GL_BYTE,
+ [GPU_COMP_U8] = GL_UNSIGNED_BYTE,
+ [GPU_COMP_I16] = GL_SHORT,
+ [GPU_COMP_U16] = GL_UNSIGNED_SHORT,
+ [GPU_COMP_I32] = GL_INT,
+ [GPU_COMP_U32] = GL_UNSIGNED_INT,
+
+ [GPU_COMP_F32] = GL_FLOAT,
+
+ [GPU_COMP_I10] = GL_INT_2_10_10_10_REV
+ };
+ return table[type];
+}
+
+static unsigned comp_sz(GPUVertCompType type)
+{
+#if TRUST_NO_ONE
+ assert(type <= GPU_COMP_F32); /* other types have irregular sizes (not bytes) */
+#endif
+ const GLubyte sizes[] = {1, 1, 2, 2, 4, 4, 4};
+ return sizes[type];
+}
+
+static unsigned attrib_sz(const GPUVertAttr *a)
+{
+ if (a->comp_type == GPU_COMP_I10) {
+ return 4; /* always packed as 10_10_10_2 */
+ }
+ return a->comp_len * comp_sz(a->comp_type);
+}
+
+static unsigned attrib_align(const GPUVertAttr *a)
+{
+ if (a->comp_type == GPU_COMP_I10) {
+ return 4; /* always packed as 10_10_10_2 */
+ }
+ unsigned c = comp_sz(a->comp_type);
+ if (a->comp_len == 3 && c <= 2) {
+ return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */
+ }
+ else {
+ return c; /* most fetches are ok if components are naturally aligned */
+ }
+}
+
+unsigned vertex_buffer_size(const GPUVertFormat *format, unsigned vertex_len)
+{
+#if TRUST_NO_ONE
+ assert(format->packed && format->stride > 0);
+#endif
+ return format->stride * vertex_len;
+}
+
+static const char *copy_attrib_name(GPUVertFormat *format, const char *name)
+{
+ /* strncpy does 110% of what we need; let's do exactly 100% */
+ char *name_copy = format->names + format->name_offset;
+ unsigned available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset;
+ bool terminated = false;
+
+ for (unsigned i = 0; i < available; ++i) {
+ const char c = name[i];
+ name_copy[i] = c;
+ if (c == '\0') {
+ terminated = true;
+ format->name_offset += (i + 1);
+ break;
+ }
+ }
+#if TRUST_NO_ONE
+ assert(terminated);
+ assert(format->name_offset <= GPU_VERT_ATTR_NAMES_BUF_LEN);
+#else
+ (void)terminated;
+#endif
+ return name_copy;
+}
+
+unsigned GPU_vertformat_attr_add(
+ GPUVertFormat *format, const char *name,
+ GPUVertCompType comp_type, unsigned comp_len, GPUVertFetchMode fetch_mode)
+{
+#if TRUST_NO_ONE
+ assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
+ assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
+ assert(!format->packed); /* packed means frozen/locked */
+ assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16);
+
+ switch (comp_type) {
+ case GPU_COMP_F32:
+ /* float type can only kept as float */
+ assert(fetch_mode == GPU_FETCH_FLOAT);
+ break;
+ case GPU_COMP_I10:
+ /* 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_len == 3 || comp_len == 4);
+ assert(fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT); /* not strictly required, may relax later */
+ break;
+ default:
+ /* integer types can be kept as int or converted/normalized to float */
+ assert(fetch_mode != GPU_FETCH_FLOAT);
+ /* only support float matrices (see Batch_update_program_bindings) */
+ assert(comp_len != 8 && comp_len != 12 && comp_len != 16);
+ }
+#endif
+ format->name_len++; /* multiname support */
+
+ const unsigned attrib_id = format->attr_len++;
+ GPUVertAttr *attrib = format->attribs + attrib_id;
+
+ attrib->name[attrib->name_len++] = copy_attrib_name(format, name);
+ attrib->comp_type = comp_type;
+ attrib->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ attrib->comp_len = (comp_type == GPU_COMP_I10) ? 4 : comp_len; /* system needs 10_10_10_2 to be 4 or BGRA */
+ attrib->sz = attrib_sz(attrib);
+ attrib->offset = 0; /* offsets & stride are calculated later (during pack) */
+ attrib->fetch_mode = fetch_mode;
+
+ return attrib_id;
+}
+
+void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
+{
+ GPUVertAttr *attrib = format->attribs + (format->attr_len - 1);
+#if TRUST_NO_ONE
+ assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
+ assert(attrib->name_len < GPU_VERT_ATTR_MAX_NAMES);
+#endif
+ format->name_len++; /* multiname support */
+ attrib->name[attrib->name_len++] = copy_attrib_name(format, alias);
+}
+
+unsigned padding(unsigned offset, unsigned alignment)
+{
+ const unsigned mod = offset % alignment;
+ return (mod == 0) ? 0 : (alignment - mod);
+}
+
+#if PACK_DEBUG
+static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
+{
+ const char c = 'A' + a_idx;
+ for (unsigned i = 0; i < pad; ++i) {
+ putchar('-');
+ }
+ for (unsigned i = 0; i < sz; ++i) {
+ putchar(c);
+ }
+}
+#endif
+
+void VertexFormat_pack(GPUVertFormat *format)
+{
+ /* For now, attributes are packed in the order they were added,
+ * making sure each attrib is naturally aligned (add padding where necessary)
+ * Later we can implement more efficient packing w/ reordering
+ * (keep attrib ID order, adjust their offsets to reorder in buffer). */
+
+ /* TODO: realloc just enough to hold the final combo string. And just enough to
+ * hold used attribs, not all 16. */
+
+ GPUVertAttr *a0 = format->attribs + 0;
+ a0->offset = 0;
+ unsigned offset = a0->sz;
+
+#if PACK_DEBUG
+ show_pack(0, a0->sz, 0);
+#endif
+
+ for (unsigned a_idx = 1; a_idx < format->attr_len; ++a_idx) {
+ GPUVertAttr *a = format->attribs + a_idx;
+ unsigned mid_padding = padding(offset, attrib_align(a));
+ offset += mid_padding;
+ a->offset = offset;
+ offset += a->sz;
+
+#if PACK_DEBUG
+ show_pack(a_idx, a->sz, mid_padding);
+#endif
+ }
+
+ unsigned end_padding = padding(offset, attrib_align(a0));
+
+#if PACK_DEBUG
+ show_pack(0, 0, end_padding);
+ putchar('\n');
+#endif
+ format->stride = offset + end_padding;
+ format->packed = true;
+}
+
+
+/* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
+ * Of the code here, only struct GPUPackedNormal needs to change. */
+
+#define SIGNED_INT_10_MAX 511
+#define SIGNED_INT_10_MIN -512
+
+static int clampi(int x, int min_allowed, int max_allowed)
+{
+#if TRUST_NO_ONE
+ assert(min_allowed <= max_allowed);
+#endif
+ if (x < min_allowed) {
+ return min_allowed;
+ }
+ else if (x > max_allowed) {
+ return max_allowed;
+ }
+ else {
+ return x;
+ }
+}
+
+static int quantize(float x)
+{
+ int qx = x * 511.0f;
+ return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX);
+}
+
+static int convert_i16(short x)
+{
+ /* 16-bit signed --> 10-bit signed */
+ /* TODO: round? */
+ return x >> 6;
+}
+
+GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3])
+{
+ GPUPackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) };
+ return n;
+}
+
+GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3])
+{
+ GPUPackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]) };
+ return n;
+}
diff --git a/source/blender/gpu/intern/gpu_vertex_format_private.h b/source/blender/gpu/intern/gpu_vertex_format_private.h
new file mode 100644
index 00000000000..e4fe61e8697
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_vertex_format_private.h
@@ -0,0 +1,39 @@
+/*
+ * ***** 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_vertex_format_private.h
+ * \ingroup gpu
+ *
+ * GPU vertex format
+ */
+
+#ifndef __GPU_VERTEX_FORMAT_PRIVATE_H__
+#define __GPU_VERTEX_FORMAT_PRIVATE_H__
+
+void VertexFormat_pack(GPUVertFormat *format);
+uint padding(uint offset, uint alignment);
+uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len);
+
+#endif /* __GPU_VERTEX_FORMAT_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 0bf215f31a8..5d495779ba1 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -539,9 +539,9 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy);
glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x1, y1, x2, y2);
- glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
- GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
+ GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
GPU_texture_unbind(color);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl
new file mode 100644
index 00000000000..328fbbe26a1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl
@@ -0,0 +1,166 @@
+uniform vec4 color;
+uniform vec4 color2;
+uniform int fill_type;
+uniform float mix_factor;
+
+uniform float g_angle;
+uniform float g_radius;
+uniform float g_boxsize;
+uniform vec2 g_scale;
+uniform vec2 g_shift;
+
+uniform float t_angle;
+uniform vec2 t_scale;
+uniform vec2 t_offset;
+uniform int t_mix;
+uniform int t_flip;
+uniform float t_opacity;
+
+uniform sampler2D myTexture;
+
+/* keep this list synchronized with list in DNA_brush_types.h */
+#define SOLID 0
+#define GRADIENT 1
+#define RADIAL 2
+#define CHESS 3
+#define TEXTURE 4
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+#define texture2D texture
+
+void set_color(in vec4 color, in vec4 color2, in vec4 tcolor, in float mixv, in float factor,
+ in int tmix, in int flip, out vec4 ocolor)
+{
+ /* full color A */
+ if (mixv == 1.0) {
+ if (tmix == 1) {
+ if (flip == 0) {
+ ocolor = color;
+ }
+ else {
+ ocolor = tcolor;
+ }
+ }
+ else {
+ if (flip == 0) {
+ ocolor = color;
+ }
+ else {
+ ocolor = color2;
+ }
+ }
+ }
+ /* full color B */
+ else if (mixv == 0.0) {
+ if (tmix == 1) {
+ if (flip == 0) {
+ ocolor = tcolor;
+ }
+ else {
+ ocolor = color;
+ }
+ }
+ else {
+ if (flip == 0) {
+ ocolor = color2;
+ }
+ else {
+ ocolor = color;
+ }
+ }
+ }
+ /* mix of colors */
+ else {
+ if (tmix == 1) {
+ if (flip == 0) {
+ ocolor = mix(color, tcolor, factor);
+ }
+ else {
+ ocolor = mix(tcolor, color, factor);
+ }
+ }
+ else {
+ if (flip == 0) {
+ ocolor = mix(color, color2, factor);
+ }
+ else {
+ ocolor = mix(color2, color, factor);
+ }
+ }
+ }
+}
+
+void main()
+{
+ vec2 t_center = vec2(0.5, 0.5);
+ mat2 matrot_tex = mat2(cos(t_angle), -sin(t_angle), sin(t_angle), cos(t_angle));
+ vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + t_offset;
+ vec4 tmp_color = texture2D(myTexture, rot_tex * t_scale);
+ vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * t_opacity);
+ vec4 chesscolor;
+
+ /* solid fill */
+ if (fill_type == SOLID) {
+ if (t_mix == 1) {
+ fragColor = mix(color, text_color, mix_factor);
+ }
+ else {
+ fragColor = color;
+ }
+ }
+ else {
+ vec2 center = vec2(0.5, 0.5) + g_shift;
+ mat2 matrot = mat2(cos(g_angle), -sin(g_angle), sin(g_angle), cos(g_angle));
+ vec2 rot = (((matrot * (texCoord_interp - center)) + center) * g_scale) + g_shift;
+ /* gradient */
+ if (fill_type == GRADIENT) {
+ set_color(color, color2, text_color, mix_factor, rot.x - mix_factor + 0.5, t_mix, t_flip, fragColor);
+ }
+ /* radial gradient */
+ if (fill_type == RADIAL) {
+ float in_rad = g_radius * mix_factor;
+ float ex_rad = g_radius - in_rad;
+ float intensity = 0;
+ float distance = length((center - texCoord_interp) * g_scale);
+ if (distance > g_radius) {
+ discard;
+ }
+ if (distance > in_rad) {
+ intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0);
+ }
+ set_color(color, color2, text_color, mix_factor, intensity, t_mix, t_flip, fragColor);
+ }
+ /* chessboard */
+ if (fill_type == CHESS) {
+ vec2 pos = rot / g_boxsize;
+ if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) {
+ if (t_flip == 0) {
+ chesscolor = color;
+ }
+ else {
+ chesscolor = color2;
+ }
+ }
+ else {
+ if (t_flip == 0) {
+ chesscolor = color2;
+ }
+ else {
+ chesscolor = color;
+ }
+ }
+ /* mix with texture */
+ if (t_mix == 1) {
+ fragColor = mix(chesscolor, text_color, mix_factor);
+ }
+ else {
+ fragColor = chesscolor;
+ }
+ }
+ /* texture */
+ if (fill_type == TEXTURE) {
+ fragColor = text_color;
+ }
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl
new file mode 100644
index 00000000000..2bc381a3689
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl
@@ -0,0 +1,11 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec2 texCoord;
+out vec2 texCoord_interp;
+
+void main(void)
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl
new file mode 100644
index 00000000000..7bb7693d202
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl
@@ -0,0 +1,20 @@
+in vec4 mColor;
+in vec2 mTexCoord;
+
+out vec4 fragColor;
+
+void main()
+{
+ const vec2 center = vec2(0, 0.5);
+ vec4 tColor = vec4(mColor);
+ /* if alpha < 0, then encap */
+ if (mColor.a < 0) {
+ tColor.a = tColor.a * -1.0;
+ float dist = length(mTexCoord - center);
+ if (dist > 0.25) {
+ discard;
+ }
+ }
+ /* Solid */
+ fragColor = tColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl
new file mode 100644
index 00000000000..3de1bd838b3
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl
@@ -0,0 +1,196 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 Viewport;
+uniform int xraymode;
+
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 13) out;
+
+in vec4 finalColor[4];
+in float finalThickness[4];
+
+out vec4 mColor;
+out vec2 mTexCoord;
+
+#define GP_XRAY_FRONT 0
+#define GP_XRAY_3DSPACE 1
+#define GP_XRAY_BACK 2
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ return vec2(vertex.xy / vertex.w) * Viewport;
+}
+
+/* get zdepth value */
+float getZdepth(vec4 point)
+{
+ if (xraymode == GP_XRAY_FRONT) {
+ return 0.0;
+ }
+ if (xraymode == GP_XRAY_3DSPACE) {
+ return (point.z / point.w);
+ }
+ if (xraymode == GP_XRAY_BACK) {
+ return 1.0;
+ }
+
+ /* in front by default */
+ return 0.0;
+}
+void main(void)
+{
+ float MiterLimit = 0.75;
+
+ /* receive 4 points */
+ vec4 P0 = gl_in[0].gl_Position;
+ vec4 P1 = gl_in[1].gl_Position;
+ vec4 P2 = gl_in[2].gl_Position;
+ vec4 P3 = gl_in[3].gl_Position;
+
+ /* get the four vertices passed to the shader */
+ vec2 sp0 = toScreenSpace(P0); // start of previous segment
+ vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment
+ vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment
+ vec2 sp3 = toScreenSpace(P3); // end of next segment
+
+ /* culling outside viewport */
+ vec2 area = Viewport * 4.0;
+ if (sp1.x < -area.x || sp1.x > area.x) return;
+ if (sp1.y < -area.y || sp1.y > area.y) return;
+ if (sp2.x < -area.x || sp2.x > area.x) return;
+ if (sp2.y < -area.y || sp2.y > area.y) return;
+
+ /* determine the direction of each of the 3 segments (previous, current, next) */
+ vec2 v0 = normalize(sp1 - sp0);
+ vec2 v1 = normalize(sp2 - sp1);
+ vec2 v2 = normalize(sp3 - sp2);
+
+ /* determine the normal of each of the 3 segments (previous, current, next) */
+ vec2 n0 = vec2(-v0.y, v0.x);
+ vec2 n1 = vec2(-v1.y, v1.x);
+ vec2 n2 = vec2(-v2.y, v2.x);
+
+ /* determine miter lines by averaging the normals of the 2 segments */
+ vec2 miter_a = normalize(n0 + n1); // miter at start of current segment
+ vec2 miter_b = normalize(n1 + n2); // miter at end of current segment
+
+ /* determine the length of the miter by projecting it onto normal and then inverse it */
+ float an1 = dot(miter_a, n1);
+ float bn1 = dot(miter_b, n2);
+ if (an1 == 0) an1 = 1;
+ if (bn1 == 0) bn1 = 1;
+ float length_a = finalThickness[1] / an1;
+ float length_b = finalThickness[2] / bn1;
+ if (length_a <= 0.0) length_a = 0.01;
+ if (length_b <= 0.0) length_b = 0.01;
+
+ /* prevent excessively long miters at sharp corners */
+ if (dot(v0, v1) < -MiterLimit) {
+ miter_a = n1;
+ length_a = finalThickness[1];
+
+ /* close the gap */
+ if (dot(v0, n1) > 0) {
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0.5);
+ mColor = finalColor[1];
+ gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+ }
+ else {
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0.5);
+ mColor = finalColor[1];
+ gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+ }
+ }
+
+ if (dot(v1, v2) < -MiterLimit) {
+ miter_b = n1;
+ length_b = finalThickness[2];
+ }
+
+ /* generate the start endcap (alpha < 0 used as endcap flag)*/
+ if (P0 == P2) {
+ mTexCoord = vec2(1, 0.5);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0;
+ gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 1);
+ mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
+ gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+ }
+
+ /* generate the triangle strip */
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[1];
+ gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = finalColor[2];
+ gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 1);
+ mColor = finalColor[2];
+ gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ /* generate the end endcap (alpha < 0 used as endcap flag)*/
+ if (P1 == P3) {
+ mTexCoord = vec2(0, 1);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(0, 0);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+
+ mTexCoord = vec2(1, 0.5);
+ mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
+ vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0;
+ gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0);
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl
new file mode 100644
index 00000000000..5f4f56dcca1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl
@@ -0,0 +1,33 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform int keep_size;
+uniform float objscale;
+uniform int pixfactor;
+
+in vec3 pos;
+in vec4 color;
+in float thickness;
+
+out vec4 finalColor;
+out float finalThickness;
+
+#define TRUE 1
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+
+void main(void)
+{
+ gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 );
+ finalColor = color;
+
+ if (keep_size == TRUE) {
+ finalThickness = thickness;
+ }
+ else {
+ float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize);
+ finalThickness = max(size * objscale, 1.0);
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
index 57362c88320..1f59c9dfdbd 100644
--- a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
@@ -8,8 +8,6 @@ out vec4 fragColor;
#error "Too many samples"
#endif
-// #define USE_DEPTH_WEIGHTING
-
void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
@@ -19,26 +17,26 @@ void main()
vec4 d1, d2, d3, d4;
vec4 c1, c2, c3, c4, c5, c6, c7, c8;
vec4 c9, c10, c11, c12, c13, c14, c15, c16;
- d1 = d2 = d3 = d4 = vec4(1.0);
+ d1 = d2 = d3 = d4 = vec4(0.5);
w1 = w2 = w3 = w4 = vec4(0.0);
c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0);
c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0);
+#ifdef USE_DEPTH
/* Depth */
-
d1.x = texelFetch(depthMulti, texel, 0).r;
d1.y = texelFetch(depthMulti, texel, 1).r;
-#if SAMPLES > 2
+# if SAMPLES > 2
d1.z = texelFetch(depthMulti, texel, 2).r;
d1.w = texelFetch(depthMulti, texel, 3).r;
-#endif
-#if SAMPLES > 4
+# endif
+# if SAMPLES > 4
d2.x = texelFetch(depthMulti, texel, 4).r;
d2.y = texelFetch(depthMulti, texel, 5).r;
d2.z = texelFetch(depthMulti, texel, 6).r;
d2.w = texelFetch(depthMulti, texel, 7).r;
-#endif
-#if SAMPLES > 8
+# endif
+# if SAMPLES > 8
d3.x = texelFetch(depthMulti, texel, 8).r;
d3.y = texelFetch(depthMulti, texel, 9).r;
d3.z = texelFetch(depthMulti, texel, 10).r;
@@ -47,6 +45,7 @@ void main()
d4.y = texelFetch(depthMulti, texel, 13).r;
d4.z = texelFetch(depthMulti, texel, 14).r;
d4.w = texelFetch(depthMulti, texel, 15).r;
+# endif
#endif
/* COLOR */
@@ -89,22 +88,26 @@ void main()
}
#endif
-#if SAMPLES > 8
- d1 = min(d1, min(d3, d4));
-#endif
-#if SAMPLES > 4
- d1 = min(d1, d2);
-#endif
-#if SAMPLES > 2
- d1.xy = min(d1.xy, d1.zw);
-#endif
- gl_FragDepth = min(d1.x, d1.y);
-
-#ifdef USE_DEPTH_WEIGHTING
- c1 *= w1.x; c2 *= w1.y; c3 *= w1.z; c4 *= w1.w;
- c5 *= w2.x; c6 *= w2.y; c7 *= w2.z; c8 *= w2.w;
- c9 *= w3.x; c10 *= w3.y; c11 *= w3.z; c12 *= w3.w;
- c13 *= w4.x; c14 *= w4.y; c15 *= w4.z; c16 *= w4.w;
+#ifdef USE_DEPTH
+ d1 *= 1.0 - step(1.0, d1); /* make far plane depth = 0 */
+# if SAMPLES > 8
+ d4 *= 1.0 - step(1.0, d4);
+ d3 *= 1.0 - step(1.0, d3);
+ d1 = max(d1, max(d3, d4));
+# endif
+# if SAMPLES > 4
+ d2 *= 1.0 - step(1.0, d2);
+ d1 = max(d1, d2);
+ d1 = max(d1, d2);
+# endif
+# if SAMPLES > 2
+ d1.xy = max(d1.xy, d1.zw);
+# endif
+ gl_FragDepth = max(d1.x, d1.y);
+ /* Don't let the 0.0 farplane occlude other things */
+ if (gl_FragDepth == 0.0) {
+ gl_FragDepth = 1.0;
+ }
#endif
c1 = c1 + c2;
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index d1183c792f5..40aba1cc004 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -238,13 +238,11 @@ void point_map_to_tube(vec3 vin, out vec3 vout)
vout = vec3(u, v, 0.0);
}
-void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
+void mapping(vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec)
{
+ mat4 mat = mat4(m0, m1, m2, m3);
outvec = (mat * vec4(vec, 1.0)).xyz;
- if (domin == 1.0)
- outvec = max(outvec, minvec);
- if (domax == 1.0)
- outvec = min(outvec, maxvec);
+ outvec = clamp(outvec, minvec, maxvec);
}
void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
@@ -482,27 +480,26 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
outdot = dot(normalize(dir), nor);
}
-void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
+void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec)
{
- outvec.x = texture(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
- outvec.y = texture(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
- outvec.z = texture(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
-
- if (fac != 1.0)
- outvec = (outvec * fac) + (vec * (1.0 - fac));
-
+ vec4 co = vec4(vec * 0.5 + 0.5, layer);
+ outvec.x = texture(curvemap, co.xw).x;
+ outvec.y = texture(curvemap, co.yw).y;
+ outvec.z = texture(curvemap, co.zw).z;
+ outvec = mix(vec, outvec, fac);
}
-void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
+void curves_rgb(float fac, vec4 col, sampler1DArray curvemap, float layer, out vec4 outcol)
{
- outcol.r = texture(curvemap, vec2(texture(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
- outcol.g = texture(curvemap, vec2(texture(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
- outcol.b = texture(curvemap, vec2(texture(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
-
- if (fac != 1.0)
- outcol = (outcol * fac) + (col * (1.0 - fac));
-
+ vec4 co = vec4(col.rgb, layer);
+ co.x = texture(curvemap, co.xw).a;
+ co.y = texture(curvemap, co.yw).a;
+ co.z = texture(curvemap, co.zw).a;
+ outcol.r = texture(curvemap, co.xw).r;
+ outcol.g = texture(curvemap, co.yw).g;
+ outcol.b = texture(curvemap, co.zw).b;
outcol.a = col.a;
+ outcol = mix(col, outcol, fac);
}
void set_value(float val, out float outval)
@@ -815,9 +812,15 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
outcol = col1 + fac * (2.0 * (col2 - vec4(0.5)));
}
-void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
+void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha)
+{
+ outcol = texture(colormap, vec2(fac, layer));
+ outalpha = outcol.a;
+}
+
+void valtorgb_nearest(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha)
{
- outcol = texture(colormap, vec2(fac, 0.0));
+ outcol = texelFetch(colormap, ivec2(fac * textureSize(colormap, 0).x, layer), 0);
outalpha = outcol.a;
}
@@ -1067,15 +1070,27 @@ float floorfrac(float x, out int i)
/* bsdfs */
+vec3 tint_from_color(vec3 color)
+{
+ float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+}
+
void convert_metallic_to_specular_tinted(
- vec3 basecol, float metallic, float specular_fac, float specular_tint,
+ vec3 basecol, vec3 basecol_tint, float metallic, float specular_fac, float specular_tint,
out vec3 diffuse, out vec3 f0)
{
- vec3 dielectric = vec3(0.034) * specular_fac * 2.0;
- float lum = dot(basecol, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
- vec3 tint = lum > 0 ? basecol / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
- f0 = mix(dielectric * mix(vec3(1.0), tint, specular_tint), basecol, metallic);
- diffuse = mix(basecol, vec3(0.0), metallic);
+ vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint);
+ f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic);
+ diffuse = basecol * (1.0 - metallic);
+}
+
+vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint)
+{
+ float f = 1.0 - NV;
+ /* Empirical approximation (manual curve fitting). Can be refined. */
+ float sheen = f*f*f*0.077 + f*0.01 + 0.00026;
+ return sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
}
#ifndef VOLUMETRICS
@@ -1104,7 +1119,7 @@ void node_bsdf_anisotropic(
vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T,
out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+ node_bsdf_glossy(color, roughness, N, -1, result);
}
void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result)
@@ -1128,62 +1143,201 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure r
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
- float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
- float sss_id, vec3 sss_scale, out Closure result)
+void node_bsdf_principled(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
{
+ ior = max(ior, 1e-5);
metallic = saturate(metallic);
transmission = saturate(transmission);
+ float dielectric = 1.0 - metallic;
+ transmission *= dielectric;
+ sheen *= dielectric;
+ subsurface_color *= dielectric;
vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
- convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
+ vec3 ctint = tint_from_color(base_color.rgb);
+ convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
- transmission *= 1.0 - metallic;
- subsurface *= 1.0 - metallic;
+ float NV = dot(N, cameraVec);
+ vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
- clearcoat *= 0.25;
- clearcoat *= 1.0 - transmission;
+ /* Far from being accurate, but 2 glossy evaluation is too expensive.
+ * Most noticeable difference is at grazing angles since the bsdf lut
+ * f0 color interpolation is done on top of this interpolation. */
+ vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint);
+ float fresnel = F_eta(ior, NV);
+ vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
+ f0 = mix(f0, spec_col, transmission);
-#ifdef USE_SSS
- diffuse = mix(diffuse, vec3(0.0), subsurface);
-#else
- diffuse = mix(diffuse, subsurface_color.rgb, subsurface);
-#endif
- f0 = mix(f0, vec3(1.0), transmission);
+ vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
- float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0));
- eevee_closure_principled(N, diffuse, f0, int(ssr_id), roughness,
- CN, clearcoat, clearcoat_roughness, 1.0, sss_scalef, ior,
+ float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface;
+ eevee_closure_principled(N, mixed_ss_base_color, f0, int(ssr_id), roughness,
+ CN, clearcoat * 0.25, clearcoat_roughness, 1.0, sss_scalef, ior,
out_diff, out_trans, out_spec, out_refr, ssr_spec);
vec3 refr_color = base_color.rgb;
refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */
+ out_refr *= refr_color * (1.0 - fresnel) * transmission;
- float fresnel = F_eta(ior, dot(N, cameraVec));
- vec3 refr_spec_color = base_color.rgb * fresnel;
- /* This bit maybe innacurate. */
- out_refr = out_refr * refr_color * (1.0 - fresnel) + out_spec * refr_spec_color;
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_refr;
+ result.radiance += out_diff * out_sheen; /* Coarse approx. */
+#ifndef USE_SSS
+ result.radiance += (out_diff + out_trans) * mixed_ss_base_color * (1.0 - transmission);
+#endif
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+#ifdef USE_SSS
+ result.sss_data.a = sss_scalef;
+ result.sss_data.rgb = out_diff + out_trans;
+# ifdef USE_SSS_ALBEDO
+ result.sss_albedo.rgb = mixed_ss_base_color;
+# else
+ result.sss_data.rgb *= mixed_ss_base_color;
+# endif
+ result.sss_data.rgb *= (1.0 - transmission);
+#endif
+}
+
+void node_bsdf_principled_dielectric(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ metallic = saturate(metallic);
+ float dielectric = 1.0 - metallic;
- ssr_spec = mix(ssr_spec, refr_spec_color, transmission);
+ vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
+ vec3 ctint = tint_from_color(base_color.rgb);
+ convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
+
+ float NV = dot(N, cameraVec);
+ vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+
+ eevee_closure_default(N, diffuse, f0, int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_diff * (diffuse + out_sheen);
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+}
+
+void node_bsdf_principled_metallic(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ vec3 out_spec, ssr_spec;
+
+ eevee_closure_glossy(N, base_color.rgb, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec;
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+}
+
+void node_bsdf_principled_clearcoat(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ vec3 out_spec, ssr_spec;
+
+ eevee_closure_clearcoat(N, base_color.rgb, int(ssr_id), roughness, CN, clearcoat * 0.25, clearcoat_roughness,
+ 1.0, out_spec, ssr_spec);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
- result.radiance = out_spec + out_diff * diffuse;
- result.radiance = mix(result.radiance, out_refr, transmission);
+ result.radiance = out_spec;
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+}
+
+void node_bsdf_principled_subsurface(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ metallic = saturate(metallic);
+
+ vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec;
+ vec3 ctint = tint_from_color(base_color.rgb);
+ convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
+
+ subsurface_color = subsurface_color * (1.0 - metallic);
+ vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
+ float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface;
+
+ float NV = dot(N, cameraVec);
+ vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+
+ eevee_closure_skin(N, mixed_ss_base_color, f0, int(ssr_id), roughness, 1.0, sss_scalef,
+ out_diff, out_trans, out_spec, ssr_spec);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec;
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
#ifdef USE_SSS
result.sss_data.a = sss_scalef;
result.sss_data.rgb = out_diff + out_trans;
-#ifdef USE_SSS_ALBEDO
- result.sss_albedo.rgb = mix(vec3(0.0), subsurface_color.rgb, subsurface);
+# ifdef USE_SSS_ALBEDO
+ result.sss_albedo.rgb = mixed_ss_base_color;
+# else
+ result.sss_data.rgb *= mixed_ss_base_color;
+# endif
#else
- result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface);
-#endif
- result.sss_data.rgb *= (1.0 - transmission);
+ result.radiance += (out_diff + out_trans) * mixed_ss_base_color;
#endif
+ result.radiance += out_diff * out_sheen;
+}
+
+void node_bsdf_principled_glass(
+ vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ ior = max(ior, 1e-5);
+
+ vec3 f0, out_spec, out_refr, ssr_spec;
+ f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
+
+ eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+
+ vec3 refr_color = base_color.rgb;
+ refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission events */
+ out_refr *= refr_color;
+
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 spec_col = F_color_blend(ior, fresnel, f0);
+ out_spec *= spec_col;
+ ssr_spec *= spec_col * fresnel;
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
}
void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
@@ -1219,13 +1373,13 @@ void node_subsurface_scattering(
result.sss_data.a = scale;
eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
result.sss_data.rgb = out_diff + out_trans;
-#ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
/* Not perfect for texture_blur not exaclty equal to 0.0 or 1.0. */
result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur);
result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur);
-#else
+# else
result.sss_data.rgb *= color.rgb;
-#endif
+# endif
#else
node_bsdf_diffuse(color, 0.0, N, result);
#endif
@@ -1315,17 +1469,17 @@ void node_volume_absorption(vec4 color, float density, out Closure result)
#endif
}
-void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color)
+void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color)
{
- if(temperature >= 12000.0) {
+ if (temperature >= 12000.0) {
color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0);
}
- else if(temperature < 965.0) {
+ else if (temperature < 965.0) {
color = vec4(4.70366907, 0.0, 0.0, 1.0);
}
else {
float t = (temperature - 965.0) / (12000.0 - 965.0);
- color = vec4(texture(spectrummap, vec2(t, 0.0)).rgb, 1.0);
+ color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0);
}
}
@@ -1342,7 +1496,8 @@ void node_volume_principled(
float density_attribute,
vec4 color_attribute,
float temperature_attribute,
- sampler2D spectrummap,
+ sampler1DArray spectrummap,
+ float layer,
out Closure result)
{
#ifdef VOLUMETRICS
@@ -1384,7 +1539,7 @@ void node_volume_principled(
if(intensity > 1e-5) {
vec4 bb;
- node_blackbody(T, spectrummap, bb);
+ node_blackbody(T, spectrummap, layer, bb);
emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
}
}
@@ -1798,24 +1953,192 @@ void node_tex_environment_empty(vec3 co, out vec4 color)
color = vec4(1.0, 0.0, 1.0, 1.0);
}
-void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
color = texture(ima, co.xy);
alpha = color.a;
}
+void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy);
+ color = texelFetch(ima, pix, 0);
+ alpha = color.a;
+}
+
+void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ vec2 tex_size = vec2(textureSize(ima, 0).xy);
+
+ co.xy *= tex_size;
+ /* texel center */
+ vec2 tc = floor(co.xy - 0.5) + 0.5;
+ vec2 f = co.xy - tc;
+ vec2 f2 = f * f;
+ vec2 f3 = f2 * f;
+ /* Bspline coefs (optimized) */
+ vec2 w3 = f3 / 6.0;
+ vec2 w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0;
+ vec2 w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0;
+ vec2 w2 = 1.0 - w0 - w1 - w3;
+
+#if 1 /* Optimized version using 4 filtered tap. */
+ vec2 s0 = w0 + w1;
+ vec2 s1 = w2 + w3;
+
+ vec2 f0 = w1 / (w0 + w1);
+ vec2 f1 = w3 / (w2 + w3);
+
+ vec4 final_co;
+ final_co.xy = tc - 1.0 + f0;
+ final_co.zw = tc + 1.0 + f1;
+
+ final_co /= tex_size.xyxy;
+
+ color = texture(ima, final_co.xy) * s0.x * s0.y;
+ color += texture(ima, final_co.zy) * s1.x * s0.y;
+ color += texture(ima, final_co.xw) * s0.x * s1.y;
+ color += texture(ima, final_co.zw) * s1.x * s1.y;
+
+#else /* Reference bruteforce 16 tap. */
+ color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 0.0, -1.0)), 0) * w1.x * w0.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 1.0, -1.0)), 0) * w2.x * w0.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 2.0, -1.0)), 0) * w3.x * w0.y;
+
+ color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 0.0, 0.0)), 0) * w1.x * w1.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 1.0, 0.0)), 0) * w2.x * w1.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 2.0, 0.0)), 0) * w3.x * w1.y;
+
+ color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 0.0, 1.0)), 0) * w1.x * w2.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 1.0, 1.0)), 0) * w2.x * w2.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 2.0, 1.0)), 0) * w3.x * w2.y;
+
+ color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 0.0, 2.0)), 0) * w1.x * w3.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 1.0, 2.0)), 0) * w2.x * w3.y;
+ color += texelFetch(ima, ivec2(tc + vec2( 2.0, 2.0)), 0) * w3.x * w3.y;
+#endif
+
+ alpha = color.a;
+}
+
+void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ /* use cubic for now */
+ node_tex_image_cubic(co, ima, color, alpha);
+}
+
+void tex_box_sample_linear(vec3 texco,
+ vec3 N,
+ sampler2D ima,
+ out vec4 color1,
+ out vec4 color2,
+ out vec4 color3)
+{
+ /* X projection */
+ vec2 uv = texco.yz;
+ if (N.x < 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color1 = texture(ima, uv);
+ /* Y projection */
+ uv = texco.xz;
+ if (N.y > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color2 = texture(ima, uv);
+ /* Z projection */
+ uv = texco.yx;
+ if (N.z > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ color3 = texture(ima, uv);
+}
+
+void tex_box_sample_nearest(vec3 texco,
+ vec3 N,
+ sampler2D ima,
+ out vec4 color1,
+ out vec4 color2,
+ out vec4 color3)
+{
+ /* X projection */
+ vec2 uv = texco.yz;
+ if (N.x < 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy);
+ color1 = texelFetch(ima, pix, 0);
+ /* Y projection */
+ uv = texco.xz;
+ if (N.y > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ pix = ivec2(uv.xy * textureSize(ima, 0).xy);
+ color2 = texelFetch(ima, pix, 0);
+ /* Z projection */
+ uv = texco.yx;
+ if (N.z > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ pix = ivec2(uv.xy * textureSize(ima, 0).xy);
+ color3 = texelFetch(ima, pix, 0);
+}
+
+void tex_box_sample_cubic(vec3 texco,
+ vec3 N,
+ sampler2D ima,
+ out vec4 color1,
+ out vec4 color2,
+ out vec4 color3)
+{
+ float alpha;
+ /* X projection */
+ vec2 uv = texco.yz;
+ if (N.x < 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ node_tex_image_cubic(uv.xyy, ima, color1, alpha);
+ /* Y projection */
+ uv = texco.xz;
+ if (N.y > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ node_tex_image_cubic(uv.xyy, ima, color2, alpha);
+ /* Z projection */
+ uv = texco.yx;
+ if (N.z > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ node_tex_image_cubic(uv.xyy, ima, color3, alpha);
+}
+
+void tex_box_sample_smart(vec3 texco,
+ vec3 N,
+ sampler2D ima,
+ out vec4 color1,
+ out vec4 color2,
+ out vec4 color3)
+{
+ tex_box_sample_cubic(texco, N, ima, color1, color2, color3);
+}
+
void node_tex_image_box(vec3 texco,
vec3 N,
+ vec4 color1,
+ vec4 color2,
+ vec4 color3,
sampler2D ima,
float blend,
out vec4 color,
out float alpha)
{
- vec3 signed_N = N;
-
/* project from direction vector to barycentric coordinates in triangles */
- N = vec3(abs(N.x), abs(N.y), abs(N.z));
- N /= (N.x + N.y + N.z);
+ N = abs(N);
+ N /= dot(N, vec3(1.0));
/* basic idea is to think of this as a triangle, each corner representing
* one of the 3 faces of the cube. in the corners we have single textures,
@@ -1825,72 +2148,36 @@ void node_tex_image_box(vec3 texco,
* the Nxyz values are the barycentric coordinates in an equilateral
* triangle, which in case of blending, in the middle has a smaller
* equilateral triangle where 3 textures blend. this divides things into
- * 7 zones, with an if () test for each zone */
+ * 7 zones, with an if () test for each zone
+ * EDIT: Now there is only 4 if's. */
+
+ float limit = 0.5 + 0.5 * blend;
- vec3 weight = vec3(0.0, 0.0, 0.0);
- float limit = 0.5 * (1.0 + blend);
+ vec3 weight;
+ weight.x = N.x / (N.x + N.y);
+ weight.y = N.y / (N.y + N.z);
+ weight.z = N.z / (N.x + N.z);
+ weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0);
- /* first test for corners with single texture */
- if (N.x > limit * (N.x + N.y) && N.x > limit * (N.x + N.z)) {
- weight.x = 1.0;
+ /* test for mixes between two textures */
+ if (N.z < (1.0 - limit) * (N.y + N.x)) {
+ weight.z = 0.0;
+ weight.y = 1.0 - weight.x;
}
- else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) {
- weight.y = 1.0;
+ else if (N.x < (1.0 - limit) * (N.y + N.z)) {
+ weight.x = 0.0;
+ weight.z = 1.0 - weight.y;
}
- else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) {
- weight.z = 1.0;
- }
- else if (blend > 0.0) {
- /* in case of blending, test for mixes between two textures */
- if (N.z < (1.0 - limit) * (N.y + N.x)) {
- weight.x = N.x / (N.x + N.y);
- weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight.y = 1.0 - weight.x;
- }
- else if (N.x < (1.0 - limit) * (N.y + N.z)) {
- weight.y = N.y / (N.y + N.z);
- weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight.z = 1.0 - weight.y;
- }
- else if (N.y < (1.0 - limit) * (N.x + N.z)) {
- weight.x = N.x / (N.x + N.z);
- weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight.z = 1.0 - weight.x;
- }
- else {
- /* last case, we have a mix between three */
- weight.x = ((2.0 - limit) * N.x + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight.y = ((2.0 - limit) * N.y + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight.z = ((2.0 - limit) * N.z + (limit - 1.0)) / (2.0 * limit - 1.0);
- }
+ else if (N.y < (1.0 - limit) * (N.x + N.z)) {
+ weight.y = 0.0;
+ weight.x = 1.0 - weight.z;
}
else {
- /* Desperate mode, no valid choice anyway, fallback to one side.*/
- weight.x = 1.0;
- }
- color = vec4(0);
- if (weight.x > 0.0) {
- vec2 uv = texco.yz;
- if(signed_N.x < 0.0) {
- uv.x = 1.0 - uv.x;
- }
- color += weight.x * texture(ima, uv);
- }
- if (weight.y > 0.0) {
- vec2 uv = texco.xz;
- if(signed_N.y > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- color += weight.y * texture(ima, uv);
- }
- if (weight.z > 0.0) {
- vec2 uv = texco.yx;
- if(signed_N.z > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- color += weight.z * texture(ima, uv);
+ /* last case, we have a mix between three */
+ weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, 2.0 * limit - 1.0);
}
+ color = weight.x * color1 + weight.y * color2 + weight.z * color3;
alpha = color.a;
}
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 31ebc3e54de..5351b00d301 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -82,8 +82,9 @@ int imb_saveiris(struct ImBuf *ibuf, const char *name, int flags);
/* jp2 */
int imb_is_a_jp2(const unsigned char *buf);
-struct ImBuf *imb_jp2_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags);
+struct ImBuf *imb_load_jp2(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+struct ImBuf *imb_load_jp2_filepath(const char *name, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_save_jp2(struct ImBuf *ibuf, const char *name, int flags);
/* jpeg */
int imb_is_a_jpeg(const unsigned char *mem);
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 290226acf78..9ab2ee7dd21 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -243,21 +243,35 @@ void IMB_close_anim_proxies(struct anim *anim)
struct IDProperty *IMB_anim_load_metadata(struct anim *anim)
{
+ switch (anim->curtype) {
+ case ANIM_FFMPEG:
+ {
#ifdef WITH_FFMPEG
- AVDictionaryEntry *entry = NULL;
+ AVDictionaryEntry *entry = NULL;
- BLI_assert(anim->pFormatCtx != NULL);
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n");
+ BLI_assert(anim->pFormatCtx != NULL);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n");
- while (true) {
- entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX);
- if (entry == NULL) break;
+ while (true) {
+ entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX);
+ if (entry == NULL) break;
- /* Delay creation of the property group until there is actual metadata to put in there. */
- IMB_metadata_ensure(&anim->metadata);
- IMB_metadata_set_field(anim->metadata, entry->key, entry->value);
- }
+ /* Delay creation of the property group until there is actual metadata to put in there. */
+ IMB_metadata_ensure(&anim->metadata);
+ IMB_metadata_set_field(anim->metadata, entry->key, entry->value);
+ }
#endif
+ break;
+ }
+ case ANIM_SEQUENCE:
+ case ANIM_AVI:
+ case ANIM_MOVIE:
+ /* TODO */
+ break;
+ case ANIM_NONE:
+ default:
+ break;
+ }
return anim->metadata;
}
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 5dcd9c1c68a..25bbd132a49 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -77,7 +77,7 @@ const ImFileType IMB_FILE_TYPES[] = {
{imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENJPEG
- {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_JP2, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_load_jp2, NULL, imb_save_jp2, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_JP2, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_DDS
{NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, IMB_FTYPE_DDS, COLOR_ROLE_DEFAULT_BYTE},
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 753b5276222..cd6bdd643d5 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -38,7 +38,1251 @@
#include "openjpeg.h"
-// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */
+/* Temporary duplicated implementations for version 1.5 and 2.3, until we
+ * upgrade all platforms to 2.3. When removing the old code,
+ * imb_load_jp2_filepath can be added in filetype.c. */
+
+#if defined(OPJ_VERSION_MAJOR) && OPJ_VERSION_MAJOR >= 2
+
+#define JP2_FILEHEADER_SIZE 12
+
+static const char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
+static const char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
+
+/* We only need this because of how the presets are set */
+/* this typedef is copied from 'openjpeg-1.5.0/applications/codec/image_to_j2k.c' */
+typedef struct img_folder {
+ /** The directory path of the folder containing input images*/
+ char *imgdirpath;
+ /** Output format*/
+ char *out_format;
+ /** Enable option*/
+ char set_imgdir;
+ /** Enable Cod Format for output*/
+ char set_out_format;
+ /** User specified rate stored in case of cinema option*/
+ float *rates;
+} img_fol_t;
+
+enum {
+ DCP_CINEMA2K = 3,
+ DCP_CINEMA4K = 4,
+};
+
+static bool check_jp2(const unsigned char *mem) /* J2K_CFMT */
+{
+ return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1;
+}
+
+static bool check_j2k(const unsigned char *mem) /* J2K_CFMT */
+{
+ return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1;
+}
+
+static OPJ_CODEC_FORMAT format_from_header(const unsigned char mem[JP2_FILEHEADER_SIZE])
+{
+ if (check_jp2(mem)) {
+ return OPJ_CODEC_JP2;
+ }
+ else if (check_j2k(mem)) {
+ return OPJ_CODEC_J2K;
+ }
+ else {
+ return OPJ_CODEC_UNKNOWN;
+ }
+}
+
+int imb_is_a_jp2(const unsigned char *buf)
+{
+ return check_jp2(buf);
+}
+
+/**
+ * sample error callback expecting a FILE* client object
+ */
+static void error_callback(const char *msg, void *client_data)
+{
+ FILE *stream = (FILE *)client_data;
+ fprintf(stream, "[ERROR] %s", msg);
+}
+/**
+ * sample warning callback expecting a FILE* client object
+ */
+static void warning_callback(const char *msg, void *client_data)
+{
+ FILE *stream = (FILE *)client_data;
+ fprintf(stream, "[WARNING] %s", msg);
+}
+
+#ifdef DEBUG
+/**
+ * sample debug callback expecting no client object
+ */
+static void info_callback(const char *msg, void *client_data)
+{
+ FILE *stream = (FILE *)client_data;
+ fprintf(stream, "[INFO] %s", msg);
+}
+#endif
+
+# define PIXEL_LOOPER_BEGIN(_rect) \
+ for (y = h - 1; y != (unsigned int)(-1); y--) { \
+ for (i = y * w, i_next = (y + 1) * w; \
+ i < i_next; \
+ i++, _rect += 4) \
+ { \
+
+# define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \
+ for (y = h - 1; y != (unsigned int)(-1); y--) { \
+ for (i = y * w, i_next = (y + 1) * w; \
+ i < i_next; \
+ i++, _rect += _channels) \
+ { \
+
+# define PIXEL_LOOPER_END \
+ } \
+} (void)0 \
+
+
+/** \name Buffer Stream
+ * \{ */
+
+struct BufInfo {
+ const unsigned char *buf;
+ const unsigned char *cur;
+ off_t len;
+};
+
+static void opj_read_from_buffer_free(void *UNUSED(p_user_data))
+{
+ /* nop */
+}
+
+static OPJ_SIZE_T opj_read_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
+{
+ struct BufInfo *p_file = p_user_data;
+ OPJ_UINT32 l_nb_read;
+
+ if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len ) {
+ l_nb_read = p_nb_bytes;
+ }
+ else {
+ l_nb_read = (OPJ_UINT32)(p_file->buf + p_file->len - p_file->cur);
+ }
+ memcpy(p_buffer, p_file->cur, l_nb_read);
+ p_file->cur += l_nb_read;
+
+ return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1);
+}
+
+#if 0
+static OPJ_SIZE_T opj_write_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
+{
+ struct BufInfo *p_file = p_user_data;
+ memcpy(p_file->cur, p_buffer, p_nb_bytes);
+ p_file->cur += p_nb_bytes;
+ p_file->len += p_nb_bytes;
+ return p_nb_bytes;
+}
+#endif
+
+static OPJ_OFF_T opj_skip_from_buffer(OPJ_OFF_T p_nb_bytes, void *p_user_data)
+{
+ struct BufInfo *p_file = p_user_data;
+ if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len) {
+ p_file->cur += p_nb_bytes;
+ return p_nb_bytes;
+ }
+ p_file->cur = p_file->buf + p_file->len;
+ return (OPJ_OFF_T)-1;
+}
+
+static OPJ_BOOL opj_seek_from_buffer(OPJ_OFF_T p_nb_bytes, void *p_user_data)
+{
+ struct BufInfo *p_file = p_user_data;
+ if (p_nb_bytes < p_file->len) {
+ p_file->cur = p_file->buf + p_nb_bytes;
+ return OPJ_TRUE;
+ }
+ p_file->cur = p_file->buf + p_file->len;
+ return OPJ_FALSE;
+}
+
+/**
+ * Stream wrapper for memory buffer
+ * (would be nice if this was supported by the API).
+ */
+
+static opj_stream_t *opj_stream_create_from_buffer(
+ struct BufInfo *p_file, OPJ_UINT32 p_size,
+ OPJ_BOOL p_is_read_stream)
+{
+ opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream);
+ if (l_stream == NULL) {
+ return NULL;
+ }
+ opj_stream_set_user_data(l_stream, p_file, opj_read_from_buffer_free);
+ opj_stream_set_user_data_length(l_stream, p_file->len);
+ opj_stream_set_read_function(l_stream, opj_read_from_buffer);
+#if 0 /* UNUSED */
+ opj_stream_set_write_function(l_stream, opj_write_from_buffer);
+#endif
+ opj_stream_set_skip_function(l_stream, opj_skip_from_buffer);
+ opj_stream_set_seek_function(l_stream, opj_seek_from_buffer);
+
+ return l_stream;
+}
+
+/** \} */
+
+
+/** \name File Stream
+ * \{ */
+
+static void opj_free_from_file(void *p_user_data)
+{
+ FILE *f = p_user_data;
+ fclose(f);
+}
+
+static OPJ_UINT64 opj_get_data_length_from_file (void *p_user_data)
+{
+ FILE *p_file = p_user_data;
+ OPJ_OFF_T file_length = 0;
+
+ fseek(p_file, 0, SEEK_END);
+ file_length = ftell(p_file);
+ fseek(p_file, 0, SEEK_SET);
+
+ return (OPJ_UINT64)file_length;
+}
+
+static OPJ_SIZE_T opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
+{
+ FILE *p_file = p_user_data;
+ OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, p_file);
+ return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1;
+}
+
+static OPJ_SIZE_T opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
+{
+ FILE *p_file = p_user_data;
+ return fwrite(p_buffer, 1, p_nb_bytes, p_file);
+}
+
+static OPJ_OFF_T opj_skip_from_file(OPJ_OFF_T p_nb_bytes, void *p_user_data)
+{
+ FILE *p_file = p_user_data;
+ if (fseek(p_file, p_nb_bytes, SEEK_CUR)) {
+ return -1;
+ }
+ return p_nb_bytes;
+}
+
+static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, void *p_user_data)
+{
+ FILE *p_file = p_user_data;
+ if (fseek(p_file, p_nb_bytes, SEEK_SET)) {
+ return OPJ_FALSE;
+ }
+ return OPJ_TRUE;
+}
+
+/**
+ * Stream wrapper for memory file
+ * (would be nice if this was supported by the API).
+ */
+
+static opj_stream_t *opj_stream_create_from_file(
+ const char *filepath, OPJ_UINT32 p_size, OPJ_BOOL p_is_read_stream,
+ FILE **r_file)
+{
+ FILE *p_file = BLI_fopen(filepath, p_is_read_stream ? "rb" : "wb");
+ if (p_file == NULL) {
+ return NULL;
+ }
+
+ opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream);
+ if (l_stream == NULL) {
+ fclose(p_file);
+ return NULL;
+ }
+
+ opj_stream_set_user_data(l_stream, p_file, opj_free_from_file);
+ opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file));
+ opj_stream_set_write_function(l_stream, opj_write_from_file);
+ opj_stream_set_read_function(l_stream, opj_read_from_file);
+ opj_stream_set_skip_function(l_stream, opj_skip_from_file);
+ opj_stream_set_seek_function(l_stream, opj_seek_from_file);
+
+ if (r_file) {
+ *r_file = p_file;
+ }
+ return l_stream;
+}
+
+/** \} */
+
+static ImBuf *imb_load_jp2_stream(
+ opj_stream_t *stream, OPJ_CODEC_FORMAT p_format,
+ int flags, char colorspace[IM_MAX_SPACE]);
+
+ImBuf *imb_load_jp2(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+{
+ const OPJ_CODEC_FORMAT format = (size > JP2_FILEHEADER_SIZE) ? format_from_header(mem) : OPJ_CODEC_UNKNOWN;
+ struct BufInfo buf_wrapper = { .buf = mem, .cur = mem, .len = size, };
+ opj_stream_t *stream = opj_stream_create_from_buffer(&buf_wrapper, OPJ_J2K_STREAM_CHUNK_SIZE, true);
+ ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace);
+ opj_stream_destroy(stream);
+ return ibuf;
+}
+
+ImBuf *imb_load_jp2_filepath(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
+{
+ FILE *p_file = NULL;
+ unsigned char mem[JP2_FILEHEADER_SIZE];
+ opj_stream_t *stream = opj_stream_create_from_file(filepath, OPJ_J2K_STREAM_CHUNK_SIZE, true, &p_file);
+ if (stream) {
+ return NULL;
+ }
+ else {
+ if (fread(mem, sizeof(mem), 1, p_file) != sizeof(mem)) {
+ opj_stream_destroy(stream);
+ return NULL;
+ }
+ else {
+ fseek(p_file, 0, SEEK_SET);
+ }
+ }
+
+ const OPJ_CODEC_FORMAT format = format_from_header(mem);
+ ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace);
+ opj_stream_destroy(stream);
+ return ibuf;
+}
+
+
+static ImBuf *imb_load_jp2_stream(
+ opj_stream_t *stream, const OPJ_CODEC_FORMAT format,
+ int flags, char colorspace[IM_MAX_SPACE])
+{
+ if (format == OPJ_CODEC_UNKNOWN) {
+ return NULL;
+ }
+
+ struct ImBuf *ibuf = NULL;
+ bool use_float = false; /* for precision higher then 8 use float */
+ bool use_alpha = false;
+
+ long signed_offsets[4] = {0, 0, 0, 0};
+ int float_divs[4] = {1, 1, 1, 1};
+
+ unsigned int i, i_next, w, h, planes;
+ unsigned int y;
+ int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */
+
+ opj_dparameters_t parameters; /* decompression parameters */
+
+ opj_image_t *image = NULL;
+ opj_codec_t *codec = NULL; /* handle to a decompressor */
+
+ /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
+ /* set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* JPEG 2000 compressed image data */
+
+ /* get a decoder handle */
+ codec = opj_create_decompress(format);
+
+ /* configure the event callbacks (not required) */
+ opj_set_error_handler(codec, error_callback, stderr);
+ opj_set_warning_handler(codec, warning_callback, stderr);
+#ifdef DEBUG /* too noisy */
+ opj_set_info_handler(codec, info_callback, stderr);
+#endif
+
+ /* setup the decoder decoding parameters using the current image and user parameters */
+ if (opj_setup_decoder(codec, &parameters) == false) {
+ goto finally;
+ }
+
+ if (opj_read_header(stream, codec, &image) == false) {
+ printf("OpenJPEG error: failed to read the header\n");
+ goto finally;
+ }
+
+ /* decode the stream and fill the image structure */
+ if (opj_decode(codec, stream, image) == false) {
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
+ goto finally;
+ }
+
+ if ((image->numcomps * image->x1 * image->y1) == 0) {
+ fprintf(stderr, "\nError: invalid raw image parameters\n");
+ goto finally;
+ }
+
+ w = image->comps[0].w;
+ h = image->comps[0].h;
+
+ switch (image->numcomps) {
+ case 1: /* Grayscale */
+ case 3: /* Color */
+ planes = 24;
+ use_alpha = false;
+ break;
+ default: /* 2 or 4 - Grayscale or Color + alpha */
+ planes = 32; /* grayscale + alpha */
+ use_alpha = true;
+ break;
+ }
+
+
+ i = image->numcomps;
+ if (i > 4) i = 4;
+
+ while (i) {
+ i--;
+
+ if (image->comps[i].prec > 8)
+ use_float = true;
+
+ if (image->comps[i].sgnd)
+ signed_offsets[i] = 1 << (image->comps[i].prec - 1);
+
+ /* only needed for float images but dosnt hurt to calc this */
+ float_divs[i] = (1 << image->comps[i].prec) - 1;
+ }
+
+ ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect);
+
+ if (ibuf == NULL) {
+ goto finally;
+ }
+
+ ibuf->ftype = IMB_FTYPE_JP2;
+ if (1 /* is_jp2 */ ) {
+ ibuf->foptions.flag |= JP2_JP2;
+ }
+ else {
+ ibuf->foptions.flag |= JP2_J2K;
+ }
+
+ if (use_float) {
+ float *rect_float = ibuf->rect_float;
+
+ if (image->numcomps < 3) {
+ r = image->comps[0].data;
+ a = (use_alpha) ? image->comps[1].data : NULL;
+
+ /* grayscale 12bits+ */
+ if (use_alpha) {
+ a = image->comps[1].data;
+ PIXEL_LOOPER_BEGIN(rect_float) {
+ rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
+ rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1];
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_float) {
+ rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
+ rect_float[3] = 1.0f;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ else {
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+
+ /* rgb or rgba 12bits+ */
+ if (use_alpha) {
+ a = image->comps[3].data;
+ PIXEL_LOOPER_BEGIN(rect_float) {
+ rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
+ rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1];
+ rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2];
+ rect_float[3] = (float)(a[i] + signed_offsets[3]) / float_divs[3];
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_float) {
+ rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
+ rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1];
+ rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2];
+ rect_float[3] = 1.0f;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+
+ }
+ else {
+ unsigned char *rect_uchar = (unsigned char *)ibuf->rect;
+
+ if (image->numcomps < 3) {
+ r = image->comps[0].data;
+ a = (use_alpha) ? image->comps[1].data : NULL;
+
+ /* grayscale */
+ if (use_alpha) {
+ a = image->comps[3].data;
+ PIXEL_LOOPER_BEGIN(rect_uchar) {
+ rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]);
+ rect_uchar[3] = a[i] + signed_offsets[1];
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_uchar) {
+ rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]);
+ rect_uchar[3] = 255;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ else {
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+
+ /* 8bit rgb or rgba */
+ if (use_alpha) {
+ a = image->comps[3].data;
+ PIXEL_LOOPER_BEGIN(rect_uchar) {
+ rect_uchar[0] = r[i] + signed_offsets[0];
+ rect_uchar[1] = g[i] + signed_offsets[1];
+ rect_uchar[2] = b[i] + signed_offsets[2];
+ rect_uchar[3] = a[i] + signed_offsets[3];
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_uchar) {
+ rect_uchar[0] = r[i] + signed_offsets[0];
+ rect_uchar[1] = g[i] + signed_offsets[1];
+ rect_uchar[2] = b[i] + signed_offsets[2];
+ rect_uchar[3] = 255;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ }
+
+ if (flags & IB_rect) {
+ IMB_rect_from_float(ibuf);
+ }
+
+finally:
+
+ /* free remaining structures */
+ if (codec) {
+ opj_destroy_codec(codec);
+ }
+
+ if (image) {
+ opj_image_destroy(image);
+ }
+
+ return ibuf;
+}
+
+//static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp)
+/* prec can be 8, 12, 16 */
+
+/* use inline because the float passed can be a function call that would end up being called many times */
+#if 0
+#define UPSAMPLE_8_TO_12(_val) ((_val << 4) | (_val & ((1 << 4) - 1)))
+#define UPSAMPLE_8_TO_16(_val) ((_val << 8) + _val)
+
+#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val)))
+#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val)))
+#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val)))
+#else
+
+BLI_INLINE int UPSAMPLE_8_TO_12(const unsigned char _val)
+{
+ return (_val << 4) | (_val & ((1 << 4) - 1));
+}
+BLI_INLINE int UPSAMPLE_8_TO_16(const unsigned char _val)
+{
+ return (_val << 8) + _val;
+}
+
+BLI_INLINE int DOWNSAMPLE_FLOAT_TO_8BIT(const float _val)
+{
+ return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val)));
+}
+BLI_INLINE int DOWNSAMPLE_FLOAT_TO_12BIT(const float _val)
+{
+ return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val)));
+}
+BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val)
+{
+ return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val)));
+}
+#endif
+
+/*
+ * 2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3x12 bits per pixel, XYZ color space
+ *
+ * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the image is used
+ * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the image is used
+ */
+
+/* ****************************** COPIED FROM image_to_j2k.c */
+
+/* ----------------------------------------------------------------------- */
+#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
+#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
+#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/
+#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/
+
+
+static int initialise_4K_poc(opj_poc_t *POC, int numres)
+{
+ POC[0].tile = 1;
+ POC[0].resno0 = 0;
+ POC[0].compno0 = 0;
+ POC[0].layno1 = 1;
+ POC[0].resno1 = numres - 1;
+ POC[0].compno1 = 3;
+ POC[0].prg1 = OPJ_CPRL;
+ POC[1].tile = 1;
+ POC[1].resno0 = numres - 1;
+ POC[1].compno0 = 0;
+ POC[1].layno1 = 1;
+ POC[1].resno1 = numres;
+ POC[1].compno1 = 3;
+ POC[1].prg1 = OPJ_CPRL;
+ return 2;
+}
+
+static void cinema_parameters(opj_cparameters_t *parameters)
+{
+ parameters->tile_size_on = 0; /* false */
+ parameters->cp_tdx = 1;
+ parameters->cp_tdy = 1;
+
+ /*Tile part*/
+ parameters->tp_flag = 'C';
+ parameters->tp_on = 1;
+
+ /*Tile and Image shall be at (0, 0)*/
+ parameters->cp_tx0 = 0;
+ parameters->cp_ty0 = 0;
+ parameters->image_offset_x0 = 0;
+ parameters->image_offset_y0 = 0;
+
+ /*Codeblock size = 32 * 32*/
+ parameters->cblockw_init = 32;
+ parameters->cblockh_init = 32;
+ parameters->csty |= 0x01;
+
+ /*The progression order shall be CPRL*/
+ parameters->prog_order = OPJ_CPRL;
+
+ /* No ROI */
+ parameters->roi_compno = -1;
+
+ parameters->subsampling_dx = 1; parameters->subsampling_dy = 1;
+
+ /* 9-7 transform */
+ parameters->irreversible = 1;
+}
+
+static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *image, img_fol_t *img_fol)
+{
+ int i;
+ float temp_rate;
+
+ switch (parameters->cp_cinema) {
+ case OPJ_CINEMA2K_24:
+ case OPJ_CINEMA2K_48:
+ if (parameters->numresolution > 6) {
+ parameters->numresolution = 6;
+ }
+ if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))) {
+ fprintf(stdout, "Image coordinates %u x %u is not 2K compliant.\nJPEG Digital Cinema Profile-3 "
+ "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n",
+ image->comps[0].w, image->comps[0].h);
+ parameters->cp_rsiz = OPJ_STD_RSIZ;
+ }
+ else {
+ parameters->cp_rsiz = DCP_CINEMA2K;
+ }
+ break;
+
+ case OPJ_CINEMA4K_24:
+ if (parameters->numresolution < 1) {
+ parameters->numresolution = 1;
+ }
+ else if (parameters->numresolution > 7) {
+ parameters->numresolution = 7;
+ }
+ if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))) {
+ fprintf(stdout, "Image coordinates %u x %u is not 4K compliant.\nJPEG Digital Cinema Profile-4"
+ "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n",
+ image->comps[0].w, image->comps[0].h);
+ parameters->cp_rsiz = OPJ_STD_RSIZ;
+ }
+ else {
+ parameters->cp_rsiz = DCP_CINEMA2K;
+ }
+ parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution);
+ break;
+ case OPJ_OFF:
+ /* do nothing */
+ break;
+ }
+
+ switch (parameters->cp_cinema) {
+ case OPJ_CINEMA2K_24:
+ case OPJ_CINEMA4K_24:
+ for (i = 0; i < parameters->tcp_numlayers; i++) {
+ temp_rate = 0;
+ if (img_fol->rates[i] == 0) {
+ parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ else {
+ temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
+ if (temp_rate > CINEMA_24_CS) {
+ parameters->tcp_rates[i] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ else {
+ parameters->tcp_rates[i] = img_fol->rates[i];
+ }
+ }
+ }
+ parameters->max_comp_size = COMP_24_CS;
+ break;
+
+ case OPJ_CINEMA2K_48:
+ for (i = 0; i < parameters->tcp_numlayers; i++) {
+ temp_rate = 0;
+ if (img_fol->rates[i] == 0) {
+ parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ else {
+ temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
+ if (temp_rate > CINEMA_48_CS) {
+ parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
+ (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ else {
+ parameters->tcp_rates[i] = img_fol->rates[i];
+ }
+ }
+ }
+ parameters->max_comp_size = COMP_48_CS;
+ break;
+ case OPJ_OFF:
+ /* do nothing */
+ break;
+ }
+ parameters->cp_disto_alloc = 1;
+}
+
+static float channel_colormanage_noop(float value)
+{
+ return value;
+}
+
+static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
+{
+ unsigned char *rect_uchar;
+ float *rect_float, from_straight[4];
+
+ unsigned int subsampling_dx = parameters->subsampling_dx;
+ unsigned int subsampling_dy = parameters->subsampling_dy;
+
+ unsigned int i, i_next, numcomps, w, h, prec;
+ unsigned int y;
+ int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */
+ OPJ_COLOR_SPACE color_space;
+ opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */
+ opj_image_t *image = NULL;
+
+ float (*chanel_colormanage_cb)(float);
+
+ img_fol_t img_fol; /* only needed for cinema presets */
+ memset(&img_fol, 0, sizeof(img_fol_t));
+
+ if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
+ /* float buffer was managed already, no need in color space conversion */
+ chanel_colormanage_cb = channel_colormanage_noop;
+ }
+ else {
+ /* standard linear-to-srgb conversion if float buffer wasn't managed */
+ chanel_colormanage_cb = linearrgb_to_srgb;
+ }
+
+ if (ibuf->foptions.flag & JP2_CINE) {
+
+ if (ibuf->x == 4096 || ibuf->y == 2160)
+ parameters->cp_cinema = OPJ_CINEMA4K_24;
+ else {
+ if (ibuf->foptions.flag & JP2_CINE_48FPS) {
+ parameters->cp_cinema = OPJ_CINEMA2K_48;
+ }
+ else {
+ parameters->cp_cinema = OPJ_CINEMA2K_24;
+ }
+ }
+ if (parameters->cp_cinema) {
+ img_fol.rates = (float *)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates");
+ for (i = 0; i < parameters->tcp_numlayers; i++) {
+ img_fol.rates[i] = parameters->tcp_rates[i];
+ }
+ cinema_parameters(parameters);
+ }
+
+ color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB;
+ prec = 12;
+ numcomps = 3;
+ }
+ else {
+ /* Get settings from the imbuf */
+ color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB;
+
+ if (ibuf->foptions.flag & JP2_16BIT) prec = 16;
+ else if (ibuf->foptions.flag & JP2_12BIT) prec = 12;
+ else prec = 8;
+
+ /* 32bit images == alpha channel */
+ /* grayscale not supported yet */
+ numcomps = (ibuf->planes == 32) ? 4 : 3;
+ }
+
+ w = ibuf->x;
+ h = ibuf->y;
+
+
+ /* initialize image components */
+ memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t));
+ for (i = 0; i < numcomps; i++) {
+ cmptparm[i].prec = prec;
+ cmptparm[i].bpp = prec;
+ cmptparm[i].sgnd = 0;
+ cmptparm[i].dx = subsampling_dx;
+ cmptparm[i].dy = subsampling_dy;
+ cmptparm[i].w = w;
+ cmptparm[i].h = h;
+ }
+ /* create the image */
+ image = opj_image_create(numcomps, &cmptparm[0], color_space);
+ if (!image) {
+ printf("Error: opj_image_create() failed\n");
+ return NULL;
+ }
+
+ /* set image offset and reference grid */
+ image->x0 = parameters->image_offset_x0;
+ image->y0 = parameters->image_offset_y0;
+ image->x1 = image->x0 + (w - 1) * subsampling_dx + 1 + image->x0;
+ image->y1 = image->y0 + (h - 1) * subsampling_dy + 1 + image->y0;
+
+ /* set image data */
+ rect_uchar = (unsigned char *) ibuf->rect;
+ rect_float = ibuf->rect_float;
+
+ /* set the destination channels */
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+ a = (numcomps == 4) ? image->comps[3].data : NULL;
+
+ if (rect_float && rect_uchar && prec == 8) {
+ /* No need to use the floating point buffer, just write the 8 bits from the char buffer */
+ rect_float = NULL;
+ }
+
+ if (rect_float) {
+ int channels_in_float = ibuf->channels ? ibuf->channels : 4;
+
+ switch (prec) {
+ case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */
+ if (numcomps == 4) {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 255;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 255;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ else {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ break;
+
+ case 12:
+ if (numcomps == 4) {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 4095;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 4095;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ else {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ break;
+
+ case 16:
+ if (numcomps == 4) {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 65535;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 65535;
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ else {
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
+ }
+ }
+ break;
+ }
+ }
+ else {
+ /* just use rect*/
+ switch (prec) {
+ case 8:
+ if (numcomps == 4) {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = rect_uchar[0];
+ g[i] = rect_uchar[1];
+ b[i] = rect_uchar[2];
+ a[i] = rect_uchar[3];
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = rect_uchar[0];
+ g[i] = rect_uchar[1];
+ b[i] = rect_uchar[2];
+ }
+ PIXEL_LOOPER_END;
+ }
+ break;
+
+ case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */
+ if (numcomps == 4) {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]);
+ g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]);
+ b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]);
+ a[i] = UPSAMPLE_8_TO_12(rect_uchar[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]);
+ g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]);
+ b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ break;
+
+ case 16:
+ if (numcomps == 4) {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]);
+ g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]);
+ b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]);
+ a[i] = UPSAMPLE_8_TO_16(rect_uchar[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN(rect_uchar)
+ {
+ r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]);
+ g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]);
+ b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ break;
+ }
+ }
+
+ /* Decide if MCT should be used */
+ parameters->tcp_mct = image->numcomps == 3 ? 1 : 0;
+
+ if (parameters->cp_cinema) {
+ cinema_setup_encoder(parameters, image, &img_fol);
+ }
+
+ if (img_fol.rates)
+ MEM_freeN(img_fol.rates);
+
+ return image;
+}
+
+int imb_save_jp2_stream(struct ImBuf *ibuf, opj_stream_t *stream, int flags);
+
+int imb_save_jp2(struct ImBuf *ibuf, const char *filepath, int flags)
+{
+ opj_stream_t *stream = opj_stream_create_from_file(filepath, OPJ_J2K_STREAM_CHUNK_SIZE, false, NULL);
+ if (stream == NULL) {
+ return 0;
+ }
+ int ret = imb_save_jp2_stream(ibuf, stream, flags);
+ opj_stream_destroy(stream);
+ return ret;
+}
+
+/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
+int imb_save_jp2_stream(struct ImBuf *ibuf, opj_stream_t *stream, int UNUSED(flags))
+{
+ int quality = ibuf->foptions.quality;
+
+ opj_cparameters_t parameters; /* compression parameters */
+ opj_image_t *image = NULL;
+
+ /* set encoding parameters to default values */
+ opj_set_default_encoder_parameters(&parameters);
+
+ /* compression ratio */
+ /* invert range, from 10-100, 100-1
+ * where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/
+ parameters.tcp_rates[0] = ((100 - quality) / 90.0f * 99.0f) + 1;
+
+
+ parameters.tcp_numlayers = 1; /* only one resolution */
+ parameters.cp_disto_alloc = 1;
+
+ image = ibuftoimage(ibuf, &parameters);
+
+ opj_codec_t *codec = NULL;
+ int ok = false;
+ /* JP2 format output */
+ {
+ /* get a JP2 compressor handle */
+ OPJ_CODEC_FORMAT format = OPJ_CODEC_JP2;
+ if (ibuf->foptions.flag & JP2_J2K) {
+ format = OPJ_CODEC_J2K;
+ }
+ else if (ibuf->foptions.flag & JP2_JP2) {
+ format = OPJ_CODEC_JP2;
+ }
+
+ codec = opj_create_compress(format);
+
+ /* configure the event callbacks (not required) */
+ opj_set_error_handler(codec, error_callback, stderr);
+ opj_set_warning_handler(codec, warning_callback, stderr);
+#ifdef DEBUG /* too noisy */
+ opj_set_info_handler(codec, info_callback, stderr);
+#endif
+
+ /* setup the encoder parameters using the current image and using user parameters */
+ if (opj_setup_encoder(codec, &parameters, image) == false) {
+ goto finally;
+ }
+
+ if (opj_start_compress(codec, image, stream) == false) {
+ goto finally;
+ }
+ if (opj_encode(codec, stream) == false) {
+ goto finally;
+ }
+ if (opj_end_compress(codec, stream) == false) {
+ goto finally;
+ }
+ }
+
+ ok = true;
+
+finally:
+ /* free remaining compression structures */
+ if (codec) {
+ opj_destroy_codec(codec);
+ }
+
+ /* free image data */
+ if (image) {
+ opj_image_destroy(image);
+ }
+
+ if (ok == false) {
+ fprintf(stderr, "failed to encode image\n");
+ }
+
+ return ok;
+}
+
+#else /* defined(OPJ_VERSION_MAJOR) && OPJ_VERSION_MAJOR >= 2 */
static const char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
static const char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
@@ -94,6 +1338,7 @@ static void warning_callback(const char *msg, void *client_data)
FILE *stream = (FILE *)client_data;
fprintf(stream, "[WARNING] %s", msg);
}
+
/**
* sample debug callback expecting no client object
*/
@@ -121,7 +1366,7 @@ static void info_callback(const char *msg, void *client_data)
} \
} (void)0 \
-struct ImBuf *imb_jp2_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+struct ImBuf *imb_load_jp2(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
bool use_float = false; /* for precision higher then 8 use float */
@@ -960,7 +2205,7 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
-int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
+int imb_save_jp2(struct ImBuf *ibuf, const char *name, int flags)
{
int quality = ibuf->foptions.quality;
@@ -1051,3 +2296,5 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
return 1;
}
+
+#endif /* defined(OPJ_VERSION_MAJOR) && OPJ_VERSION_MAJOR >= 2 */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index ec71f28cb23..634819b33ce 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -564,6 +564,7 @@ enum {
INDEX_ID_IP,
INDEX_ID_AC,
INDEX_ID_KE,
+ INDEX_ID_PAL,
INDEX_ID_GD,
INDEX_ID_NT,
INDEX_ID_IM,
@@ -581,7 +582,6 @@ enum {
INDEX_ID_TXT,
INDEX_ID_SO,
INDEX_ID_GR,
- INDEX_ID_PAL,
INDEX_ID_PC,
INDEX_ID_BR,
INDEX_ID_PA,
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 0546dcb1a6c..55e1a43925d 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -82,9 +82,9 @@ typedef struct bMotionPath {
int flag; /* baking settings - eMotionPath_Flag */
/* Used for drawing. */
- struct Gwn_VertBuf *points_vbo;
- struct Gwn_Batch *batch_line;
- struct Gwn_Batch *batch_points;
+ struct GPUVertBuf *points_vbo;
+ struct GPUBatch *batch_line;
+ struct GPUBatch *batch_points;
void *pad;
} bMotionPath;
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index fc3b4afe18d..dcb7fbd344b 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -44,6 +44,7 @@
struct CurveMapping;
struct MTex;
struct Image;
+struct Material;
typedef struct BrushClone {
struct Image *image; /* image for clone tool */
@@ -51,6 +52,109 @@ typedef struct BrushClone {
float alpha, pad; /* transparency for drawing of clone image */
} BrushClone;
+
+typedef struct BrushGpencilSettings {
+ float draw_smoothfac; /* amount of smoothing to apply to newly created strokes */
+ float draw_sensitivity; /* amount of sensivity to apply to newly created strokes */
+ float draw_strength; /* amount of alpha strength to apply to newly created strokes */
+ float draw_jitter; /* amount of jitter to apply to newly created strokes */
+ float draw_angle; /* angle when the brush has full thickness */
+ float draw_angle_factor; /* factor to apply when angle change (only 90 degrees) */
+ float draw_random_press; /* factor of randomness for pressure */
+ float draw_random_strength; /* factor of strength for strength */
+ float draw_random_sub; /* factor of randomness for subdivision */
+ short draw_smoothlvl; /* number of times to apply smooth factor to new strokes */
+ short draw_subdivide; /* number of times to subdivide new strokes */
+ short flag; /* internal grease pencil drawing flags */
+
+ short thick_smoothlvl; /* number of times to apply thickness smooth factor to new strokes */
+ float thick_smoothfac; /* amount of thickness smoothing to apply to newly created strokes */
+
+ float fill_threshold; /* factor for transparency */
+ short fill_leak; /* number of pixel to consider the leak is too small (x 2) */
+ char pad_1[6];
+
+ int fill_simplylvl; /* number of simplify steps */
+ int fill_draw_mode; /* type of control lines drawing mode */
+ int icon_id; /* icon identifier */
+
+ int input_samples; /* maximum distance before generate new point for very fast mouse movements */
+ float uv_random; /* random factor for UV rotation */
+
+ int brush_type; /* type of brush (draw, fill, erase, etc..) */
+ int eraser_mode; /* soft, hard or stroke */
+ float active_smooth; /* smooth while drawing factor */
+ char pad_2[4];
+
+ struct CurveMapping *curve_sensitivity;
+ struct CurveMapping *curve_strength;
+ struct CurveMapping *curve_jitter;
+
+ /* optional link of material to replace default in context */
+ struct Material *material; /* material */
+} BrushGpencilSettings;
+
+/* BrushGpencilSettings->gp_flag */
+typedef enum eGPDbrush_Flag {
+ /* brush use pressure */
+ GP_BRUSH_USE_PRESSURE = (1 << 0),
+ /* brush use pressure for alpha factor */
+ GP_BRUSH_USE_STENGTH_PRESSURE = (1 << 1),
+ /* brush use pressure for alpha factor */
+ GP_BRUSH_USE_JITTER_PRESSURE = (1 << 2),
+ /* enable screen cursor */
+ GP_BRUSH_ENABLE_CURSOR = (1 << 5),
+ /* fill hide transparent */
+ GP_BRUSH_FILL_HIDE = (1 << 6),
+ /* show fill help lines */
+ GP_BRUSH_FILL_SHOW_HELPLINES = (1 << 7),
+ /* lazy mouse */
+ GP_BRUSH_STABILIZE_MOUSE = (1 << 8),
+ /* lazy mouse override (internal only) */
+ GP_BRUSH_STABILIZE_MOUSE_TEMP = (1 << 9),
+ /* default eraser brush for quick switch */
+ GP_BRUSH_DEFAULT_ERASER = (1 << 10),
+ /* settings group */
+ GP_BRUSH_GROUP_SETTINGS = (1 << 11),
+ /* Random settings group */
+ GP_BRUSH_GROUP_RANDOM = (1 << 12)
+} eGPDbrush_Flag;
+
+/* BrushGpencilSettings->gp_fill_draw_mode */
+typedef enum eGP_FillDrawModes {
+ GP_FILL_DMODE_BOTH = 0,
+ GP_FILL_DMODE_STROKE = 1,
+ GP_FILL_DMODE_CONTROL = 2,
+} eGP_FillDrawModes;
+
+/* BrushGpencilSettings->brush type */
+typedef enum eGP_BrushType {
+ GP_BRUSH_TYPE_DRAW = 0,
+ GP_BRUSH_TYPE_FILL = 1,
+ GP_BRUSH_TYPE_ERASE = 2,
+} eGP_BrushType;
+
+/* BrushGpencilSettings->gp_eraser_mode */
+typedef enum eGP_BrushEraserMode {
+ GP_BRUSH_ERASER_SOFT = 0,
+ GP_BRUSH_ERASER_HARD = 1,
+ GP_BRUSH_ERASER_STROKE = 2,
+} eGP_BrushEraserMode;
+
+/* BrushGpencilSettings default brush icons */
+typedef enum eGP_BrushIcons {
+ GP_BRUSH_ICON_PENCIL = 1,
+ GP_BRUSH_ICON_PEN = 2,
+ GP_BRUSH_ICON_INK = 3,
+ GP_BRUSH_ICON_INKNOISE = 4,
+ GP_BRUSH_ICON_BLOCK = 5,
+ GP_BRUSH_ICON_MARKER = 6,
+ GP_BRUSH_ICON_FILL = 7,
+ GP_BRUSH_ICON_ERASE_SOFT = 8,
+ GP_BRUSH_ICON_ERASE_HARD = 9,
+ GP_BRUSH_ICON_ERASE_STROKE = 10
+} eGP_BrushIcons;
+
typedef struct Brush {
ID id;
@@ -139,8 +243,10 @@ typedef struct Brush {
float mask_stencil_pos[2];
float mask_stencil_dimension[2];
-} Brush;
+ struct BrushGpencilSettings *gpencil_settings;
+
+} Brush;
typedef struct PaletteColor {
struct PaletteColor *next, *prev;
/* two values, one to store rgb, other to store values for sculpt/weight */
@@ -355,5 +461,6 @@ enum {
};
#define MAX_BRUSH_PIXEL_RADIUS 500
+#define GP_MAX_BRUSH_PIXEL_RADIUS 1000
#endif /* __DNA_BRUSH_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h
index 8ed38b0b05d..4f860e16b88 100644
--- a/source/blender/makesdna/DNA_color_types.h
+++ b/source/blender/makesdna/DNA_color_types.h
@@ -99,6 +99,7 @@ typedef enum eCurveMappingPreset {
CURVE_PRESET_MID9 = 4,
CURVE_PRESET_ROUND = 5,
CURVE_PRESET_ROOT = 6,
+ CURVE_PRESET_GAUSS = 7,
} eCurveMappingPreset;
/* histogram->mode */
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
new file mode 100644
index 00000000000..ae3621576f2
--- /dev/null
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -0,0 +1,415 @@
+/*
+ * ***** 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 DNA_gpencil_modifier_types.h
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_GPENCIL_MODIFIER_TYPES_H__
+#define __DNA_GPENCIL_MODIFIER_TYPES_H__
+
+#include "DNA_defs.h"
+#include "DNA_listBase.h"
+
+/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE!
+ * (ONLY ADD NEW ITEMS AT THE END)
+ */
+
+struct RNG;
+
+typedef enum GpencilModifierType {
+ eGpencilModifierType_None = 0,
+ eGpencilModifierType_Noise = 1,
+ eGpencilModifierType_Subdiv = 2,
+ eGpencilModifierType_Thick = 3,
+ eGpencilModifierType_Tint = 4,
+ eGpencilModifierType_Instance = 5,
+ eGpencilModifierType_Build = 6,
+ eGpencilModifierType_Opacity = 7,
+ eGpencilModifierType_Color = 8,
+ eGpencilModifierType_Lattice = 9,
+ eGpencilModifierType_Simplify = 10,
+ eGpencilModifierType_Smooth = 11,
+ eGpencilModifierType_Hook = 12,
+ eGpencilModifierType_Offset = 13,
+ eGpencilModifierType_Mirror = 14,
+ NUM_GREASEPENCIL_MODIFIER_TYPES
+} GpencilModifierType;
+
+typedef enum GpencilModifierMode {
+ eGpencilModifierMode_Realtime = (1 << 0),
+ eGpencilModifierMode_Render = (1 << 1),
+ eGpencilModifierMode_Editmode = (1 << 2),
+ eGpencilModifierMode_Expanded = (1 << 3),
+} GpencilModifierMode;
+
+typedef enum {
+ /* This modifier has been inserted in local override, and hence can be fully edited. */
+ eGpencilModifierFlag_StaticOverride_Local = (1 << 0),
+} GpencilModifierFlag;
+
+typedef struct GpencilModifierData {
+ struct GpencilModifierData *next, *prev;
+
+ int type, mode;
+ int stackindex;
+ short flag;
+ short pad;
+ char name[64]; /* MAX_NAME */
+
+ char *error;
+} GpencilModifierData;
+
+typedef struct NoiseGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* several flags */
+ float factor; /* factor of noise */
+ int step; /* how many frames before recalculate randoms */
+ int gp_frame; /* last gp frame used */
+ int scene_frame; /* last scene frame used */
+ float vrand1, vrand2; /* random values */
+ struct RNG *rng;
+} NoiseGpencilModifierData;
+
+typedef enum eNoiseGpencil_Flag {
+ GP_NOISE_USE_RANDOM = (1 << 0),
+ GP_NOISE_MOD_LOCATION = (1 << 1),
+ GP_NOISE_MOD_STRENGTH = (1 << 2),
+ GP_NOISE_MOD_THICKNESS = (1 << 3),
+ GP_NOISE_FULL_STROKE = (1 << 4),
+ GP_NOISE_MOVE_EXTREME = (1 << 5),
+ GP_NOISE_INVERT_LAYER = (1 << 6),
+ GP_NOISE_INVERT_PASS = (1 << 7),
+ GP_NOISE_INVERT_VGROUP = (1 << 8),
+ GP_NOISE_MOD_UV = (1 << 9),
+} eNoiseGpencil_Flag;
+
+typedef struct SubdivGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ int level; /* factor of subdivision */
+ char pad[4];
+} SubdivGpencilModifierData;
+
+typedef enum eSubdivGpencil_Flag {
+ GP_SUBDIV_SIMPLE = (1 << 0),
+ GP_SUBDIV_INVERT_LAYER = (1 << 1),
+ GP_SUBDIV_INVERT_PASS = (1 << 2),
+} eSubdivGpencil_Flag;
+
+typedef struct ThickGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ int thickness; /* Thickness change */
+ char pad[4];
+ struct CurveMapping *curve_thickness;
+} ThickGpencilModifierData;
+
+typedef enum eThickGpencil_Flag {
+ GP_THICK_INVERT_LAYER = (1 << 0),
+ GP_THICK_INVERT_PASS = (1 << 1),
+ GP_THICK_INVERT_VGROUP = (1 << 2),
+ GP_THICK_CUSTOM_CURVE = (1 << 3),
+ GP_THICK_NORMALIZE = (1 << 4),
+} eThickGpencil_Flag;
+
+typedef enum eModifyColorGpencil_Flag {
+ GP_MODIFY_COLOR_BOTH = 0,
+ GP_MODIFY_COLOR_STROKE = 1,
+ GP_MODIFY_COLOR_FILL = 2
+} eModifyColorGpencil_Flag;
+
+typedef struct TintGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float rgb[3]; /* Tint color */
+ float factor; /* Mix factor */
+ char modify_color; /* modify stroke, fill or both */
+ char pad[7];
+} TintGpencilModifierData;
+
+typedef enum eTintGpencil_Flag {
+ GP_TINT_CREATE_COLORS = (1 << 0),
+ GP_TINT_INVERT_LAYER = (1 << 1),
+ GP_TINT_INVERT_PASS = (1 << 2),
+} eTintGpencil_Flag;
+
+typedef struct ColorGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float hsv[3]; /* hsv factors */
+ char modify_color; /* modify stroke, fill or both */
+ char pad[3];
+} ColorGpencilModifierData;
+
+typedef enum eColorGpencil_Flag {
+ GP_COLOR_CREATE_COLORS = (1 << 0),
+ GP_COLOR_INVERT_LAYER = (1 << 1),
+ GP_COLOR_INVERT_PASS = (1 << 2),
+} eColorGpencil_Flag;
+
+typedef struct OpacityGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float factor; /* Main Opacity factor */
+ char modify_color; /* modify stroke, fill or both */
+ char pad[3];
+} OpacityGpencilModifierData;
+
+typedef enum eOpacityGpencil_Flag {
+ GP_OPACITY_INVERT_LAYER = (1 << 0),
+ GP_OPACITY_INVERT_PASS = (1 << 1),
+ GP_OPACITY_INVERT_VGROUP = (1 << 2),
+ GP_OPACITY_CREATE_COLORS = (1 << 3),
+} eOpacityGpencil_Flag;
+
+typedef struct InstanceGpencilModifierData {
+ GpencilModifierData modifier;
+ int count[3]; /* number of elements in array */
+ int flag; /* several flags */
+ float offset[3]; /* Location increments */
+ float shift[3]; /* shift increment */
+ float rnd_size; /* random size factor */
+ float rnd_rot; /* random size factor */
+ float rot[3]; /* Rotation changes */
+ float scale[3]; /* Scale changes */
+ float rnd[20]; /* (first element is the index) random values */
+ int lock_axis; /* lock shift to one axis */
+
+ int pass_index; /* custom index for passes */
+ char layername[64]; /* layer name */
+} InstanceGpencilModifierData;
+
+typedef enum eInstanceGpencil_Flag {
+ GP_INSTANCE_RANDOM_SIZE = (1 << 0),
+ GP_INSTANCE_RANDOM_ROT = (1 << 1),
+ GP_INSTANCE_INVERT_LAYER = (1 << 2),
+ GP_INSTANCE_INVERT_PASS = (1 << 3),
+ GP_INSTANCE_MAKE_OBJECTS = (1 << 4),
+} eInstanceGpencil_Flag;
+
+typedef struct BuildGpencilModifierData {
+ GpencilModifierData modifier;
+
+ char layername[64]; /* if set, restrict modifier to operating on this layer */
+ int pass_index;
+
+ int pad;
+
+ float start_frame; /* If GP_BUILD_RESTRICT_TIME is set, the defines the frame range where GP frames are considered */
+ float end_frame;
+
+ float start_delay; /* For each pair of gp keys, number of frames before strokes start appearing */
+ float length; /* For each pair of gp keys, number of frames that build effect must be completed within */
+
+ short flag; /* (eGpencilBuild_Flag) Options for controlling modifier behaviour */
+
+ short mode; /* (eGpencilBuild_Mode) How are strokes ordered */
+ short transition; /* (eGpencilBuild_Transition) In what order do stroke points appear/disappear */
+
+ short time_alignment; /* (eGpencilBuild_TimeAlignment) For the "Concurrent" mode, when should "shorter" strips start/end */
+} BuildGpencilModifierData;
+
+typedef enum eBuildGpencil_Mode {
+ /* Strokes are shown one by one until all have appeared */
+ GP_BUILD_MODE_SEQUENTIAL = 0,
+ /* All strokes start at the same time */
+ GP_BUILD_MODE_CONCURRENT = 1,
+} eBuildGpencil_Mode;
+
+typedef enum eBuildGpencil_Transition {
+ /* Show in forward order */
+ GP_BUILD_TRANSITION_GROW = 0,
+ /* Hide in reverse order */
+ GP_BUILD_TRANSITION_SHRINK = 1,
+ /* Hide in forward order */
+ GP_BUILD_TRANSITION_FADE = 2,
+} eBuildGpencil_Transition;
+
+typedef enum eBuildGpencil_TimeAlignment {
+ /* All strokes start at same time */
+ GP_BUILD_TIMEALIGN_START = 0,
+ /* All strokes end at same time */
+ GP_BUILD_TIMEALIGN_END = 1,
+
+ /* TODO: Random Offsets, Stretch-to-Fill */
+} eBuildGpencil_TimeAlignment;
+
+typedef enum eBuildGpencil_Flag {
+ /* Restrict modifier to particular layer/passes? */
+ GP_BUILD_INVERT_LAYER = (1 << 0),
+ GP_BUILD_INVERT_PASS = (1 << 1),
+
+ /* Restrict modifier to only operating between the nominated frames */
+ GP_BUILD_RESTRICT_TIME = (1 << 2),
+} eBuildGpencil_Flag;
+
+typedef struct LatticeGpencilModifierData {
+ GpencilModifierData modifier;
+ struct Object *object;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float strength;
+ char pad[4];
+ void *cache_data; /* runtime only (LatticeDeformData) */
+} LatticeGpencilModifierData;
+
+typedef enum eLatticeGpencil_Flag {
+ GP_LATTICE_INVERT_LAYER = (1 << 0),
+ GP_LATTICE_INVERT_PASS = (1 << 1),
+ GP_LATTICE_INVERT_VGROUP = (1 << 2),
+} eLatticeGpencil_Flag;
+
+typedef struct MirrorGpencilModifierData {
+ GpencilModifierData modifier;
+ struct Object *object;
+ char layername[64]; /* layer name */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+} MirrorGpencilModifierData;
+
+typedef enum eMirrorGpencil_Flag {
+ GP_MIRROR_INVERT_LAYER = (1 << 0),
+ GP_MIRROR_INVERT_PASS = (1 << 1),
+ GP_MIRROR_CLIPPING = (1 << 2),
+ GP_MIRROR_AXIS_X = (1 << 3),
+ GP_MIRROR_AXIS_Y = (1 << 4),
+ GP_MIRROR_AXIS_Z = (1 << 5),
+} eMirrorGpencil_Flag;
+
+typedef struct HookGpencilModifierData {
+ GpencilModifierData modifier;
+
+ struct Object *object;
+ char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+
+ int flag;
+ char falloff_type; /* use enums from WarpGpencilModifier (exact same functionality) */
+ char pad[3];
+ float parentinv[4][4]; /* matrix making current transform unmodified */
+ float cent[3]; /* visualization of hook */
+ float falloff; /* if not zero, falloff is distance where influence zero */
+ float force;
+ struct CurveMapping *curfalloff;
+} HookGpencilModifierData;
+
+typedef enum eHookGpencil_Flag {
+ GP_HOOK_INVERT_LAYER = (1 << 0),
+ GP_HOOK_INVERT_PASS = (1 << 1),
+ GP_HOOK_INVERT_VGROUP = (1 << 2),
+ GP_HOOK_UNIFORM_SPACE = (1 << 3),
+} eHookGpencil_Flag;
+
+typedef enum eHookGpencil_Falloff {
+ eGPHook_Falloff_None = 0,
+ eGPHook_Falloff_Curve = 1,
+ eGPHook_Falloff_Sharp = 2,
+ eGPHook_Falloff_Smooth = 3,
+ eGPHook_Falloff_Root = 4,
+ eGPHook_Falloff_Linear = 5,
+ eGPHook_Falloff_Const = 6,
+ eGPHook_Falloff_Sphere = 7,
+ eGPHook_Falloff_InvSquare = 8,
+} eHookGpencil_Falloff;
+
+typedef struct SimplifyGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float factor; /* factor of simplify */
+ short mode; /* type of simplify */
+ short step; /* every n vertex to keep */
+} SimplifyGpencilModifierData;
+
+typedef enum eSimplifyGpencil_Flag {
+ GP_SIMPLIFY_INVERT_LAYER = (1 << 0),
+ GP_SIMPLIFY_INVERT_PASS = (1 << 1),
+} eSimplifyGpencil_Flag;
+
+typedef enum eSimplifyGpencil_Mode {
+ /* Keep only one vertex every n vertices */
+ GP_SIMPLIFY_FIXED = 0,
+ /* Use RDP algorithm */
+ GP_SIMPLIFY_ADAPTATIVE = 1,
+} eSimplifyGpencil_Mode;
+
+typedef struct OffsetGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* flags */
+ float loc[3];
+ float rot[3];
+ float scale[3];
+ char pad[4];
+} OffsetGpencilModifierData;
+
+typedef enum eOffsetGpencil_Flag {
+ GP_OFFSET_INVERT_LAYER = (1 << 0),
+ GP_OFFSET_INVERT_PASS = (1 << 1),
+ GP_OFFSET_INVERT_VGROUP = (1 << 2)
+} eOffsetGpencil_Flag;
+
+typedef struct SmoothGpencilModifierData {
+ GpencilModifierData modifier;
+ char layername[64]; /* layer name */
+ char vgname[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ int pass_index; /* custom index for passes */
+ int flag; /* several flags */
+ float factor; /* factor of noise */
+ int step; /* how many times apply smooth */
+} SmoothGpencilModifierData;
+
+typedef enum eSmoothGpencil_Flag {
+ GP_SMOOTH_MOD_LOCATION = (1 << 0),
+ GP_SMOOTH_MOD_STRENGTH = (1 << 1),
+ GP_SMOOTH_MOD_THICKNESS = (1 << 2),
+ GP_SMOOTH_INVERT_LAYER = (1 << 3),
+ GP_SMOOTH_INVERT_PASS = (1 << 4),
+ GP_SMOOTH_INVERT_VGROUP = (1 << 5),
+ GP_SMOOTH_MOD_UV = (1 << 6),
+} eSmoothGpencil_Flag;
+
+#define MOD_MESHSEQ_READ_ALL \
+ (MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)
+
+#endif /* __DNA_GPENCIL_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index e2ee561de7f..8febfbc8ffc 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -36,6 +36,17 @@
struct AnimData;
struct CurveMapping;
+struct GHash;
+struct MDeformVert;
+
+/* TODO: add size as userprefs parameter */
+#define GP_OBGPENCIL_DEFAULT_SIZE 0.2f
+#define GP_DEFAULT_PIX_FACTOR 1.0f
+#define GP_DEFAULT_GRID_LINES 4
+#define GP_MAX_INPUT_SAMPLES 10
+
+/* ***************************************** */
+/* GP Stroke Points */
/* Grease-Pencil Annotations - 'Stroke Point'
* -> Coordinates may either be 2d or 3d depending on settings at the time
@@ -47,7 +58,10 @@ typedef struct bGPDspoint {
float pressure; /* pressure of input device (from 0 to 1) at this point */
float strength; /* color strength (used for alpha factor) */
float time; /* seconds since start of stroke */
- int flag; /* additional options (NOTE: can shrink this field down later if needed) */
+ int flag; /* additional options */
+
+ float uv_fac; /* factor of uv along the stroke */
+ float uv_rot; /* uv rotation for dot mode */
} bGPDspoint;
/* bGPDspoint->flag */
@@ -59,54 +73,24 @@ typedef enum eGPDspoint_Flag {
GP_SPOINT_TAG = (1 << 1),
} eGPSPoint_Flag;
+/* ***************************************** */
+/* GP Fill - Triangle Tesselation Data */
+
/* Grease-Pencil Annotations - 'Triangle'
- * A triangle contains the index of three vertices for filling the stroke
- * This is only used if high quality fill is enabled.
- * (not saved to blend file).
+ * -> A triangle contains the index of three vertices for filling the stroke
+ * This is only used if high quality fill is enabled
*/
typedef struct bGPDtriangle {
/* indices for tesselated triangle used for GP Fill */
unsigned int verts[3];
+ /* texture coordinates for verts */
+ float uv[3][2];
} bGPDtriangle;
-/* GP brush (used for new strokes) */
-typedef struct bGPDbrush {
- struct bGPDbrush *next, *prev;
+/* ***************************************** */
- char info[64]; /* Brush name. Must be unique. */
- short thickness; /* thickness to apply to strokes */
- short flag;
- float draw_smoothfac; /* amount of smoothing to apply to newly created strokes */
- short draw_smoothlvl; /* number of times to apply smooth factor to new strokes */
- short sublevel; /* number of times to subdivide new strokes */
-
- float draw_sensitivity; /* amount of sensivity to apply to newly created strokes */
- float draw_strength; /* amount of alpha strength to apply to newly created strokes */
- float draw_jitter; /* amount of jitter to apply to newly created strokes */
- float draw_angle; /* angle when the brush has full thickness */
- float draw_angle_factor; /* factor to apply when angle change (only 90 degrees) */
- float draw_random_press; /* factor of randomness for sensitivity and strength */
- float draw_random_sub; /* factor of randomness for subdivision */
- struct CurveMapping *cur_sensitivity;
- struct CurveMapping *cur_strength;
- struct CurveMapping *cur_jitter;
-} bGPDbrush;
-
-/* bGPDbrush->flag */
-typedef enum eGPDbrush_Flag {
- /* brush is active */
- GP_BRUSH_ACTIVE = (1 << 0),
- /* brush use pressure */
- GP_BRUSH_USE_PRESSURE = (1 << 1),
- /* brush use pressure for alpha factor */
- GP_BRUSH_USE_STENGTH_PRESSURE = (1 << 2),
- /* brush use pressure for alpha factor */
- GP_BRUSH_USE_JITTER_PRESSURE = (1 << 3),
- /* brush use random for pressure */
- GP_BRUSH_USE_RANDOM_PRESSURE = (1 << 4),
- /* brush use random for strength */
- GP_BRUSH_USE_RANDOM_STRENGTH = (1 << 5)
-} eGPDbrush_Flag;
+/* ***************************************** */
+/* GP Palettes (Deprecated - 2.78 - 2.79 only) */
/* color of palettes */
typedef struct bGPDpalettecolor {
@@ -129,9 +113,7 @@ typedef enum eGPDpalettecolor_Flag {
/* do onion skinning */
PC_COLOR_ONIONSKIN = (1 << 3),
/* "volumetric" strokes */
- PC_COLOR_VOLUMETRIC = (1 << 4),
- /* Use High quality fill */
- PC_COLOR_HQ_FILL = (1 << 5)
+ PC_COLOR_VOLUMETRIC = (1 << 4)
} eGPDpalettecolor_Flag;
/* palette of colors */
@@ -152,6 +134,21 @@ typedef enum eGPDpalette_Flag {
PL_PALETTE_ACTIVE = (1 << 0)
} eGPDpalette_Flag;
+/* ***************************************** */
+/* GP Strokes */
+
+/* Runtime temp data for bGPDstroke */
+typedef struct bGPDstroke_runtime {
+ /* runtime final colors (result of original colors and modifiers) */
+ float tmp_stroke_rgba[4];
+ float tmp_fill_rgba[4];
+
+ /* temporary layer name only used during copy/paste to put the stroke in the original layer */
+ char tmp_layerinfo[128];
+
+ float multi_frame_falloff; /* runtime falloff factor (only for transform) */
+} bGPDstroke_runtime;
+
/* Grease-Pencil Annotations - 'Stroke'
* -> A stroke represents a (simplified version) of the curve
* drawn by the user in one 'mousedown'->'mouseup' operation
@@ -168,14 +165,16 @@ typedef struct bGPDstroke {
short flag, pad[2]; /* various settings about this stroke */
double inittime; /* Init time of stroke */
- /* The pointer to color is only used during drawing, but not saved
- * colorname is the join with the palette, but when draw, the pointer is update if the value is NULL
- * to speed up the drawing
- */
- char colorname[128]; /* color name */
- bGPDpalettecolor *palcolor; /* current palette color */
- /* temporary layer name only used during copy/paste to put the stroke in the original layer */
- char tmp_layerinfo[128];
+
+ char colorname[128] DNA_DEPRECATED; /* color name */
+
+ int mat_nr; /* material index */
+ char pad_[4];
+
+ struct MDeformVert *dvert; /* vertex weight data */
+
+ bGPDstroke_runtime runtime;
+ char pad_1[4];
} bGPDstroke;
/* bGPDstroke->flag */
@@ -190,14 +189,22 @@ typedef enum eGPDstroke_Flag {
GP_STROKE_SELECT = (1 << 3),
/* Recalculate triangulation for high quality fill (when true, force a new recalc) */
GP_STROKE_RECALC_CACHES = (1 << 4),
- /* Recalculate the color pointer using the name as index (true force a new recalc) */
- GP_STROKE_RECALC_COLOR = (1 << 5),
/* Flag used to indicate that stroke is closed and draw edge between last and first point */
GP_STROKE_CYCLIC = (1 << 7),
+ /* Flag used to indicate that stroke is used for fill close and must use fill color for stroke and no fill area */
+ GP_STROKE_NOFILL = (1 << 8),
/* only for use with stroke-buffer (while drawing eraser) */
GP_STROKE_ERASER = (1 << 15)
} eGPDstroke_Flag;
+/* ***************************************** */
+/* GP Frame */
+
+/* Runtime temp data for bGPDframe */
+typedef struct bGPDframe_runtime {
+ float viewmatrix[4][4]; /* parent matrix for drawing */
+} bGPDframe_runtime;
+
/* Grease-Pencil Annotations - 'Frame'
* -> Acts as storage for the 'image' formed by strokes
*/
@@ -210,6 +217,8 @@ typedef struct bGPDframe {
short flag; /* temp settings */
short key_type; /* keyframe type (eBezTriple_KeyframeType) */
+
+ bGPDframe_runtime runtime;
} bGPDframe;
/* bGPDframe->flag */
@@ -220,6 +229,16 @@ typedef enum eGPDframe_Flag {
GP_FRAME_SELECT = (1 << 1)
} eGPDframe_Flag;
+/* ***************************************** */
+/* GP Layer */
+
+/* Runtime temp data for bGPDlayer */
+typedef struct bGPDlayer_runtime {
+ struct GHash *derived_data; /* runtime data created by modifiers */
+ int icon_id; /* id for dynamic icon used to show annotation color preview for layer */
+ char pad[4];
+} bGPDlayer_runtime;
+
/* Grease-Pencil Annotations - 'Layer' */
typedef struct bGPDlayer {
struct bGPDlayer *next, *prev;
@@ -228,27 +247,27 @@ typedef struct bGPDlayer {
bGPDframe *actframe; /* active frame (should be the frame that is currently being displayed) */
short flag; /* settings for layer */
- short thickness; /* current thickness to apply to strokes */
-
- short gstep; /* Ghosts Before: max number of ghost frames to show between active frame and the one before it (0 = only the ghost itself) */
- short gstep_next; /* Ghosts After: max number of ghost frames to show after active frame and the following it (0 = only the ghost itself) */
+ short onion_flag; /* Per-layer onion-skinning flags (eGPDlayer_OnionFlag) */
- float gcolor_prev[3]; /* optional color for ghosts before the active frame */
- float gcolor_next[3]; /* optional color for ghosts after the active frame */
+ float color[4]; /* Color for strokes in layers. Used for annotations, and for ruler (which uses GPencil internally) */
+ float fill[4]; /* Fill color for strokes in layers. Not used anymore (was only for) */
- float color[4]; /* Color for strokes in layers (replaced by palettecolor). Only used for ruler (which uses GPencil internally) */
- float fill[4]; /* Fill color for strokes in layers. Not used and replaced by palettecolor fill */
+ char info[128]; /* name/reference info for this layer (i.e. "director's comments, 12/3")
+ * needs to be kept unique, as it's used as the layer identifier */
- char info[128]; /* optional reference info about this layer (i.e. "director's comments, 12/3")
- * this is used for the name of the layer too and kept unique. */
+ short thickness; /* thickness to apply to strokes (Annotations) */
+ char pad_1[2];
struct Object *parent; /* parent object */
float inverse[4][4]; /* inverse matrix (only used if parented) */
char parsubstr[64]; /* String describing subobject info, MAX_ID_NAME-2 */
- short partype, pad;
+ short partype;
+ short line_change; /* Thickness adjustment */
float tintcolor[4]; /* Color used to tint layer, alpha value is used as factor */
float opacity; /* Opacity of the layer */
+
+ bGPDlayer_runtime runtime;
} bGPDlayer;
/* bGPDlayer->flag */
@@ -261,51 +280,89 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_ACTIVE = (1 << 2),
/* draw points of stroke for debugging purposes */
GP_LAYER_DRAWDEBUG = (1 << 3),
- /* do onion skinning */
- GP_LAYER_ONIONSKIN = (1 << 4),
/* for editing in Action Editor */
GP_LAYER_SELECT = (1 << 5),
/* current frame for layer can't be changed */
GP_LAYER_FRAMELOCK = (1 << 6),
/* don't render xray (which is default) */
GP_LAYER_NO_XRAY = (1 << 7),
- /* use custom color for ghosts before current frame */
- GP_LAYER_GHOST_PREVCOL = (1 << 8),
- /* use custom color for ghosts after current frame */
- GP_LAYER_GHOST_NEXTCOL = (1 << 9),
/* "volumetric" strokes */
GP_LAYER_VOLUMETRIC = (1 << 10),
- /* Use high quality fill (instead of buggy legacy OpenGL Fill) */
- GP_LAYER_HQ_FILL = (1 << 11),
/* Unlock color */
GP_LAYER_UNLOCK_COLOR = (1 << 12),
- /* always show onion skins (i.e. even during renders/animation playback) */
- GP_LAYER_GHOST_ALWAYS = (1 << 13),
} eGPDlayer_Flag;
+/* bGPDlayer->onion_flag */
+typedef enum eGPDlayer_OnionFlag {
+ /* do onion skinning */
+ GP_LAYER_ONIONSKIN = (1 << 0),
+} eGPDlayer_OnionFlag;
+
+/* ***************************************** */
+/* GP Datablock */
+
+/* Runtime temp data for bGPdata */
+typedef struct bGPdata_runtime {
+ /* Drawing Manager cache */
+ struct GHash *batch_cache_data;
+ void *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
+
+ /* GP Object drawing */
+ float scolor[4]; /* buffer stroke color */
+ float sfill[4]; /* buffer fill color */
+ short mode; /* settings for color */
+ short bstroke_style; /* buffer style for drawing strokes (used to select shader type) */
+ short bfill_style; /* buffer style for filling areas (used to select shader type) */
+
+ /* Stroke Buffer data (only used during paint-session)
+ * - buffer must be initialized before use, but freed after
+ * whole paint operation is over
+ */
+ short sbuffer_size; /* number of elements currently in cache */
+ short sbuffer_sflag; /* flags for stroke that cache represents */
+ char pad_[6];
+} bGPdata_runtime;
+
/* Grease-Pencil Annotations - 'DataBlock' */
typedef struct bGPdata {
ID id; /* Grease Pencil data is a datablock */
struct AnimData *adt; /* animation data - for animating draw settings */
- /* saved Grease-Pencil data */
+ /* Grease-Pencil data */
ListBase layers; /* bGPDlayers */
int flag; /* settings for this datablock */
- /* not-saved stroke buffer data (only used during paint-session)
- * - buffer must be initialized before use, but freed after
- * whole paint operation is over
- */
- short sbuffer_size; /* number of elements currently in cache */
- short sbuffer_sflag; /* flags for stroke that cache represents */
- void *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
- float scolor[4]; /* buffer color using palettes */
- float sfill[4]; /* buffer fill color */
- char pad[6]; /* padding for compiler alignment error */
- short sflag; /* settings for palette color */
-
- /* saved palettes */
- ListBase palettes;
+ short xray_mode; /* xray mode for strokes (eGP_DepthOrdering) */
+ char pad_1[2];
+
+ /* Palettes */
+ ListBase palettes DNA_DEPRECATED; /* list of bGPDpalette's - Deprecated (2.78 - 2.79 only) */
+
+ /* 3D Viewport/Appearance Settings */
+ float pixfactor; /* factor to define pixel size conversion */
+ float line_color[4]; /* color for edit line */
+
+ /* Onion skinning */
+ float onion_factor; /* onion alpha factor change */
+ int onion_mode; /* onion skinning range (eGP_OnionModes) */
+ int onion_flag; /* onion skinning flags (eGPD_OnionFlag) */
+ short gstep; /* Ghosts Before: max number of ghost frames to show between active frame and the one before it (0 = only the ghost itself) */
+ short gstep_next; /* Ghosts After: max number of ghost frames to show after active frame and the following it (0 = only the ghost itself) */
+
+ float gcolor_prev[3]; /* optional color for ghosts before the active frame */
+ float gcolor_next[3]; /* optional color for ghosts after the active frame */
+
+ char pad[4];
+ struct Material **mat; /* materials array */
+ short totcol; /* total materials */
+
+ /* stats */
+ short totlayer;
+ short totframe;
+ short totstroke;
+ short totpoint;
+ char pad_2[6];
+ bGPdata_runtime runtime;
} bGPdata;
/* bGPdata->flag */
@@ -314,8 +371,12 @@ typedef struct bGPdata {
* changes made during the porting process.
*/
typedef enum eGPdata_Flag {
- /* don't allow painting to occur at all */
- /* GP_DATA_LMBPLOCK = (1 << 0), */
+ /* datablock is used for "annotations"
+ * NOTE: This flag used to be used in 2.4x, but should hardly ever have been set.
+ * We can use this freely now, as all GP datablocks from pre-2.8 will get
+ * set on file load (as many old use cases are for "annotations" only)
+ */
+ GP_DATA_ANNOTATIONS = (1 << 0),
/* show debugging info in viewport (i.e. status print) */
GP_DATA_DISPINFO = (1 << 1),
@@ -339,10 +400,80 @@ typedef enum eGPdata_Flag {
/* Stroke Editing Mode - Toggle to enable alternative keymap for easier editing of stroke points */
GP_DATA_STROKE_EDITMODE = (1 << 8),
- /* Convenience/cache flag to make it easier to quickly toggle onion skinning on/off */
+ /* Main flag to switch onion skinning on/off */
GP_DATA_SHOW_ONIONSKINS = (1 << 9),
/* Draw a green and red point to indicate start and end of the stroke */
- GP_DATA_SHOW_DIRECTION = (1 << 10)
+ GP_DATA_SHOW_DIRECTION = (1 << 10),
+
+ /* Batch drawing cache need to be recalculated */
+ GP_DATA_CACHE_IS_DIRTY = (1 << 11),
+
+ /* Stroke Paint Mode - Toggle paint mode */
+ GP_DATA_STROKE_PAINTMODE = (1 << 12),
+ /* Stroke Editing Mode - Toggle sculpt mode */
+ GP_DATA_STROKE_SCULPTMODE = (1 << 13),
+ /* Stroke Editing Mode - Toggle weight paint mode */
+ GP_DATA_STROKE_WEIGHTMODE = (1 << 14),
+
+ /* keep stroke thickness unchanged when zoom change */
+ GP_DATA_STROKE_KEEPTHICKNESS = (1 << 15),
+
+ /* Allow edit several frames at the same time */
+ GP_DATA_STROKE_MULTIEDIT = (1 << 16),
} eGPdata_Flag;
+/* gpd->onion_flag */
+typedef enum eGPD_OnionFlag {
+ /* use custom color for ghosts before current frame */
+ GP_ONION_GHOST_PREVCOL = (1 << 0),
+ /* use custom color for ghosts after current frame */
+ GP_ONION_GHOST_NEXTCOL = (1 << 1),
+ /* always show onion skins (i.e. even during renders/animation playback) */
+ GP_ONION_GHOST_ALWAYS = (1 << 2),
+ /* use fade color in onion skin */
+ GP_ONION_FADE = (1 << 3),
+ /* Loop showing first frame after last frame */
+ GP_ONION_LOOP = (1 << 4),
+} eGPD_OnionFlag;
+
+/* gpd->onion_mode */
+typedef enum eGP_OnionModes {
+ GP_ONION_MODE_ABSOLUTE = 0,
+ GP_ONION_MODE_RELATIVE = 1,
+ GP_ONION_MODE_SELECTED = 2,
+} eGP_OnionModes;
+
+/* xray modes (Depth Ordering) */
+typedef enum eGP_DepthOrdering {
+ GP_XRAY_FRONT = 0,
+ GP_XRAY_3DSPACE = 1,
+ GP_XRAY_BACK = 2
+} eGP_DepthOrdering;
+
+/* ***************************************** */
+/* Mode Checking Macros */
+
+/* Check if 'multiedit sessions' is enabled */
+#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) \
+ ((gpd) && (gpd->flag & \
+ (GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)) && \
+ (gpd->flag & GP_DATA_STROKE_MULTIEDIT))
+
+/* Macros to check grease pencil modes */
+#define GPENCIL_ANY_MODE(gpd) \
+ ((gpd) && (gpd->flag & \
+ (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE | \
+ GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)))
+#define GPENCIL_ANY_EDIT_MODE(gpd) \
+ ((gpd) && (gpd->flag & (GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)))
+#define GPENCIL_PAINT_MODE(gpd) \
+ ((gpd) && (gpd->flag & (GP_DATA_STROKE_PAINTMODE)))
+#define GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd) \
+ ((gpd) && (gpd->flag & (GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)))
+#define GPENCIL_NONE_EDIT_MODE(gpd) \
+ ((gpd) && ((gpd->flag & (GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)) == 0))
+#define GPENCIL_LAZY_MODE(brush, shift) \
+ (((brush) && ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) && (shift == 0))) || \
+ (((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && (shift == 1)))
+
#endif /* __DNA_GPENCIL_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index bfdd21807b8..e6b1bda7cf5 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -104,6 +104,8 @@ enum {
BASE_ENABLED_VIEWPORT = (1 << 6), /* Object is enabled in viewport. */
BASE_ENABLED_RENDER = (1 << 7), /* Object is enabled in final render */
BASE_ENABLED = (1 << 9), /* Object is enabled. */
+ BASE_HOLDOUT = (1 << 10), /* Object masked out from render */
+ BASE_INDIRECT_ONLY = (1 << 11), /* Object only contributes indirectly to render */
};
/* LayerCollection->flag */
@@ -113,6 +115,8 @@ enum {
/* LAYER_COLLECTION_DEPRECATED2 = (1 << 2), */
/* LAYER_COLLECTION_DEPRECATED3 = (1 << 3), */
LAYER_COLLECTION_EXCLUDE = (1 << 4),
+ LAYER_COLLECTION_HOLDOUT = (1 << 5),
+ LAYER_COLLECTION_INDIRECT_ONLY = (1 << 6),
};
/* Layer Collection->runtime_flag */
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
index 81286e5e4d0..490e2574a33 100644
--- a/source/blender/makesdna/DNA_lightprobe_types.h
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -68,11 +68,9 @@ typedef struct LightProbe {
struct Image *image; /* Image to use on as lighting data */
struct Collection *visibility_grp; /* Object visibility group, inclusive or exclusive */
- float data_draw_size;
-
/* Runtime display data */
float distfalloff, distgridinf;
- float pad;
+ float pad[2];
} LightProbe;
/* Probe->type */
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index eb469895fd7..9d4da91aaed 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -54,6 +54,59 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
+typedef struct MaterialGPencilStyle {
+ struct Image *sima; /* Texture image for strokes */
+ struct Image *ima; /* Texture image for filling */
+ float stroke_rgba[4]; /* color for paint and strokes (alpha included) */
+ float fill_rgba[4]; /* color that should be used for drawing "fills" for strokes (alpha included) */
+ float mix_rgba[4]; /* secondary color used for gradients and other stuff */
+ short flag; /* settings */
+ short index; /* custom index for passes */
+ short stroke_style; /* style for drawing strokes (used to select shader type) */
+ short fill_style; /* style for filling areas (used to select shader type) */
+ float mix_factor; /* factor used to define shader behavior (several uses) */
+ float gradient_angle; /* angle used for gradients orientation */
+ float gradient_radius; /* radius for radial gradients */
+ float pattern_gridsize; /* cheesboard size */
+ float gradient_scale[2]; /* uv coordinates scale */
+ float gradient_shift[2]; /* factor to shift filling in 2d space */
+ float texture_angle; /* angle used for texture orientation */
+ float texture_scale[2]; /* texture scale (separated of uv scale) */
+ float texture_offset[2]; /* factor to shift texture in 2d space */
+ float texture_opacity; /* texture opacity */
+ float texture_pixsize; /* pixel size for uv along the stroke */
+ int mode; /* drawing mode (line or dots) */
+
+ int gradient_type; /* type of gradient */
+ char pad[4];
+} MaterialGPencilStyle;
+
+/* MaterialGPencilStyle->flag */
+typedef enum eMaterialGPencilStyle_Flag {
+ /* Fill Texture is a pattern */
+ GP_STYLE_FILL_PATTERN = (1 << 0),
+ /* don't display color */
+ GP_STYLE_COLOR_HIDE = (1 << 1),
+ /* protected from further editing */
+ GP_STYLE_COLOR_LOCKED = (1 << 2),
+ /* do onion skinning */
+ GP_STYLE_COLOR_ONIONSKIN = (1 << 3),
+ /* clamp texture */
+ GP_STYLE_COLOR_TEX_CLAMP = (1 << 4),
+ /* mix texture */
+ GP_STYLE_COLOR_TEX_MIX = (1 << 5),
+ /* Flip fill colors */
+ GP_STYLE_COLOR_FLIP_FILL = (1 << 6),
+ /* Stroke Texture is a pattern */
+ GP_STYLE_STROKE_PATTERN = (1 << 7)
+} eMaterialGPencilStyle_Flag;
+
+typedef enum eMaterialGPencilStyle_Mode {
+ GP_STYLE_MODE_LINE = 0, /* line */
+ GP_STYLE_MODE_DOTS = 1, /* dots */
+ GP_STYLE_MODE_BOX = 2, /* rectangles */
+} eMaterialGPencilStyle_Mode;
+
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -107,6 +160,9 @@ typedef struct Material {
/* Runtime cache for GLSL materials. */
ListBase gpumaterial;
+
+ /* grease pencil color */
+ struct MaterialGPencilStyle *gp_style;
} Material;
/* **************** MATERIAL ********************* */
@@ -217,7 +273,7 @@ enum {
enum {
MA_BL_HIDE_BACKSIDE = (1 << 0),
MA_BL_SS_REFRACTION = (1 << 1),
- MA_BL_SS_SUBSURFACE = (1 << 2),
+ MA_BL_SS_SUBSURFACE = (1 << 2), /* DEPRECATED */
MA_BL_TRANSLUCENCY = (1 << 3),
};
@@ -229,4 +285,24 @@ enum {
MA_BS_HASHED,
};
+/* Grease Pencil Stroke styles */
+enum {
+ GP_STYLE_STROKE_STYLE_SOLID = 0,
+ GP_STYLE_STROKE_STYLE_TEXTURE
+};
+
+/* Grease Pencil Fill styles */
+enum {
+ GP_STYLE_FILL_STYLE_SOLID = 0,
+ GP_STYLE_FILL_STYLE_GRADIENT,
+ GP_STYLE_FILL_STYLE_CHESSBOARD,
+ GP_STYLE_FILL_STYLE_TEXTURE
+};
+
+/* Grease Pencil Gradient Types */
+enum {
+ GP_STYLE_GRADIENT_LINEAR = 0,
+ GP_STYLE_GRADIENT_RADIAL
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 6e8c1d10c91..5a69db4e0b4 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -392,7 +392,7 @@ enum {
/* SELECT = (1 << 0), */
ME_VERT_TMP_TAG = (1 << 2),
ME_HIDE = (1 << 4),
- ME_VERT_MERGED = (1 << 6),
+/* ME_VERT_MERGED = (1 << 6), */
ME_VERT_PBVH_UPDATE = (1 << 7),
};
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index e3d02cdc0c8..5000a4d248a 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -90,7 +90,8 @@ typedef enum ModifierType {
eModifierType_CorrectiveSmooth = 51,
eModifierType_MeshSequenceCache = 52,
eModifierType_SurfaceDeform = 53,
- eModifierType_Hair = 54,
+ eModifierType_WeightedNormal = 54,
+ eModifierType_Hair = 55,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -124,13 +125,6 @@ typedef enum {
eModifierFlag_SharedCaches = (1 << 1),
} ModifierFlag;
-typedef enum {
- eSubsurfModifierFlag_Incremental = (1 << 0),
- eSubsurfModifierFlag_DebugIncr = (1 << 1),
- eSubsurfModifierFlag_ControlEdges = (1 << 2),
- eSubsurfModifierFlag_SubsurfUv = (1 << 3),
-} SubsurfModifierFlag;
-
/* not a real modifier */
typedef struct MappingInfoModifierData {
ModifierData modifier;
@@ -142,6 +136,18 @@ typedef struct MappingInfoModifierData {
int texmapping;
} MappingInfoModifierData;
+typedef enum {
+ eSubsurfModifierFlag_Incremental = (1 << 0),
+ eSubsurfModifierFlag_DebugIncr = (1 << 1),
+ eSubsurfModifierFlag_ControlEdges = (1 << 2),
+ eSubsurfModifierFlag_SubsurfUv = (1 << 3),
+} SubsurfModifierFlag;
+
+typedef enum {
+ SUBSURF_TYPE_CATMULL_CLARK = 0,
+ SUBSURF_TYPE_SIMPLE = 1,
+} eSubsurfModifierType;
+
typedef struct SubsurfModifierData {
ModifierData modifier;
@@ -318,6 +324,10 @@ enum {
MOD_EDGESPLIT_FROMFLAG = (1 << 2),
};
+typedef struct BevelModNorEditData {
+ struct GHash *faceHash;
+} BevelModNorEditData;
+
typedef struct BevelModifierData {
ModifierData modifier;
@@ -328,13 +338,16 @@ typedef struct BevelModifierData {
short lim_flags; /* flags to tell the tool how to limit the bevel */
short e_flags; /* flags to direct how edge weights are applied to verts */
short mat; /* material index if >= 0, else material inherited from surrounding faces */
- short pad;
+ short edge_flags;
int pad2;
float profile; /* controls profile shape (0->1, .5 is round) */
/* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */
float bevel_angle;
/* if the MOD_BEVEL_VWEIGHT option is set, this will be the name of the vert group, MAX_VGROUP_NAME */
+ int hnmode;
+ float hn_strength;
char defgrp_name[64];
+ struct BevelModNorEditData clnordata;
} BevelModifierData;
/* BevelModifierData->flags and BevelModifierData->lim_flags */
@@ -355,6 +368,7 @@ enum {
/* MOD_BEVEL_DIST = (1 << 12), */ /* same as above */
MOD_BEVEL_OVERLAP_OK = (1 << 13),
MOD_BEVEL_EVEN_WIDTHS = (1 << 14),
+ MOD_BEVEL_SET_WN_STR = (1 << 15),
};
/* BevelModifierData->val_flags (not used as flags any more) */
@@ -365,6 +379,20 @@ enum {
MOD_BEVEL_AMT_PERCENT = 3,
};
+/* BevelModifierData->edge_flags */
+enum {
+ MOD_BEVEL_MARK_SEAM = (1 << 0),
+ MOD_BEVEL_MARK_SHARP = (1 << 1),
+};
+
+/* BevelModifierData->hnmode */
+enum {
+ MOD_BEVEL_HN_NONE,
+ MOD_BEVEL_HN_FACE,
+ MOD_BEVEL_HN_ADJ,
+ MOD_BEVEL_FIX_SHA,
+};
+
typedef struct SmokeModifierData {
ModifierData modifier;
@@ -1636,6 +1664,32 @@ enum {
MOD_SDEF_MODE_CENTROID = 2,
};
+typedef struct WeightedNormalModifierData {
+ ModifierData modifier;
+
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char mode, flag;
+ short weight;
+ float thresh;
+} WeightedNormalModifierData;
+
+/* Name/id of the generic PROP_INT cdlayer storing face weights. */
+#define MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID "__mod_weightednormals_faceweight"
+
+/* WeightedNormalModifierData.mode */
+enum {
+ MOD_WEIGHTEDNORMAL_MODE_FACE = 0,
+ MOD_WEIGHTEDNORMAL_MODE_ANGLE = 1,
+ MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE = 2,
+};
+
+/* WeightedNormalModifierData.flag */
+enum {
+ MOD_WEIGHTEDNORMAL_KEEP_SHARP = (1 << 0),
+ MOD_WEIGHTEDNORMAL_INVERT_VGROUP = (1 << 1),
+ MOD_WEIGHTEDNORMAL_FACE_INFLUENCE = (1 << 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 ca01ffc2b29..31a5931dde4 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -905,6 +905,14 @@ typedef struct NodeSunBeams {
float ray_length;
} NodeSunBeams;
+typedef struct NodeCryptomatte {
+ float add[3];
+ float remove[3];
+ char *matte_id;
+ int num_inputs;
+ int pad;
+} NodeCryptomatte;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@@ -953,6 +961,11 @@ typedef struct NodeSunBeams {
#define SHD_HAIR_REFLECTION 0
#define SHD_HAIR_TRANSMISSION 1
+/* principled hair parametrization */
+#define SHD_PRINCIPLED_HAIR_REFLECTANCE 0
+#define SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION 1
+#define SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION 2
+
/* blend texture */
#define SHD_BLEND_LINEAR 0
#define SHD_BLEND_QUADRATIC 1
diff --git a/source/blender/makesdna/DNA_object_enums.h b/source/blender/makesdna/DNA_object_enums.h
index 802ca6c7d0d..01228376174 100644
--- a/source/blender/makesdna/DNA_object_enums.h
+++ b/source/blender/makesdna/DNA_object_enums.h
@@ -37,7 +37,10 @@ typedef enum eObjectMode {
OB_MODE_TEXTURE_PAINT = 1 << 4,
OB_MODE_PARTICLE_EDIT = 1 << 5,
OB_MODE_POSE = 1 << 6,
- OB_MODE_GPENCIL = 1 << 7, /* NOTE: Just a dummy to make the UI nicer */
+ OB_MODE_GPENCIL_EDIT = 1 << 7,
+ OB_MODE_GPENCIL_PAINT = 1 << 8,
+ OB_MODE_GPENCIL_SCULPT = 1 << 9,
+ OB_MODE_GPENCIL_WEIGHT = 1 << 10,
} eObjectMode;
/* Any mode where the brush system is used. */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 999ebe0ccc3..1f6f7cd9bf2 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -142,6 +142,10 @@ typedef struct Object_Runtime {
* It has deforemation only modifiers applied on it.
*/
struct Mesh *mesh_deform_eval;
+
+
+ /* Runtime evaluated curve-specific data, not stored in the file. */
+ struct CurveCache *curve_cache;
} Object_Runtime;
typedef struct Object {
@@ -176,7 +180,9 @@ typedef struct Object {
ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile
ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */
ListBase modifiers; /* list of ModifierData structures */
+ ListBase greasepencil_modifiers; /* list of GpencilModifierData structures */
ListBase fmaps; /* list of facemaps */
+ ListBase shader_fx; /* list of viewport effects. Actually only used by grease pencil */
int mode; /* Local object mode */
int restore_mode;
@@ -280,10 +286,6 @@ typedef struct Object {
uint64_t lastDataMask; /* the custom data layer mask that was last used to calculate derivedDeform and derivedFinal */
uint64_t customdata_mask; /* (extra) custom data layer mask to use for creating derivedmesh, set by depsgraph */
- /* Runtime valuated curve-specific data, not stored in the file */
- struct CurveCache *curve_cache;
-
- ListBase gpulamp; /* runtime, for glsl lamp display only */
ListBase pc_ids;
struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */
@@ -351,6 +353,9 @@ enum {
/* 23 and 24 are for life and sector (old file compat.) */
OB_ARMATURE = 25,
+/* Grease Pencil object used in 3D view but not used for annotation in 2D */
+ OB_GPENCIL = 26,
+
OB_TYPE_MAX,
};
@@ -361,9 +366,9 @@ enum {
/* check if the object type supports materials */
#define OB_TYPE_SUPPORT_MATERIAL(_type) \
- ((_type) >= OB_MESH && (_type) <= OB_MBALL)
+ (((_type) >= OB_MESH && (_type) <= OB_MBALL) || ((_type) == OB_GPENCIL))
#define OB_TYPE_SUPPORT_VGROUP(_type) \
- (ELEM(_type, OB_MESH, OB_LATTICE))
+ (ELEM(_type, OB_MESH, OB_LATTICE, OB_GPENCIL))
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
(ELEM(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
#define OB_TYPE_SUPPORT_PARVERT(_type) \
@@ -375,10 +380,10 @@ enum {
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \
- (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_LP, ID_CA, ID_LT, ID_AR))
+ (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_LP, ID_CA, ID_LT, ID_GD, ID_AR))
#define OB_DATA_SUPPORT_ID_CASE \
- ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_LP: case ID_CA: case ID_LT: case ID_AR
+ ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_LP: case ID_CA: case ID_LT: case ID_GD: case ID_AR
/* partype: first 4 bits: type */
enum {
@@ -466,6 +471,13 @@ enum {
OB_EMPTY_IMAGE = 8,
};
+/* gpencil add types */
+enum {
+ GP_EMPTY = 0,
+ GP_STROKE = 1,
+ GP_MONKEY = 2
+};
+
/* boundtype */
enum {
OB_BOUND_BOX = 0,
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 449f71905f0..75d0ce493f5 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -60,6 +60,10 @@ enum {
TSE_CHILDSEARCH = (1 << 3),
TSE_SEARCHMATCH = (1 << 4),
TSE_HIGHLIGHTED = (1 << 5),
+ TSE_DRAG_INTO = (1 << 6),
+ TSE_DRAG_BEFORE = (1 << 7),
+ TSE_DRAG_AFTER = (1 << 8),
+ TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER),
};
/* TreeStoreElem->types */
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
index 693707b8b7a..a99d5b409be 100644
--- a/source/blender/makesdna/DNA_rigidbody_types.h
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -220,7 +220,8 @@ typedef struct RigidBodyCon {
int flag; /* (eRigidBodyCon_Flag) */
float breaking_threshold; /* breaking impulse threshold */
- float pad;
+ char spring_type; /* spring implementation to use */
+ char pad[3];
/* limits */
/* translation limits */
@@ -290,9 +291,15 @@ typedef enum eRigidBodyCon_Type {
/* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */
RBC_TYPE_SPRING,
/* dirves bodies by applying linear and angular forces */
- RBC_TYPE_MOTOR
+ RBC_TYPE_MOTOR,
} eRigidBodyCon_Type;
+/* Spring implementation type for RigidBodyOb */
+typedef enum eRigidBodyCon_SpringType {
+ RBC_SPRING_TYPE1 = 0, /* btGeneric6DofSpringConstraint */
+ RBC_SPRING_TYPE2, /* btGeneric6DofSpring2Constraint */
+} eRigidBodyCon_SpringType;
+
/* Flags for RigidBodyCon */
typedef enum eRigidBodyCon_Flag {
/* constraint influences rigid body motion */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 0c4c0a00f1a..262c24164df 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -66,7 +66,6 @@ struct AnimData;
struct Editing;
struct SceneStats;
struct bGPdata;
-struct bGPDbrush;
struct MovieClip;
struct ColorSpace;
struct SceneCollection;
@@ -686,7 +685,8 @@ typedef struct RenderData {
/* render simplify */
short simplify_subsurf;
short simplify_subsurf_render;
- short pad9, pad10;
+ short simplify_gpencil;
+ short pad10;
float simplify_particles;
float simplify_particles_render;
@@ -905,6 +905,11 @@ typedef struct UvSculpt {
Paint paint;
} UvSculpt;
+/* grease pencil drawing brushes */
+typedef struct GpPaint {
+ Paint paint;
+} GpPaint;
+
/* ------------------------------------------- */
/* Vertex Paint */
@@ -929,15 +934,18 @@ enum {
typedef enum eGP_EditBrush_Types {
GP_EDITBRUSH_TYPE_SMOOTH = 0,
GP_EDITBRUSH_TYPE_THICKNESS = 1,
- GP_EDITBRUSH_TYPE_GRAB = 2,
- GP_EDITBRUSH_TYPE_PUSH = 3,
- GP_EDITBRUSH_TYPE_TWIST = 4,
- GP_EDITBRUSH_TYPE_PINCH = 5,
- GP_EDITBRUSH_TYPE_RANDOMIZE = 6,
- GP_EDITBRUSH_TYPE_SUBDIVIDE = 7,
- GP_EDITBRUSH_TYPE_SIMPLIFY = 8,
- GP_EDITBRUSH_TYPE_CLONE = 9,
- GP_EDITBRUSH_TYPE_STRENGTH = 10,
+ GP_EDITBRUSH_TYPE_STRENGTH = 2,
+ GP_EDITBRUSH_TYPE_GRAB = 3,
+ GP_EDITBRUSH_TYPE_PUSH = 4,
+ GP_EDITBRUSH_TYPE_TWIST = 5,
+ GP_EDITBRUSH_TYPE_PINCH = 6,
+ GP_EDITBRUSH_TYPE_RANDOMIZE = 7,
+ GP_EDITBRUSH_TYPE_CLONE = 8,
+ GP_EDITBRUSH_TYPE_SUBDIVIDE = 9,
+ GP_EDITBRUSH_TYPE_SIMPLIFY = 10,
+ /* add any sculpt brush above this value */
+ GP_EDITBRUSH_TYPE_WEIGHT = 11,
+ /* add any weight paint brush below this value. Do no mix brushes */
/* !!! Update GP_EditBrush_Data brush[###]; below !!! */
TOT_GP_EDITBRUSH_TYPES
@@ -956,6 +964,8 @@ typedef struct GP_EditBrush_Data {
short size; /* radius of brush */
short flag; /* eGP_EditBrush_Flag */
float strength; /* strength of effect */
+ float curcolor_add[3]; /* cursor color for add */
+ float curcolor_sub[3]; /* cursor color for sub */
} GP_EditBrush_Data;
/* GP_EditBrush_Data.flag */
@@ -969,20 +979,31 @@ typedef enum eGP_EditBrush_Flag {
GP_EDITBRUSH_FLAG_USE_FALLOFF = (1 << 2),
/* smooth brush affects pressure values as well */
- GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE = (1 << 3)
+ GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE = (1 << 3),
+ /* enable screen cursor */
+ GP_EDITBRUSH_FLAG_ENABLE_CURSOR = (1 << 4),
+ /* temporary invert action */
+ GP_EDITBRUSH_FLAG_TMP_INVERT = (1 << 5),
} eGP_EditBrush_Flag;
/* GPencil Stroke Sculpting Settings */
typedef struct GP_BrushEdit_Settings {
- GP_EditBrush_Data brush[11]; /* TOT_GP_EDITBRUSH_TYPES */
+ GP_EditBrush_Data brush[12]; /* TOT_GP_EDITBRUSH_TYPES */
void *paintcursor; /* runtime */
- int brushtype; /* eGP_EditBrush_Types */
+ int brushtype; /* eGP_EditBrush_Types (sculpt) */
int flag; /* eGP_BrushEdit_SettingsFlag */
int lock_axis; /* eGP_Lockaxis_Types lock drawing to one axis */
- float alpha; /* alpha factor for selection color */
+ char pad1[4];
+
+ /* weight paint is a submode of sculpt but use its own index. All weight paint
+ * brushes must be defined at the end of the brush array.
+ */
+ int weighttype; /* eGP_EditBrush_Types (weight paint) */
+ char pad[4];
+ struct CurveMapping *cur_falloff; /* multiframe edit falloff effect by frame */
} GP_BrushEdit_Settings;
/* GP_BrushEdit_Settings.flag */
@@ -995,6 +1016,12 @@ typedef enum eGP_BrushEdit_SettingsFlag {
GP_BRUSHEDIT_FLAG_APPLY_STRENGTH = (1 << 2),
/* apply brush to thickness */
GP_BRUSHEDIT_FLAG_APPLY_THICKNESS = (1 << 3),
+ /* apply brush to thickness */
+ GP_BRUSHEDIT_FLAG_WEIGHT_MODE = (1 << 4),
+ /* enable falloff for multiframe editing */
+ GP_BRUSHEDIT_FLAG_FRAME_FALLOFF = (1 << 5),
+ /* apply brush to uv data */
+ GP_BRUSHEDIT_FLAG_APPLY_UV = (1 << 6),
} eGP_BrushEdit_SettingsFlag;
@@ -1213,6 +1240,7 @@ typedef struct ToolSettings {
VPaint *wpaint; /* weight paint */
Sculpt *sculpt;
UvSculpt *uvsculpt; /* uv smooth */
+ GpPaint *gp_paint; /* gpencil paint */
/* Vertex group weight - used only for editmode, not weight
* paint */
@@ -1236,19 +1264,19 @@ typedef struct ToolSettings {
/* Auto-IK */
short autoik_chainlen; /* runtime only */
- /* SCE_MPR_LOC/SCAL */
- char gizmo_flag;
-
/* Grease Pencil */
char gpencil_flags; /* flags/options for how the tool works */
- char gpencil_src; /* for main 3D view Grease Pencil, where data comes from */
char gpencil_v3d_align; /* stroke placement settings: 3D View */
char gpencil_v2d_align; /* : General 2D Editor */
char gpencil_seq_align; /* : Sequencer Preview */
char gpencil_ima_align; /* : Image Editor */
- char _pad3[3];
+ /* Annotations */
+ char annotate_v3d_align; /* stroke placement settings - 3D View */
+
+ short annotate_thickness; /* default stroke thickness for annotation strokes */
+ char _pad3[2];
/* Grease Pencil Sculpt */
struct GP_BrushEdit_Settings gp_sculpt;
@@ -1256,10 +1284,7 @@ typedef struct ToolSettings {
/* Grease Pencil Interpolation Tool(s) */
struct GP_Interpolate_Settings gp_interpolate;
- /* Grease Pencil Drawing Brushes (bGPDbrush) */
- ListBase gp_brushes;
-
- /* Image Paint (8 byttse aligned please!) */
+ /* Image Paint (8 bytes aligned please!) */
struct ImagePaintSettings imapaint;
/* Particle Editing */
@@ -1281,7 +1306,9 @@ typedef struct ToolSettings {
/* Alt+RMB option */
char edge_mode;
char edge_mode_live_unwrap;
- char _pad1;
+
+ /* SCE_MPR_LOC/SCAL */
+ char gizmo_flag;
/* Transform */
char transform_pivot_point;
@@ -1322,6 +1349,10 @@ typedef struct ToolSettings {
struct CurvePaintSettings curve_paint_settings;
struct MeshStatVis statvis;
+
+ /* Normal Editing */
+ float normal_vector[3];
+ int face_strength;
} ToolSettings;
/* *************************************************************** */
@@ -1381,6 +1412,9 @@ typedef struct SceneDisplay {
float matcap_ssao_attenuation;
int matcap_ssao_samples;
int pad;
+
+ /* OpenGL render engine settings. */
+ View3DShading shading;
} SceneDisplay;
typedef struct SceneEEVEE {
@@ -1500,7 +1534,7 @@ typedef struct Scene {
/* Units */
struct UnitSettings unit;
- /* Grease Pencil */
+ /* Grease Pencil - Annotations */
struct bGPdata *gpd;
/* Movie Tracking */
@@ -1512,6 +1546,7 @@ typedef struct Scene {
uint64_t customdata_mask; /* XXX. runtime flag for drawing, actually belongs in the window, only used by BKE_object_handle_update() */
uint64_t customdata_mask_modal; /* XXX. same as above but for temp operator use (gl renders) */
+
/* Color Management */
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
@@ -1707,7 +1742,7 @@ enum {
/* RenderData.engine (scene.c) */
extern const char *RE_engine_id_BLENDER_EEVEE;
-extern const char *RE_engine_id_BLENDER_WORKBENCH;
+extern const char *RE_engine_id_BLENDER_OPENGL;
extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */
@@ -1853,6 +1888,13 @@ enum {
OB_DRAW_GROUPUSER_ALL = 2
};
+/* toolsettings->face_strength */
+enum {
+ FACE_STRENGTH_WEAK = -16384,
+ FACE_STRENGTH_MEDIUM = 0,
+ FACE_STRENGTH_STRONG = 16384,
+};
+
/* object_vgroup.c */
/* ToolSettings.vgroupsubset */
typedef enum eVGroupSelect {
@@ -2011,25 +2053,39 @@ typedef enum eImagePaintMode {
#define EDGE_MODE_TAG_FREESTYLE 5
/* ToolSettings.gizmo_flag */
-#define SCE_MANIP_TRANSLATE 1
-#define SCE_MANIP_ROTATE 2
-#define SCE_MANIP_SCALE 4
+enum {
+ SCE_MANIP_TRANSLATE = (1 << 0),
+ SCE_MANIP_ROTATE = (1 << 1),
+ SCE_MANIP_SCALE = (1 << 2),
+
+ SCE_MANIP_DISABLE_APRON = (1 << 3),
+};
/* ToolSettings.gpencil_flags */
typedef enum eGPencil_Flags {
- /* "Continuous Drawing" - The drawing operator enters a mode where multiple strokes can be drawn */
- GP_TOOL_FLAG_PAINTSESSIONS_ON = (1 << 0),
/* When creating new frames, the last frame gets used as the basis for the new one */
GP_TOOL_FLAG_RETAIN_LAST = (1 << 1),
/* Add the strokes below all strokes in the layer */
- GP_TOOL_FLAG_PAINT_ONBACK = (1 << 2)
+ GP_TOOL_FLAG_PAINT_ONBACK = (1 << 2),
+ /* Show compact list of colors */
+ GP_TOOL_FLAG_THUMBNAIL_LIST = (1 << 3),
} eGPencil_Flags;
-/* ToolSettings.gpencil_src */
-typedef enum eGPencil_Source_3D {
- GP_TOOL_SOURCE_SCENE = 0,
- GP_TOOL_SOURCE_OBJECT = 1
-} eGPencil_Source_3d;
+/* scene->r.simplify_gpencil */
+typedef enum eGPencil_SimplifyFlags {
+ /* Simplify */
+ SIMPLIFY_GPENCIL_ENABLE = (1 << 0),
+ /* Simplify on play */
+ SIMPLIFY_GPENCIL_ON_PLAY = (1 << 1),
+ /* Simplify fill on viewport */
+ SIMPLIFY_GPENCIL_FILL = (1 << 2),
+ /* Simplify modifier on viewport */
+ SIMPLIFY_GPENCIL_MODIFIER = (1 << 3),
+ /* Remove fill external line */
+ SIMPLIFY_GPENCIL_REMOVE_FILL_LINE = (1 << 4),
+ /* Simplify Shader FX */
+ SIMPLIFY_GPENCIL_FX = (1 << 5)
+} eGPencil_SimplifyFlags;
/* ToolSettings.gpencil_*_align - Stroke Placement mode flags */
typedef enum eGPencil_Placement_Flags {
@@ -2045,6 +2101,7 @@ typedef enum eGPencil_Placement_Flags {
/* "Use Endpoints" */
GP_PROJECT_DEPTH_STROKE_ENDPOINTS = (1 << 4),
+ GP_PROJECT_CURSOR = (1 << 5),
} eGPencil_Placement_Flags;
/* ToolSettings.particle flag */
@@ -2093,7 +2150,7 @@ enum {
SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0),
SCE_EEVEE_VOLUMETRIC_LIGHTS = (1 << 1),
SCE_EEVEE_VOLUMETRIC_SHADOWS = (1 << 2),
- SCE_EEVEE_VOLUMETRIC_COLORED = (1 << 3),
+// SCE_EEVEE_VOLUMETRIC_COLORED = (1 << 3), /* Unused */
SCE_EEVEE_GTAO_ENABLED = (1 << 4),
SCE_EEVEE_GTAO_BENT_NORMALS = (1 << 5),
SCE_EEVEE_GTAO_BOUNCE = (1 << 6),
diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h
new file mode 100644
index 00000000000..f3c9f06c8dc
--- /dev/null
+++ b/source/blender/makesdna/DNA_shader_fx_types.h
@@ -0,0 +1,196 @@
+/*
+ * ***** 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 DNA_shader_fx_types.h
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_SHADER_FX_TYPES_H__
+#define __DNA_SHADER_FX_TYPES_H__
+
+#include "DNA_defs.h"
+#include "DNA_listBase.h"
+
+struct DRWShadingGroup;
+
+/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE!
+ * (ONLY ADD NEW ITEMS AT THE END)
+ */
+
+typedef enum ShaderFxType {
+ eShaderFxType_None = 0,
+ eShaderFxType_Blur = 1,
+ eShaderFxType_Flip = 2,
+ eShaderFxType_Light = 3,
+ eShaderFxType_Pixel = 4,
+ eShaderFxType_Swirl = 5,
+ eShaderFxType_Wave = 6,
+ eShaderFxType_Rim = 7,
+ eShaderFxType_Colorize = 8,
+ NUM_SHADER_FX_TYPES
+} ShaderFxType;
+
+typedef enum ShaderFxMode {
+ eShaderFxMode_Realtime = (1 << 0),
+ eShaderFxMode_Render = (1 << 1),
+ eShaderFxMode_Editmode = (1 << 2),
+ eShaderFxMode_Expanded = (1 << 3),
+} ShaderFxMode;
+
+typedef enum {
+ /* This fx has been inserted in local override, and hence can be fully edited. */
+ eShaderFxFlag_StaticOverride_Local = (1 << 0),
+} ShaderFxFlag;
+
+typedef struct ShaderFxData {
+ struct ShaderFxData *next, *prev;
+
+ int type, mode;
+ int stackindex;
+ short flag;
+ short pad;
+ char name[64]; /* MAX_NAME */
+
+ char *error;
+} ShaderFxData;
+
+/* Runtime temp data */
+typedef struct ShaderFxData_runtime {
+ struct DRWShadingGroup *fx_sh;
+ struct DRWShadingGroup *fx_sh_b;
+ struct DRWShadingGroup *fx_sh_c;
+} ShaderFxData_runtime;
+
+typedef struct BlurShaderFxData {
+ ShaderFxData shaderfx;
+ int radius[2];
+ int flag; /* flags */
+ int samples; /* number of samples */
+ float coc; /* circle of confusion */
+ int blur[2]; /* not visible in rna */
+ char pad[4];
+ ShaderFxData_runtime runtime;
+} BlurShaderFxData;
+
+typedef enum eBlurShaderFx_Flag {
+ FX_BLUR_DOF_MODE = (1 << 0)
+} eBlurShaderFx_Flag;
+
+typedef struct ColorizeShaderFxData {
+ ShaderFxData shaderfx;
+ int mode;
+ float low_color[4];
+ float high_color[4];
+ float factor;
+ int flag; /* flags */
+ char pad[4];
+ ShaderFxData_runtime runtime;
+} ColorizeShaderFxData;
+
+typedef enum ColorizeShaderFxModes {
+ eShaderFxColorizeMode_GrayScale = 0,
+ eShaderFxColorizeMode_Sepia = 1,
+ eShaderFxColorizeMode_BiTone = 2,
+ eShaderFxColorizeMode_Custom = 3,
+ eShaderFxColorizeMode_Transparent = 4,
+} ColorizeShaderFxModes;
+
+typedef struct FlipShaderFxData {
+ ShaderFxData shaderfx;
+ int flag; /* flags */
+ int flipmode; /* internal, not visible in rna */
+ ShaderFxData_runtime runtime;
+} FlipShaderFxData;
+
+typedef enum eFlipShaderFx_Flag {
+ FX_FLIP_HORIZONTAL = (1 << 0),
+ FX_FLIP_VERTICAL = (1 << 1),
+} eFlipShaderFx_Flag;
+
+typedef struct LightShaderFxData {
+ ShaderFxData shaderfx;
+ struct Object *object;
+ int flag; /* flags */
+ float energy;
+ float ambient;
+ float loc[4]; /* internal, not visible in rna */
+ char pad[4];
+ ShaderFxData_runtime runtime;
+} LightShaderFxData;
+
+typedef struct PixelShaderFxData {
+ ShaderFxData shaderfx;
+ int size[3]; /* last element used for shader only */
+ int flag; /* flags */
+ float rgba[4];
+ ShaderFxData_runtime runtime;
+} PixelShaderFxData;
+
+typedef enum ePixelShaderFx_Flag {
+ FX_PIXEL_USE_LINES = (1 << 0),
+} ePixelShaderFx_Flag;
+
+typedef struct RimShaderFxData {
+ ShaderFxData shaderfx;
+ int offset[2];
+ int flag; /* flags */
+ float rim_rgb[3];
+ float mask_rgb[3];
+ int mode;
+ int blur[2];
+ int samples;
+ char pad[4];
+ ShaderFxData_runtime runtime;
+} RimShaderFxData;
+
+typedef enum RimShaderFxModes {
+ eShaderFxRimMode_Normal = 0,
+ eShaderFxRimMode_Overlay = 1,
+ eShaderFxRimMode_Add = 2,
+ eShaderFxRimMode_Subtract = 3,
+ eShaderFxRimMode_Multiply = 4,
+ eShaderFxRimMode_Divide = 5,
+} RimShaderFxModes;
+
+typedef struct SwirlShaderFxData {
+ ShaderFxData shaderfx;
+ struct Object *object;
+ int flag; /* flags */
+ int radius;
+ float angle;
+ int transparent; /* not visible in rna */
+ ShaderFxData_runtime runtime;
+} SwirlShaderFxData;
+
+typedef enum eSwirlShaderFx_Flag {
+ FX_SWIRL_MAKE_TRANSPARENT = (1 << 0),
+} eSwirlShaderFx_Flag;
+
+typedef struct WaveShaderFxData {
+ ShaderFxData shaderfx;
+ float amplitude;
+ float period;
+ float phase;
+ int orientation;
+ int flag; /* flags */
+ char pad[4];
+ ShaderFxData_runtime runtime;
+} WaveShaderFxData;
+#endif /* __DNA_SHADER_FX_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index 76b609b0c6c..443c6923ed0 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -137,6 +137,9 @@ typedef struct SmokeDomainSettings {
struct GPUTexture *tex_wt;
struct GPUTexture *tex_shadow;
struct GPUTexture *tex_flame;
+ struct GPUTexture *tex_velocity_x;
+ struct GPUTexture *tex_velocity_y;
+ struct GPUTexture *tex_velocity_z;
float *shadow;
/* simulation data */
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index aefe1a7d5a3..02d3aa928c7 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -65,13 +65,15 @@ typedef struct bSound {
*/
struct PackedFile *newpackedfile;
struct Ipo *ipo;
+
float volume;
float attenuation;
float pitch;
float min_gain;
float max_gain;
float distance;
- int flags;
+ short flags;
+ short tags; /* Runtime only, always reset in readfile. */
int pad;
/* unused currently
@@ -116,13 +118,19 @@ enum {
SND_CFRA_NUM = 2,
};
+/* bSound->flags */
enum {
#ifdef DNA_DEPRECATED
SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
#endif
SOUND_FLAGS_CACHING = (1 << 4),
SOUND_FLAGS_MONO = (1 << 5),
- SOUND_FLAGS_WAVEFORM_LOADING = (1 << 6),
+};
+
+/* bSound->tags */
+enum {
+ SOUND_TAGS_WAVEFORM_NO_RELOAD = 1 << 0, /* Do not free/reset waveform on sound load, only used by undo code. */
+ SOUND_TAGS_WAVEFORM_LOADING = (1 << 6),
};
/* to DNA_sound_types.h*/
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index d6d043b03ae..5404f4160fd 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -198,6 +198,7 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_VIEW_LAYER = 13,
BCONTEXT_TOOL = 14,
BCONTEXT_WORKSPACE = 15,
+ BCONTEXT_SHADERFX = 16,
/* always as last... */
BCONTEXT_TOT
@@ -1346,7 +1347,7 @@ typedef enum eSpaceClip_Flag {
SC_SHOW_GRID = (1 << 9),
SC_SHOW_STABLE = (1 << 10),
SC_MANUAL_CALIBRATION = (1 << 11),
- SC_SHOW_GPENCIL = (1 << 12),
+ SC_SHOW_ANNOTATION = (1 << 12),
SC_SHOW_FILTERS = (1 << 13),
SC_SHOW_GRAPH_FRAMES = (1 << 14),
SC_SHOW_GRAPH_TRACKS_MOTION = (1 << 15),
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index cdfcf5598e8..cb2c69e2fa1 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -651,7 +651,9 @@ typedef struct UserDef {
struct WalkNavigation walk_navigation;
short opensubdiv_compute_type;
- char pad5[6];
+ short gpencil_multisamples; /* eMultiSample_Type, amount of samples for Grease Pencil */
+
+ char pad5[4];
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@@ -862,7 +864,8 @@ typedef enum eOpenGL_AntiAliasMethod {
/* text draw options
* UserDef.text_render */
typedef enum eText_Draw_Options {
- USER_TEXT_DISABLE_AA = (1 << 0),
+ USER_TEXT_DISABLE_AA = (1 << 0),
+ USER_TEXT_DISABLE_HINTING = (1 << 1),
} eText_Draw_Options;
/* tw_flag (transform widget) */
@@ -957,7 +960,7 @@ typedef enum eNdof_Flag {
#define NDOF_PIXELS_PER_SECOND 600.0f
-/* UserDef.ogl_multisamples */
+/* UserDef.ogl_multisamples and gpencil_multisamples */
typedef enum eMultiSample_Type {
USER_MULTISAMPLE_NONE = 0,
USER_MULTISAMPLE_2 = 2,
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 40551701627..317cde9009d 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -135,11 +135,16 @@ typedef struct View3DCursor {
/* 3D Viewport Shading setings */
typedef struct View3DShading {
+ short type; /* Shading type (VIEW3D_SHADE_SOLID, ..) */
+ short prev_type; /* Runtime, for toggle between rendered viewport. */
+
short flag;
short color_type;
short light;
- char pad[2];
+ short background_type;
+ short pad2[2];
+
char studio_light[256]; /* FILE_MAXFILE */
char matcap[256]; /* FILE_MAXFILE */
@@ -154,6 +159,10 @@ typedef struct View3DShading {
float cavity_valley_factor;
float cavity_ridge_factor;
+
+ float background_color[3];
+ int pad;
+
} View3DShading;
/* 3D Viewport Overlay setings */
@@ -181,6 +190,14 @@ typedef struct View3DOverlay {
float wireframe_threshold;
char _pad0[4];
+ /* grease pencil setttings */
+ float gpencil_grid_scale;
+ float gpencil_paper_opacity;
+ int gpencil_grid_lines;
+ int gpencil_grid_axis;
+ float gpencil_grid_opacity;
+ char _pad1[4];
+
} View3DOverlay;
/* 3D ViewPort Struct */
@@ -219,8 +236,10 @@ typedef struct View3D {
int layact;
short ob_centre_cursor; /* optional bool for 3d cursor to define center */
- short scenelock, _pad1;
- short flag, flag2, pad2;
+ short scenelock;
+ short gp_flag;
+ short flag;
+ int flag2;
float lens, grid;
float near, far;
@@ -237,17 +256,18 @@ typedef struct View3D {
char gridflag;
/* transform gizmo info */
- char _pad5[2], mpr_flag;
+ char _pad5[2], gizmo_flag;
- short flag3;
+ short _pad2;
/* drawflags, denoting state */
- char _pad2;
+ char _pad3;
char transp, xray;
char multiview_eye; /* multiview current eye - for internal use */
- char pad3[4];
+ /* actually only used to define the opacity of the grease pencil vertex in edit mode */
+ float vertex_opacity;
/* note, 'fx_settings.dof' is currently _not_ allocated,
* instead set (temporarily) from camera */
@@ -267,9 +287,8 @@ typedef struct View3D {
float stereo3d_convergence_alpha;
/* Display settings */
- short drawtype; /* Shading mode (OB_SOLID, OB_TEXTURE, ..) */
- short prev_drawtype; /* Runtime, for toggle between rendered viewport. */
- int pad5;
+ short drawtype DNA_DEPRECATED;
+ short pad5[3];
View3DShading shading;
View3DOverlay overlay;
@@ -329,10 +348,10 @@ typedef struct View3D {
#define RV3D_VIEW_IS_AXIS(view) \
(((view) >= RV3D_VIEW_FRONT) && ((view) <= RV3D_VIEW_BOTTOM))
-/* View3d->flag2 (short) */
+/* View3d->flag2 (int) */
#define V3D_RENDER_OVERRIDE (1 << 2)
#define V3D_SOLID_TEX (1 << 3)
-#define V3D_SHOW_GPENCIL (1 << 4)
+#define V3D_SHOW_ANNOTATION (1 << 4)
#define V3D_LOCK_CAMERA (1 << 5)
#define V3D_RENDER_SHADOW (1 << 6) /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */
#define V3D_SHOW_RECONSTRUCTION (1 << 7)
@@ -345,9 +364,12 @@ typedef struct View3D {
#define V3D_OCCLUDE_WIRE (1 << 14)
#define V3D_SHOW_MODE_SHADE_OVERRIDE (1 << 15) /* XXX: DNA deprecated */
-
-/* View3d->flag3 (short) */
-#define V3D_SHOW_WORLD (1 << 0)
+/* View3d->gp_flag (short) */
+#define V3D_GP_SHOW_PAPER (1 << 0) /* Activate paper to cover all viewport */
+#define V3D_GP_SHOW_GRID (1 << 1) /* Activate paper grid */
+#define V3D_GP_SHOW_EDIT_LINES (1 << 2)
+#define V3D_GP_SHOW_MULTIEDIT_LINES (1 << 3)
+#define V3D_GP_SHOW_ONION_SKIN (1 << 4) /* main switch at view level */
/* View3DShading->light */
enum {
@@ -376,6 +398,13 @@ enum {
V3D_SHADING_TEXTURE_COLOR = 3,
};
+/* View3DShading->background_type */
+enum {
+ V3D_SHADING_BACKGROUND_THEME = 0,
+ V3D_SHADING_BACKGROUND_WORLD = 1,
+ V3D_SHADING_BACKGROUND_VIEWPORT = 2,
+};
+
/* View3DOverlay->flag */
enum {
V3D_OVERLAY_FACE_ORIENTATION = (1 << 0),
@@ -467,4 +496,12 @@ enum {
#define RV3D_CAMZOOM_MIN_FACTOR 0.1657359312880714853f
#define RV3D_CAMZOOM_MAX_FACTOR 44.9852813742385702928f
+/* View3d.gpencil_grid_axis */
+enum {
+ V3D_GP_GRID_AXIS_LOCK = (1 << 0),
+ V3D_GP_GRID_AXIS_X = (1 << 1),
+ V3D_GP_GRID_AXIS_Y = (1 << 2),
+ V3D_GP_GRID_AXIS_Z = (1 << 3),
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 80ad3840a8f..25d9e50ff7a 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -184,7 +184,7 @@ typedef struct wmWindow {
struct wmWindow *next, *prev;
void *ghostwin; /* don't want to include ghost.h stuff */
- void *gwnctx; /* don't want to include gawin stuff */
+ void *gpuctx; /* don't want to include gpu stuff */
struct wmWindow *parent; /* Parent window */
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 61fa70e6e2a..14d42662cfc 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -113,6 +113,8 @@ static const char *includefiles[] = {
"DNA_particle_types.h",
"DNA_cloth_types.h",
"DNA_gpencil_types.h",
+ "DNA_gpencil_modifier_types.h",
+ "DNA_shader_fx_types.h",
"DNA_windowmanager_types.h",
"DNA_anim_types.h",
"DNA_boid_types.h",
@@ -1338,6 +1340,8 @@ int main(int argc, char **argv)
#include "DNA_particle_types.h"
#include "DNA_cloth_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_shader_fx_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_anim_types.h"
#include "DNA_boid_types.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 8434202d99b..9001e21c76e 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -269,9 +269,6 @@ extern StructRNA RNA_FreestyleSettings;
extern StructRNA RNA_Function;
extern StructRNA RNA_GPencilFrame;
extern StructRNA RNA_GPencilLayer;
-extern StructRNA RNA_GPencilPalette;
-extern StructRNA RNA_GPencilPaletteColor;
-extern StructRNA RNA_GPencilBrush;
extern StructRNA RNA_GPencilInterpolateSettings;
extern StructRNA RNA_GPencilStroke;
extern StructRNA RNA_GPencilStrokePoint;
@@ -603,6 +600,31 @@ extern StructRNA RNA_SunLight;
extern StructRNA RNA_SurfaceCurve;
extern StructRNA RNA_SurfaceDeformModifier;
extern StructRNA RNA_SurfaceModifier;
+extern StructRNA RNA_GpencilModifier;
+extern StructRNA RNA_BuildGpencilModifier;
+extern StructRNA RNA_NoiseGpencilModifier;
+extern StructRNA RNA_SubdivGpencilModifier;
+extern StructRNA RNA_SimplifyGpencilModifier;
+extern StructRNA RNA_ThickGpencilModifier;
+extern StructRNA RNA_TintGpencilModifier;
+extern StructRNA RNA_ColorGpencilModifier;
+extern StructRNA RNA_InstanceGpencilModifier;
+extern StructRNA RNA_DupliGpencilModifier;
+extern StructRNA RNA_OpacityGpencilModifier;
+extern StructRNA RNA_LatticeGpencilModifier;
+extern StructRNA RNA_MirrorGpencilModifier;
+extern StructRNA RNA_SmoothGpencilModifier;
+extern StructRNA RNA_HookGpencilModifier;
+extern StructRNA RNA_OffsetGpencilModifier;
+extern StructRNA RNA_ShaderFx;
+extern StructRNA RNA_ShaderFxBlur;
+extern StructRNA RNA_ShaderFxColorize;
+extern StructRNA RNA_ShaderFxFlip;
+extern StructRNA RNA_ShaderFxLight;
+extern StructRNA RNA_ShaderFxPixel;
+extern StructRNA RNA_ShaderFxRim;
+extern StructRNA RNA_ShaderFxSwirl;
+extern StructRNA RNA_ShaderFxWave;
extern StructRNA RNA_TexMapping;
extern StructRNA RNA_Text;
extern StructRNA RNA_TextBox;
@@ -696,6 +718,7 @@ extern StructRNA RNA_WaveModifier;
extern StructRNA RNA_VertexWeightEditModifier;
extern StructRNA RNA_VertexWeightMixModifier;
extern StructRNA RNA_VertexWeightProximityModifier;
+extern StructRNA RNA_WeightedNormalModifier;
extern StructRNA RNA_View3DOverlay;
extern StructRNA RNA_View3DShading;
extern StructRNA RNA_ViewLayer;
@@ -803,7 +826,7 @@ bool RNA_struct_bl_idname_ok_or_report(struct ReportList *reports, const char *i
/* Property Information */
-const char *RNA_property_identifier(PropertyRNA *prop);
+const char *RNA_property_identifier(const PropertyRNA *prop);
const char *RNA_property_description(PropertyRNA *prop);
PropertyType RNA_property_type(PropertyRNA *prop);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index bafb2bf5753..9efa8475f8e 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -44,6 +44,7 @@ extern const EnumPropertyItem rna_enum_id_type_items[];
extern const EnumPropertyItem rna_enum_object_mode_items[];
extern const EnumPropertyItem rna_enum_object_empty_drawtype_items[];
+extern const EnumPropertyItem rna_enum_object_gpencil_type_items[];
extern const EnumPropertyItem rna_enum_metaelem_type_items[];
extern const EnumPropertyItem rna_enum_proportional_falloff_items[];
@@ -54,6 +55,7 @@ extern const EnumPropertyItem rna_enum_snap_element_items[];
extern const EnumPropertyItem rna_enum_snap_node_element_items[];
extern const EnumPropertyItem rna_enum_curve_fit_method_items[];
extern const EnumPropertyItem rna_enum_mesh_select_mode_items[];
+extern const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[];
extern const EnumPropertyItem rna_enum_mesh_delimit_mode_items[];
extern const EnumPropertyItem rna_enum_space_graph_mode_items[];
extern const EnumPropertyItem rna_enum_space_type_items[];
@@ -64,6 +66,8 @@ extern const EnumPropertyItem rna_enum_object_modifier_type_items[];
extern const EnumPropertyItem rna_enum_constraint_type_items[];
extern const EnumPropertyItem rna_enum_boidrule_type_items[];
extern const EnumPropertyItem rna_enum_sequence_modifier_type_items[];
+extern const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[];
+extern const EnumPropertyItem rna_enum_object_shaderfx_type_items[];
extern const EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[];
extern const EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[];
@@ -116,6 +120,8 @@ extern const EnumPropertyItem rna_enum_brush_sculpt_tool_items[];
extern const EnumPropertyItem rna_enum_brush_vertex_tool_items[];
extern const EnumPropertyItem rna_enum_brush_image_tool_items[];
+extern const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[];
+extern const EnumPropertyItem rna_enum_particle_edit_disconnected_hair_brush_items[];
extern const EnumPropertyItem rna_enum_gpencil_sculpt_brush_items[];
extern const EnumPropertyItem rna_enum_uv_sculpt_tool_items[];
@@ -227,6 +233,7 @@ const EnumPropertyItem *rna_node_socket_type_itemf(
struct bContext;
struct PointerRNA;
struct PropertyRNA;
+
const EnumPropertyItem *rna_TransformOrientation_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *rna_Sensor_type_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *rna_Actuator_type_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0baa96e0e61..bd603868278 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -49,6 +49,8 @@ set(DEFSRC
rna_fcurve.c
rna_fluidsim.c
rna_gpencil.c
+ rna_gpencil_modifier.c
+ rna_shader_fx.c
rna_group.c
rna_hair.c
rna_image.c
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 579a40910eb..f63ba0729e3 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3418,6 +3418,8 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_mesh_sample.c", NULL, RNA_def_mesh_sample},
{"rna_meta.c", "rna_meta_api.c", RNA_def_meta},
{"rna_modifier.c", NULL, RNA_def_modifier},
+ {"rna_gpencil_modifier.c", NULL, RNA_def_greasepencil_modifier},
+ {"rna_shader_fx.c", NULL, RNA_def_shader_fx },
{"rna_nla.c", NULL, RNA_def_nla},
{"rna_nodetree.c", NULL, RNA_def_nodetree},
{"rna_object.c", "rna_object_api.c", RNA_def_object},
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 7228f4a4683..a0c34afa7ed 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -975,7 +975,7 @@ bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifi
/* Property Information */
-const char *RNA_property_identifier(PropertyRNA *prop)
+const char *RNA_property_identifier(const PropertyRNA *prop)
{
return rna_ensure_property_identifier(prop);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 4f1e29b482d..0f3e74c567f 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -31,6 +31,8 @@
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_workspace_types.h"
+#include "DNA_gpencil_types.h"
#include "BLI_math.h"
@@ -122,6 +124,44 @@ const EnumPropertyItem rna_enum_brush_image_tool_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_gpencil_brush_types_items[] = {
+ { GP_BRUSH_TYPE_DRAW, "DRAW", ICON_GREASEPENCIL_STROKE_PAINT, "Draw", "The brush is of type used for drawing strokes" },
+ { GP_BRUSH_TYPE_FILL, "FILL", ICON_COLOR, "Fill", "The brush is of type used for filling areas" },
+ { GP_BRUSH_TYPE_ERASE, "ERASE", ICON_PANEL_CLOSE, "Erase", "The brush is used for erasing strokes" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
+ { GP_BRUSH_ERASER_SOFT, "SOFT", 0, "Soft", "Use soft eraser" },
+ { GP_BRUSH_ERASER_HARD, "HARD", 0, "Hard", "Use hard eraser" },
+ { GP_BRUSH_ERASER_STROKE, "STROKE", 0, "Stroke", "Use stroke eraser" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static EnumPropertyItem rna_enum_gpencil_fill_draw_modes_items[] = {
+ { GP_FILL_DMODE_STROKE, "STROKE", 0, "Strokes", "Use visible strokes as fill boundary limits" },
+ { GP_FILL_DMODE_CONTROL, "CONTROL", 0, "Control", "Use internal control lines as fill boundary limits" },
+ { GP_FILL_DMODE_BOTH, "BOTH", 0, "Both", "Use visible strokes and control lines as fill boundary limits" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static EnumPropertyItem rna_enum_gpencil_brush_icons_items[] = {
+ { GP_BRUSH_ICON_PENCIL, "PENCIL", ICON_GPBRUSH_PENCIL, "Pencil", "" },
+ { GP_BRUSH_ICON_PEN, "PEN", ICON_GPBRUSH_PEN, "Pen", "" },
+ { GP_BRUSH_ICON_INK, "INK", ICON_GPBRUSH_INK, "Ink", "" },
+ { GP_BRUSH_ICON_INKNOISE, "INKNOISE", ICON_GPBRUSH_INKNOISE, "Ink Noise", "" },
+ { GP_BRUSH_ICON_BLOCK, "BLOCK", ICON_GPBRUSH_BLOCK, "Block", "" },
+ { GP_BRUSH_ICON_MARKER, "MARKER", ICON_GPBRUSH_MARKER, "Marker", "" },
+ { GP_BRUSH_ICON_FILL, "FILL", ICON_GPBRUSH_FILL, "Fill", "" },
+ { GP_BRUSH_ICON_ERASE_SOFT, "SOFT", ICON_GPBRUSH_ERASE_SOFT, "Eraser Soft", "" },
+ { GP_BRUSH_ICON_ERASE_HARD, "HARD", ICON_GPBRUSH_ERASE_HARD, "Eraser Hard", "" },
+ { GP_BRUSH_ICON_ERASE_STROKE, "STROKE", ICON_GPBRUSH_ERASE_STROKE, "Eraser Stroke", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+#endif
+
+
#ifdef RNA_RUNTIME
#include "MEM_guardedalloc.h"
@@ -442,6 +482,33 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
+static const EnumPropertyItem *rna_DynamicGpencil_type_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ Main *bmain = CTX_data_main(C);
+ EnumPropertyItem *item = NULL, item_tmp = { 0 };
+ int totitem = 0;
+ int i = 0;
+
+ Brush *brush;
+ for (brush = bmain->brush.first; brush; brush = brush->id.next, i++) {
+ if (brush->gpencil_settings == NULL)
+ continue;
+
+ item_tmp.identifier = brush->id.name + 2;
+ item_tmp.name = brush->id.name + 2;
+ item_tmp.value = i;
+ item_tmp.icon = brush->gpencil_settings->icon_id;
+
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
static void rna_TextureSlot_brush_angle_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -615,6 +682,58 @@ static const EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *U
return brush_stroke_method_items;
}
}
+
+/* Grease Pencil Drawing Brushes Settings */
+static void rna_BrushGpencilSettings_default_eraser_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ ToolSettings *ts = scene->toolsettings;
+ Paint *paint = &ts->gp_paint->paint;
+ Brush *brush_cur = paint->brush;
+
+ /* disable default eraser in all brushes */
+ for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if ((brush != brush_cur) &&
+ (brush->ob_mode == OB_MODE_GPENCIL_PAINT) &&
+ (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE))
+ {
+ brush->gpencil_settings->flag &= ~GP_BRUSH_DEFAULT_ERASER;
+ }
+ }
+}
+
+static void rna_BrushGpencilSettings_eraser_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ ToolSettings *ts = scene->toolsettings;
+ Paint *paint = &ts->gp_paint->paint;
+ Brush *brush = paint->brush;
+
+ /* set eraser icon */
+ if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) {
+ switch (brush->gpencil_settings->eraser_mode) {
+ case GP_BRUSH_ERASER_SOFT:
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
+ break;
+ case GP_BRUSH_ERASER_HARD:
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
+ break;
+ case GP_BRUSH_ERASER_STROKE:
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
+ break;
+ default:
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
+ break;
+ }
+ }
+}
+
+static bool rna_BrushGpencilSettings_material_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
+{
+ Material *ma = (Material *)value.data;
+
+ /* GP materials only */
+ return (ma->gp_style != NULL);
+}
+
#else
static void rna_def_brush_texture_slot(BlenderRNA *brna)
@@ -809,6 +928,316 @@ static void rna_def_image_paint_capabilities(BlenderRNA *brna)
#undef IMAPAINT_TOOL_CAPABILITY
}
+static void rna_def_gpencil_options(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* Grease Pencil Drawing - generated dynamically */
+ static const EnumPropertyItem prop_dynamic_gpencil_type[] = {
+ { 1, "DRAW", 0, "Draw", "" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ srna = RNA_def_struct(brna, "BrushGpencilSettings", NULL);
+ RNA_def_struct_sdna(srna, "BrushGpencilSettings");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Brush Settings", "Settings for grease pencil brush");
+
+ /* grease pencil drawing brushes */
+ prop = RNA_def_property(srna, "grease_pencil_tool", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "brush_type");
+ RNA_def_property_enum_items(prop, prop_dynamic_gpencil_type);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DynamicGpencil_type_itemf");
+ RNA_def_property_ui_text(prop, "Grease Pencil Tool", "");
+ /* TODO: GPXX review update */
+ RNA_def_property_update(prop, 0, NULL);
+ //RNA_def_property_update(prop, 0, "rna_Brush_gpencil_tool_update");
+
+ /* Sensitivity factor for new strokes */
+ prop = RNA_def_property(srna, "pen_sensitivity_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_sensitivity");
+ RNA_def_property_range(prop, 0.1f, 3.0f);
+ RNA_def_property_ui_text(prop, "Sensitivity", "Pressure sensitivity factor for new strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Strength factor for new strokes */
+ prop = RNA_def_property(srna, "pen_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_strength");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Strength", "Color strength for new strokes (affect alpha factor of color)");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Jitter factor for new strokes */
+ prop = RNA_def_property(srna, "pen_jitter", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_jitter");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Jitter", "Jitter factor for new strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Randomnes factor for pressure */
+ prop = RNA_def_property(srna, "random_pressure", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_random_press");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Pressure Randomness", "Randomness factor for pressure in new strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Randomnes factor for strength */
+ prop = RNA_def_property(srna, "random_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_random_strength");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Strength Randomness", "Randomness factor strength in new strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Randomnes factor for subdivision */
+ prop = RNA_def_property(srna, "random_subdiv", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_random_sub");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Random Subdivision", "Randomness factor for new strokes after subdivision");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Angle when brush is full size */
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_angle");
+ RNA_def_property_range(prop, -M_PI_2, M_PI_2);
+ RNA_def_property_ui_text(prop, "Angle",
+ "Direction of the stroke at which brush gives maximal thickness "
+ "(0° for horizontal)");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Factor to change brush size depending of angle */
+ prop = RNA_def_property(srna, "angle_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_angle_factor");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Angle Factor",
+ "Reduce brush thickness by this factor when stroke is perpendicular to 'Angle' direction");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Smoothing factor for new strokes */
+ prop = RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "draw_smoothfac");
+ RNA_def_property_range(prop, 0.0, 2.0f);
+ RNA_def_property_ui_text(prop, "Smooth",
+ "Amount of smoothing to apply after finish newly created strokes, to reduce jitter/noise");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Iterations of the Smoothing factor */
+ prop = RNA_def_property(srna, "pen_smooth_steps", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "draw_smoothlvl");
+ RNA_def_property_range(prop, 1, 3);
+ RNA_def_property_ui_text(prop, "Iterations",
+ "Number of times to smooth newly created strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Thickness smoothing factor for new strokes */
+ prop = RNA_def_property(srna, "pen_thick_smooth_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "thick_smoothfac");
+ RNA_def_property_range(prop, 0.0, 2.0f);
+ RNA_def_property_ui_text(prop, "Smooth Thickness",
+ "Amount of thickness smoothing to apply after finish newly created strokes, to reduce jitter/noise");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Thickness iterations of the Smoothing factor */
+ prop = RNA_def_property(srna, "pen_thick_smooth_steps", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "thick_smoothlvl");
+ RNA_def_property_range(prop, 1, 3);
+ RNA_def_property_ui_text(prop, "Iterations Thickness",
+ "Number of times to smooth thickness for newly created strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Subdivision level for new strokes */
+ prop = RNA_def_property(srna, "pen_subdivision_steps", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "draw_subdivide");
+ RNA_def_property_range(prop, 0, 3);
+ RNA_def_property_ui_text(prop, "Subdivision Steps",
+ "Number of times to subdivide newly created strokes, for less jagged strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Curves for pressure */
+ prop = RNA_def_property(srna, "curve_sensitivity", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_sensitivity");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "curve_strength", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_strength");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve Strength", "Curve used for the strength");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "curve_jitter", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_jitter");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve Jitter", "Curve used for the jitter effect");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* fill threshold for transparence */
+ prop = RNA_def_property(srna, "gpencil_fill_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "fill_threshold");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Threshold",
+ "Threshold to consider color transparent for filling");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* fill leak size */
+ prop = RNA_def_property(srna, "gpencil_fill_leak", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "fill_leak");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Leak Size",
+ "Size in pixels to consider the leak closed");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* fill simplify steps */
+ prop = RNA_def_property(srna, "gpencil_fill_simplyfy_level", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "fill_simplylvl");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_text(prop, "Simplify",
+ "Number of simplify steps (large values reduce fill accuracy)");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "uv_random", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_random");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "UV Random", "Random factor for autogenerated UV rotation");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "input_samples");
+ RNA_def_property_range(prop, 0, GP_MAX_INPUT_SAMPLES);
+ RNA_def_property_ui_text(prop, "Input Samples", "Generate intermediate points for very fast mouse movements. Set to 0 to disable");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* active smooth factor while drawing */
+ prop = RNA_def_property(srna, "active_smooth_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "active_smooth");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Active Smooth",
+ "Amount of smoothing while drawing ");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* brush standard icon */
+ prop = RNA_def_property(srna, "gp_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "icon_id");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_icons_items);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_ui_text(prop, "Grease Pencil Icon", "");
+
+ /* Flags */
+ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure", "Use tablet pressure");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "use_strength_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_STENGTH_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure Strength", "Use tablet pressure for color strength");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "use_jitter_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_JITTER_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure Jitter", "Use tablet pressure for jitter");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "use_stabilizer", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_STABILIZE_MOUSE);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Stabilizer",
+ "Draw lines with a delay to allow smooth strokes. Press Shift key to override while drawing");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "use_cursor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_ENABLE_CURSOR);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Enable Cursor", "Enable cursor on screen");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "gpencil_brush_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "brush_type");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_types_items);
+ RNA_def_property_ui_text(prop, "Type", "Category of the brush");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "eraser_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "eraser_mode");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_eraser_modes_items);
+ RNA_def_property_ui_text(prop, "Mode", "Eraser Mode");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_eraser_mode_update");
+
+ prop = RNA_def_property(srna, "gpencil_fill_draw_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "fill_draw_mode");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_draw_modes_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode to draw boundary limits");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ /* Material */
+ prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Material");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_BrushGpencilSettings_material_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_ui_text(prop, "Material", "Material used for strokes drawn using this brush");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ prop = RNA_def_property(srna, "gpencil_fill_show_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_FILL_SHOW_HELPLINES);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Show Lines", "Show help lines for filling to see boundaries");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "gpencil_fill_hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_FILL_HIDE);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Hide", "Hide transparent lines to use as boundary for filling");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "default_eraser", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_DEFAULT_ERASER);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1);
+ RNA_def_property_ui_text(prop, "Default Eraser", "Use this brush when enable eraser with fast switch key");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_default_eraser_update");
+
+ prop = RNA_def_property(srna, "enable_settings", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_GROUP_SETTINGS);
+ RNA_def_property_ui_text(prop, "Settings", "Enable additional post processing options for new strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "enable_random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_GROUP_RANDOM);
+ RNA_def_property_ui_text(prop, "Random Settings", "Enable random settings for brush");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+}
+
static void rna_def_brush(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1373,6 +1802,10 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_TEXTURE_PAINT);
RNA_def_property_ui_text(prop, "Use Texture", "Use this brush in texture paint mode");
+ prop = RNA_def_property(srna, "use_paint_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_GPENCIL_PAINT);
+ RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in grease pencil drawing mode");
+
/* texture */
prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BrushTextureSlot");
@@ -1475,6 +1908,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ImapaintToolCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Imapaint_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Image Painting Capabilities", "Brush's capabilities in image paint mode");
+
+ prop = RNA_def_property(srna, "gpencil_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "BrushGpencilSettings");
+ RNA_def_property_pointer_sdna(prop, NULL, "gpencil_settings");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Gpencil Settings", "");
+
}
@@ -1543,6 +1983,7 @@ void RNA_def_brush(BlenderRNA *brna)
rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
rna_def_image_paint_capabilities(brna);
+ rna_def_gpencil_options(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);
}
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 146a8e2738d..8ca45e6dd2d 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -428,6 +428,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "passepartalpha");
+ RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_ui_text(prop, "Passepartout Alpha", "Opacity (alpha) of the darkened overlay in Camera view");
RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
@@ -454,6 +455,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipsta");
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip Start", "Camera near clipping distance");
@@ -461,6 +463,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipend");
+ RNA_def_property_float_default(prop, 1000.0f);
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip End", "Camera far clipping distance");
@@ -468,6 +471,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "lens");
+ RNA_def_property_float_default(prop, 50.0f);
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters");
@@ -475,6 +479,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "sensor_x");
+ RNA_def_property_float_default(prop, 36.0f);
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2);
RNA_def_property_ui_text(prop, "Sensor Width", "Horizontal size of the image sensor area in millimeters");
@@ -482,6 +487,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "sensor_y");
+ RNA_def_property_float_default(prop, 34.0f);
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2);
RNA_def_property_ui_text(prop, "Sensor Height", "Vertical size of the image sensor area in millimeters");
@@ -489,6 +495,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "ortho_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "ortho_scale");
+ RNA_def_property_float_default(prop, 6.0f);
RNA_def_property_range(prop, FLT_MIN, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, 10000.0f, 10, 3);
RNA_def_property_ui_text(prop, "Orthographic Scale", "Orthographic Camera scale (similar to zoom)");
@@ -496,6 +503,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "draw_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "drawsize");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.01f, 1000.0f);
RNA_def_property_ui_range(prop, 0.01, 100, 1, 2);
RNA_def_property_ui_text(prop, "Draw Size", "Apparent size of the Camera object in the 3D View");
@@ -542,6 +550,7 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_passepartout", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWPASSEPARTOUT);
+ RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Show Passepartout",
"Show a darkened overlay outside the image area in Camera view");
RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 7b07faf8ee7..618cefe13e5 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -34,6 +34,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h" /* own include */
@@ -52,6 +53,10 @@ const EnumPropertyItem rna_enum_context_mode_items[] = {
{CTX_MODE_PAINT_TEXTURE, "PAINT_TEXTURE", 0, "Texture Paint", ""},
{CTX_MODE_PARTICLE, "PARTICLE", 0, "Particle", ""},
{CTX_MODE_OBJECT, "OBJECT", 0, "Object", ""},
+ {CTX_MODE_GPENCIL_PAINT, "GPENCIL_PAINT", 0, "Grease Pencil Paint", "" },
+ {CTX_MODE_GPENCIL_EDIT, "GPENCIL_EDIT", 0, "Grease Pencil Edit", "" },
+ {CTX_MODE_GPENCIL_SCULPT, "GPENCIL_SCULPT", 0, "Grease Pencil Sculpt", "" },
+ {CTX_MODE_GPENCIL_WEIGHT, "GPENCIL_WEIGHT", 0, "Grease Pencil Weight Paint", "" },
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index c84ce56c58b..4964e94652c 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -2282,7 +2282,7 @@ void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func)
void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func)
{
if (prop->type == PROP_POINTER) {
- ((PointerPropertyRNA *)prop)->poll = func;
+ ((PointerPropertyRNA *)prop)->poll = (void *)func;
}
else {
fprintf(stderr, "%s: %s is not a Pointer Property.\n", __func__, prop->identifier);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index d9dba4679e0..c4aa90fb61b 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -26,8 +26,13 @@
#include <stdlib.h>
+#include "BLI_math.h"
+
+#include "DNA_meshdata_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -38,12 +43,11 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
#include "WM_types.h"
-#include "DNA_object_types.h"
-#include "ED_gpencil.h"
/* parent type */
static const EnumPropertyItem parent_type_items[] = {
@@ -53,31 +57,53 @@ static const EnumPropertyItem parent_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_gpencil_xraymodes_items[] = {
+ { GP_XRAY_FRONT, "FRONT", 0, "Front", "Draw all strokes in front" },
+ { GP_XRAY_3DSPACE, "3DSPACE", 0, "3DSpace", "Draw strokes relative to other objects in 3D space" },
+ { GP_XRAY_BACK, "BACK", 0, "Back", "Draw all strokes on back" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static EnumPropertyItem rna_enum_gpencil_onion_modes_items[] = {
+ { GP_ONION_MODE_ABSOLUTE, "ABSOLUTE", 0, "Frames", "Frames in absolute range of scene frame number" },
+ { GP_ONION_MODE_RELATIVE, "RELATIVE", 0, "Keyframes", "Frames in relative range of grease pencil keyframes" },
+ { GP_ONION_MODE_SELECTED, "SELECTED", 0, "Selected", "Only Selected Frames" },
+ { 0, NULL, 0, NULL, NULL }
+};
+#endif
#ifdef RNA_RUNTIME
-#include "BLI_math.h"
+#include "BLI_ghash.h"
#include "WM_api.h"
+#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_gpencil.h"
-#include "BKE_action.h"
+#include "BKE_icons.h"
+
+#include "DEG_depsgraph.h"
-static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
-static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+
/* Notify all places where GPencil data lives that the editing state is different */
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
WM_main_add_notifier(NC_SCENE | ND_MODE | NC_MOVIECLIP, NULL);
}
-static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void UNUSED_FUNCTION(rna_GPencil_onion_skinning_update)(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bGPdata *gpd = (bGPdata *)ptr->id.data;
bGPDlayer *gpl;
@@ -87,7 +113,7 @@ static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, Pointer
* stays in sync with the status of the actual layers
*/
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->flag & GP_LAYER_ONIONSKIN) {
+ if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
enabled = true;
}
}
@@ -102,16 +128,22 @@ static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, Pointer
rna_GPencil_update(bmain, scene, ptr);
}
-static void rna_GPencil_stroke_colorname_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+
+/* Poll Callback to filter GP Datablocks to only show those for Annotations */
+bool rna_GPencil_datablocks_annotations_poll(PointerRNA *UNUSED(ptr), const PointerRNA value)
{
- bGPDstroke *gps = (bGPDstroke *)ptr->data;
- gps->flag |= GP_STROKE_RECALC_COLOR;
- gps->palcolor = NULL;
+ bGPdata *gpd = value.data;
+ return (gpd->flag & GP_DATA_ANNOTATIONS) != 0;
+}
- /* Now do standard updates... */
- rna_GPencil_update(bmain, scene, ptr);
+/* Poll Callback to filter GP Datablocks to only show those for GP Objects */
+bool rna_GPencil_datablocks_obdata_poll(PointerRNA *UNUSED(ptr), const PointerRNA value)
+{
+ bGPdata *gpd = value.data;
+ return (gpd->flag & GP_DATA_ANNOTATIONS) == 0;
}
+
static char *rna_GPencilLayer_path(PointerRNA *ptr)
{
bGPDlayer *gpl = (bGPDlayer *)ptr->data;
@@ -133,36 +165,6 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr, const char **
return PROP_EDITABLE;
}
-static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *max,
- int *softmin, int *softmax)
-{
- bGPDlayer *gpl = ptr->data;
-
- /* The restrictions on max width here are due to OpenGL on Windows not supporting
- * any widths greater than 10 (for driver-drawn) strokes/points.
- *
- * Although most of our 2D strokes also don't suffer from this restriction,
- * it's relatively hard to test for that. So, for now, only volumetric strokes
- * get to be larger...
- */
-
- /* From GP v2 this value is used to increase or decrease the thickness of the stroke */
- if (gpl->flag & GP_LAYER_VOLUMETRIC) {
- *min = -300;
- *max = 300;
-
- *softmin = -100;
- *softmax = 100;
- }
- else {
- *min = -10;
- *max = 10;
-
- *softmin = -10;
- *softmax = 10;
- }
-}
-
/* set parent */
static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *substr)
{
@@ -202,21 +204,6 @@ static void rna_GPencilLayer_parent_set(PointerRNA *ptr, PointerRNA value)
set_parent(gpl, par, gpl->partype, gpl->parsubstr);
}
else {
- /* keep strokes in the same place, so apply current transformation */
- if (gpl->parent != NULL) {
- bGPDspoint *pt;
- int i;
- float diff_mat[4][4];
- /* calculate difference matrix */
- ED_gpencil_parent_location(gpl, diff_mat);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- mul_m4_v3(diff_mat, &pt->x);
- }
- }
- }
- }
/* clear parent */
gpl->parent = NULL;
}
@@ -306,6 +293,15 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value)
{
bGPdata *gpd = ptr->id.data;
+ /* Don't allow setting active layer to NULL if layers exist
+ * as this breaks various tools. Tools should be used instead
+ * if it's necessary to remove layers
+ */
+ if (value.data == NULL) {
+ printf("%s: Setting active layer to None is not allowed\n", __func__);
+ return;
+ }
+
if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
bGPDlayer *gl;
@@ -349,6 +345,36 @@ static void rna_GPencil_active_layer_index_range(PointerRNA *ptr, int *min, int
*softmax = *max;
}
+static const EnumPropertyItem *rna_GPencil_active_layer_itemf(
+ bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPDlayer *gpl;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (ELEM(NULL, C, gpd)) {
+ return DummyRNA_NULL_items;
+ }
+
+ /* Existing layers */
+ for (gpl = gpd->layers.first, i = 0; gpl; gpl = gpl->next, i++) {
+ item_tmp.identifier = gpl->info;
+ item_tmp.name = gpl->info;
+ item_tmp.value = i;
+
+ item_tmp.icon = BKE_icon_gplayer_color_ensure(gpl);
+
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
{
bGPdata *gpd = ptr->id.data;
@@ -366,31 +392,6 @@ static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
BKE_animdata_fix_paths_rename_all(&gpd->id, "layers", oldname, gpl->info);
}
-static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const bool value)
-{
- bGPdata *gpd = ptr->id.data;
- bGPDlayer *gpl;
-
- /* set new value */
- if (value) {
- /* enable on active layer (it's the one that's most likely to be of interest right now) */
- gpl = BKE_gpencil_layer_getactive(gpd);
- if (gpl) {
- gpl->flag |= GP_LAYER_ONIONSKIN;
- }
-
- gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
- }
- else {
- /* disable on all layers - allowa quickly turning them all off, without having to check */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag &= ~GP_LAYER_ONIONSKIN;
- }
-
- gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS;
- }
-}
-
static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, const bGPDspoint *pt, bGPDlayer **r_gpl, bGPDframe **r_gpf)
{
bGPDlayer *gpl;
@@ -454,14 +455,21 @@ static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count, float pr
stroke->points = MEM_recallocN_id(stroke->points,
sizeof(bGPDspoint) * (stroke->totpoints + count),
"gp_stroke_points");
+ stroke->dvert = MEM_recallocN_id(stroke->dvert,
+ sizeof(MDeformVert) * (stroke->totpoints + count),
+ "gp_stroke_weight");
/* init the pressure and strength values so that old scripts won't need to
* be modified to give these initial values...
*/
for (int i = 0; i < count; i++) {
bGPDspoint *pt = stroke->points + (stroke->totpoints + i);
+ MDeformVert *dvert = stroke->dvert + (stroke->totpoints + i);
pt->pressure = pressure;
pt->strength = strength;
+
+ dvert->totweight = 0;
+ dvert->dw = NULL;
}
stroke->totpoints += count;
@@ -471,6 +479,7 @@ static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count, float pr
static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports, int index)
{
bGPDspoint *pt_tmp = stroke->points;
+ MDeformVert *pt_dvert = stroke->dvert;
/* python style negative indexing */
if (index < 0) {
@@ -485,27 +494,35 @@ static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports
stroke->totpoints--;
stroke->points = MEM_callocN(sizeof(bGPDspoint) * stroke->totpoints, "gp_stroke_points");
+ stroke->dvert = MEM_callocN(sizeof(MDeformVert) * stroke->totpoints, "gp_stroke_weights");
- if (index > 0)
+ if (index > 0) {
memcpy(stroke->points, pt_tmp, sizeof(bGPDspoint) * index);
+ /* verify weight data is available */
+ if (pt_dvert != NULL) {
+ memcpy(stroke->dvert, pt_dvert, sizeof(MDeformVert) * index);
+ }
+ }
- if (index < stroke->totpoints)
+ if (index < stroke->totpoints) {
memcpy(&stroke->points[index], &pt_tmp[index + 1], sizeof(bGPDspoint) * (stroke->totpoints - index));
+ if (pt_dvert != NULL) {
+ memcpy(&stroke->dvert[index], &pt_dvert[index + 1], sizeof(MDeformVert) * (stroke->totpoints - index));
+ }
+ }
/* free temp buffer */
MEM_freeN(pt_tmp);
+ if (pt_dvert != NULL) {
+ MEM_freeN(pt_dvert);
+ }
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
-static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame, const char *colorname)
+static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame)
{
bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
- if (colorname) {
- BLI_strncpy(stroke->colorname, colorname, sizeof(stroke->colorname));
- }
- stroke->palcolor = NULL;
- stroke->flag |= GP_STROKE_RECALC_COLOR;
BLI_addtail(&frame->strokes, stroke);
return stroke;
@@ -635,260 +652,18 @@ static void rna_GPencil_clear(bGPdata *gpd)
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-/* Palettes */
-static bGPDpalette *rna_GPencil_palette_new(bGPdata *gpd, const char *name, bool setactive)
-{
- bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, name, setactive != 0);
-
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return palette;
-}
-
-static void rna_GPencil_palette_remove(bGPdata *gpd, ReportList *reports, PointerRNA *palette_ptr)
-{
- bGPDpalette *palette = palette_ptr->data;
- if (BLI_findindex(&gpd->palettes, palette) == -1) {
- BKE_report(reports, RPT_ERROR, "Palette not found in grease pencil data");
- return;
- }
-
- BKE_gpencil_palette_delete(gpd, palette);
- RNA_POINTER_INVALIDATE(palette_ptr);
-
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-static PointerRNA rna_GPencil_active_palette_get(PointerRNA *ptr)
-{
- bGPdata *gpd = ptr->id.data;
-
- if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
- bGPDpalette *palette;
-
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
- if (palette->flag & PL_PALETTE_ACTIVE) {
- break;
- }
- }
-
- if (palette) {
- return rna_pointer_inherit_refine(ptr, &RNA_GPencilPalette, palette);
- }
- }
-
- return rna_pointer_inherit_refine(ptr, NULL, NULL);
-}
-
-static void rna_GPencil_active_palette_set(PointerRNA *ptr, PointerRNA value)
-{
- bGPdata *gpd = ptr->id.data;
-
- if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
- bGPDpalette *palette;
-
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
- if (palette == value.data) {
- palette->flag |= PL_PALETTE_ACTIVE;
- }
- else {
- palette->flag &= ~PL_PALETTE_ACTIVE;
- }
- }
- /* force color recalc */
- BKE_gpencil_palette_change_strokes(gpd);
-
- WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
- }
-}
-
-static int rna_GPencilPalette_index_get(PointerRNA *ptr)
-{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
-
- return BLI_findindex(&gpd->palettes, palette);
-}
-
-static void rna_GPencilPalette_index_set(PointerRNA *ptr, int value)
-{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
- bGPDpalette *palette = BLI_findlink(&gpd->palettes, value);
-
- BKE_gpencil_palette_setactive(gpd, palette);
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-static void rna_GPencilPalette_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
-{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
-
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&gpd->palettes) - 1);
-
- *softmin = *min;
- *softmax = *max;
-}
-
-/* Palette colors */
-static bGPDpalettecolor *rna_GPencilPalette_color_new(bGPDpalette *palette)
-{
- bGPDpalettecolor *color = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true);
-
- return color;
-}
-
-static void rna_GPencilPalette_color_remove(bGPDpalette *palette, ReportList *reports, PointerRNA *color_ptr)
-{
- bGPDpalettecolor *color = color_ptr->data;
-
- if (BLI_findindex(&palette->colors, color) == -1) {
- BKE_reportf(reports, RPT_ERROR, "Palette '%s' does not contain color given", palette->info + 2);
- return;
- }
-
- BKE_gpencil_palettecolor_delete(palette, color);
- RNA_POINTER_INVALIDATE(color_ptr);
-
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-static PointerRNA rna_GPencilPalette_active_color_get(PointerRNA *ptr)
-{
- bGPDpalette *palette = (bGPDpalette *)ptr->data;
- bGPDpalettecolor *color;
-
- for (color = palette->colors.first; color; color = color->next) {
- if (color->flag & PC_COLOR_ACTIVE) {
- break;
- }
- }
-
- if (color) {
- return rna_pointer_inherit_refine(ptr, &RNA_GPencilPaletteColor, color);
- }
-
- return rna_pointer_inherit_refine(ptr, NULL, NULL);
-}
-
-static void rna_GPencilPalette_active_color_set(PointerRNA *ptr, PointerRNA value)
-{
- bGPDpalette *palette = (bGPDpalette *)ptr->data;
- bGPDpalettecolor *color = value.data;
-
- BKE_gpencil_palettecolor_setactive(palette, color);
-}
-
-static void rna_GPencilPalette_info_set(PointerRNA *ptr, const char *value)
-{
- bGPdata *gpd = ptr->id.data;
- bGPDpalette *palette = ptr->data;
-
- char oldname[64] = "";
- BLI_strncpy(oldname, palette->info, sizeof(oldname));
-
- /* copy the new name into the name slot */
- BLI_strncpy_utf8(palette->info, value, sizeof(palette->info));
-
- BLI_uniquename(&gpd->palettes, palette, DATA_("GP_Palette"), '.', offsetof(bGPDpalette, info),
- sizeof(palette->info));
- /* now fix animation paths */
- BKE_animdata_fix_paths_rename_all(&gpd->id, "palettes", oldname, palette->info);
-}
-
-static char *rna_GPencilPalette_path(PointerRNA *ptr)
-{
- bGPDpalette *palette = ptr->data;
- char name_esc[sizeof(palette->info) * 2];
-
- BLI_strescape(name_esc, palette->info, sizeof(name_esc));
-
- return BLI_sprintfN("palettes[\"%s\"]", name_esc);
-}
-
-static char *rna_GPencilPalette_color_path(PointerRNA *ptr)
-{
- bGPdata *gpd = ptr->id.data;
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = ptr->data;
-
- char name_palette[sizeof(palette->info) * 2];
- char name_color[sizeof(palcolor->info) * 2];
-
- BLI_strescape(name_palette, palette->info, sizeof(name_palette));
- BLI_strescape(name_color, palcolor->info, sizeof(name_color));
-
- return BLI_sprintfN("palettes[\"%s\"].colors[\"%s\"]", name_palette, name_color);
-}
-
-static void rna_GPencilPaletteColor_info_set(PointerRNA *ptr, const char *value)
-{
- bGPdata *gpd = ptr->id.data;
- bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
- bGPDpalettecolor *palcolor = ptr->data;
-
- char oldname[64] = "";
- BLI_strncpy(oldname, palcolor->info, sizeof(oldname));
-
- /* copy the new name into the name slot */
- BLI_strncpy_utf8(palcolor->info, value, sizeof(palcolor->info));
- BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info),
- sizeof(palcolor->info));
-
- /* rename all strokes */
- BKE_gpencil_palettecolor_changename(gpd, oldname, palcolor->info);
-
- /* now fix animation paths */
- BKE_animdata_fix_paths_rename_all(&gpd->id, "colors", oldname, palcolor->info);
-}
-
-static void rna_GPencilStrokeColor_info_set(PointerRNA *ptr, const char *value)
+static void rna_GpencilVertex_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
bGPDstroke *gps = ptr->data;
- /* copy the new name into the name slot */
- BLI_strncpy_utf8(gps->colorname, value, sizeof(gps->colorname));
-}
-
+ if (gps->dvert) {
+ MDeformVert *dvert = gps->dvert;
-static bool rna_GPencilPaletteColor_is_stroke_visible_get(PointerRNA *ptr)
-{
- bGPDpalettecolor *pcolor = (bGPDpalettecolor *)ptr->data;
- return (pcolor->color[3] > GPENCIL_ALPHA_OPACITY_THRESH);
-}
-
-static bool rna_GPencilPaletteColor_is_fill_visible_get(PointerRNA *ptr)
-{
- bGPDpalettecolor *pcolor = (bGPDpalettecolor *)ptr->data;
- return (pcolor->fill[3] > GPENCIL_ALPHA_OPACITY_THRESH);
-}
-
-static int rna_GPencilPaletteColor_index_get(PointerRNA *ptr)
-{
- bGPDpalette *palette = (bGPDpalette *)ptr->data;
- bGPDpalettecolor *pcolor = BKE_gpencil_palettecolor_getactive(palette);
-
- return BLI_findindex(&palette->colors, pcolor);
-}
-
-static void rna_GPencilPaletteColor_index_set(PointerRNA *ptr, int value)
-{
- bGPDpalette *palette = (bGPDpalette *)ptr->data;
- bGPDpalettecolor *pcolor = BLI_findlink(&palette->colors, value);
- BKE_gpencil_palettecolor_setactive(palette, pcolor);
-}
-
-static void rna_GPencilPaletteColor_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
-{
- bGPDpalette *palette = (bGPDpalette *)ptr->data;
-
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&palette->colors) - 1);
-
- *softmin = *min;
- *softmax = *max;
+ rna_iterator_array_begin(iter, (void *)dvert->dw, sizeof(MDeformWeight), dvert->totweight, 0, NULL);
+ }
+ else
+ rna_iterator_array_begin(iter, NULL, 0, 0, 0, NULL);
}
-
#else
static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
@@ -918,11 +693,24 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strength", "Color intensity (alpha factor)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "uv_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "uv_fac");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "UV Factor", "Internal UV factor");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "uv_rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "uv_rot");
+ RNA_def_property_range(prop, 0.0f, M_PI * 2);
+ RNA_def_property_ui_text(prop, "UV Rotation", "Internal UV factor for dot mode");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SPOINT_SELECT);
RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_point_select_set");
RNA_def_property_ui_text(prop, "Select", "Point is selected for viewport editing");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
}
static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop)
@@ -955,7 +743,7 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna)
srna = RNA_def_struct(brna, "GPencilTriangle", NULL);
RNA_def_struct_sdna(srna, "bGPDtriangle");
- RNA_def_struct_ui_text(srna, "Triangle", "Triangulation data for HQ fill");
+ RNA_def_struct_ui_text(srna, "Triangle", "Triangulation data for Grease Pencil fills");
/* point v1 */
prop = RNA_def_property(srna, "v1", PROP_INT, PROP_NONE);
@@ -974,6 +762,51 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "verts[2]");
RNA_def_property_ui_text(prop, "v3", "Third triangle vertex index");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* texture coord for point v1 */
+ prop = RNA_def_property(srna, "uv1", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "uv[0]");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "uv1", "First triangle vertex texture coordinates");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* texture coord for point v2 */
+ prop = RNA_def_property(srna, "uv2", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "uv[1]");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "uv2", "Second triangle vertex texture coordinates");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* texture coord for point v3 */
+ prop = RNA_def_property(srna, "uv3", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "uv[2]");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "uv3", "Third triangle vertex texture coordinates");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+}
+
+static void rna_def_gpencil_mvert_group(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "GpencilVertexGroupElement", NULL);
+ RNA_def_struct_sdna(srna, "MDeformWeight");
+ RNA_def_struct_ui_text(srna, "Vertex Group Element", "Weight value of a vertex in a vertex group");
+ RNA_def_struct_ui_icon(srna, ICON_GROUP_VERTEX);
+
+ /* we can't point to actual group, it is in the object and so
+ * there is no unique group to point to, hence the index */
+ prop = RNA_def_property(srna, "group", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "def_nr");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Group Index", "");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Weight", "Vertex Weight");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}
static void rna_def_gpencil_stroke(BlenderRNA *brna)
@@ -1000,24 +833,30 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points");
rna_def_gpencil_stroke_points_api(brna, prop);
+ /* vertex groups */
+ prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_GpencilVertex_groups_begin", "rna_iterator_array_next",
+ "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "GpencilVertexGroupElement");
+ RNA_def_property_ui_text(prop, "Groups", "Weights for the vertex groups this vertex is member of");
+
/* Triangles */
prop = RNA_def_property(srna, "triangles", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "triangles", "tot_triangles");
RNA_def_property_struct_type(prop, "GPencilTriangle");
RNA_def_property_ui_text(prop, "Triangles", "Triangulation data for HQ fill");
- /* Color */
- prop = RNA_def_property(srna, "color", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GPencilPaletteColor");
- RNA_def_property_pointer_sdna(prop, NULL, "palcolor");
- RNA_def_property_ui_text(prop, "Palette Color", "Color from palette used in Stroke");
- RNA_def_property_update(prop, 0, "rna_GPencil_update");
+ /* Material Index */
+ prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "mat_nr");
+ RNA_def_property_ui_text(prop, "Material Index", "Index of material used in this stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Settings */
prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, stroke_draw_mode_items);
- RNA_def_property_ui_text(prop, "Draw Mode", "");
+ RNA_def_property_ui_text(prop, "Draw Mode", "Coordinate space that stroke is in");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -1026,22 +865,23 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Select", "Stroke is selected for viewport editing");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
- /* Color Name */
- prop = RNA_def_property(srna, "colorname", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilStrokeColor_info_set");
- RNA_def_property_ui_text(prop, "Color Name", "Palette color name");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_colorname_update");
-
/* Cyclic: Draw a line from end to start point */
prop = RNA_def_property(srna, "draw_cyclic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_CYCLIC);
RNA_def_property_ui_text(prop, "Cyclic", "Enable cyclic drawing, closing the stroke");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
+ /* No fill: The stroke never must fill area and must use fill color as stroke color (this is a special flag for fill brush) */
+ prop = RNA_def_property(srna, "is_nofill_stroke", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_NOFILL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "No Fill", "Special stroke to use as boundary for filling areas");
+ RNA_def_property_update(prop, 0, "rna_GPencil_update");
+
/* Line Thickness */
prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "thickness");
- RNA_def_property_range(prop, 1, 300);
+ RNA_def_property_range(prop, 1, 1000);
RNA_def_property_ui_range(prop, 1, 10, 1, 0);
RNA_def_property_ui_text(prop, "Thickness", "Thickness of stroke (in pixels)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -1062,7 +902,6 @@ static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new");
RNA_def_function_ui_description(func, "Add a new grease pencil stroke");
- parm = RNA_def_string(func, "colorname", 0, MAX_NAME, "Color", "Name of the color");
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke");
RNA_def_function_return(func, parm);
@@ -1183,20 +1022,30 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Draw Style */
- // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)?
- prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC);
- RNA_def_property_ui_text(prop, "Volumetric Strokes",
- "Draw strokes as a series of circular blobs, resulting in a volumetric effect");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Layer Opacity */
prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "opacity");
RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ /* Stroke Drawing Color (Annotations) */
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Color", "Color for all strokes in this layer");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ /* Line Thickness (Annotations) */
+ prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "thickness");
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Thickness", "Thickness of annotation strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+
/* Tint Color */
prop = RNA_def_property(srna, "tint_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "tintcolor");
@@ -1212,62 +1061,21 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tint Factor", "Factor of tinting color");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- /* Line Thickness change */
+ /* Line Thickness Change */
prop = RNA_def_property(srna, "line_change", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "thickness");
- //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */
- RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range");
- RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply to current strokes (in pixels)");
+ RNA_def_property_int_sdna(prop, NULL, "line_change");
+ RNA_def_property_range(prop, -300, 300);
+ RNA_def_property_ui_range(prop, -100, 100, 1.0, 1);
+ RNA_def_property_ui_text(prop, "Thickness Change", "Thickness change to apply to current strokes (in pixels)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Onion-Skinning */
prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ONIONSKIN);
- RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_onion_skinning_update");
-
- prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "gstep");
- RNA_def_property_range(prop, -1, 120);
- RNA_def_property_ui_text(prop, "Frames Before",
- "Maximum number of frames to show before current frame "
- "(0 = show only the previous sketch, -1 = don't show any frames before current)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "gstep_next");
- RNA_def_property_range(prop, -1, 120);
- RNA_def_property_ui_text(prop, "Frames After",
- "Maximum number of frames to show after current frame "
- "(0 = show only the next sketch, -1 = don't show any frames after current)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL);
- RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
+ RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_LAYER_ONIONSKIN);
+ RNA_def_property_ui_text(prop, "Onion Skinning", "Display onion skins before and after the current frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_ALWAYS);
- RNA_def_property_ui_text(prop, "Always Show Ghosts",
- "Ghosts are shown in renders and animation playback. Useful for special effects (e.g. motion blur)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
-
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
@@ -1296,7 +1104,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* expose as layers.active */
+ /* exposed as layers.active */
#if 0
prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ACTIVE);
@@ -1310,7 +1118,6 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the Dope Sheet");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, "rna_GPencil_update");
- /* XXX keep this option? */
prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG);
RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)");
@@ -1399,215 +1206,24 @@ static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop,
- "rna_GPencil_active_layer_index_get",
- "rna_GPencil_active_layer_index_set",
- "rna_GPencil_active_layer_index_range");
+ RNA_def_property_int_funcs(
+ prop,
+ "rna_GPencil_active_layer_index_get",
+ "rna_GPencil_active_layer_index_set",
+ "rna_GPencil_active_layer_index_range");
RNA_def_property_ui_text(prop, "Active Layer Index", "Index of active grease pencil layer");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
-}
-
-static void rna_def_gpencil_palettecolor(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "GPencilPaletteColor", NULL);
- RNA_def_struct_sdna(srna, "bGPDpalettecolor");
- RNA_def_struct_ui_text(srna, "Grease Pencil Palette color", "Collection of related colors");
- RNA_def_struct_path_func(srna, "rna_GPencilPalette_color_path");
-
- /* Stroke Drawing Color */
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "color");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Color", "Color for strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "color[3]");
- RNA_def_property_range(prop, 0.0, 1.0f);
- RNA_def_property_ui_text(prop, "Opacity", "Color Opacity");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Name */
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "info");
- RNA_def_property_ui_text(prop, "Name", "Color name");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilPaletteColor_info_set");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Fill Drawing Color */
- prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "fill");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Fill Color", "Color for filling region bounded by each stroke");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Fill alpha */
- prop = RNA_def_property(srna, "fill_alpha", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fill[3]");
- RNA_def_property_range(prop, 0.0, 1.0f);
- RNA_def_property_ui_text(prop, "Fill Opacity", "Opacity for filling region bounded by each stroke");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- /* Flags */
- prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_HIDE);
- RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, 1);
- RNA_def_property_ui_text(prop, "Hide", "Set color Visibility");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_LOCKED);
- RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
- RNA_def_property_ui_text(prop, "Locked", "Protect color from further editing and/or frame changes");
+ /* Active Layer - As an enum (for selecting active layer for annotations) */
+ prop = RNA_def_property(srna, "active_note", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(
+ prop,
+ "rna_GPencil_active_layer_index_get",
+ "rna_GPencil_active_layer_index_set",
+ "rna_GPencil_active_layer_itemf");
+ RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items); /* purely dynamic, as it maps to user-data */
+ RNA_def_property_ui_text(prop, "Active Note", "Note/Layer to add annotation strokes to");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "ghost", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_ONIONSKIN);
- RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0);
- RNA_def_property_ui_text(prop, "Show in Ghosts", "Display strokes using this color when showing onion skins");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Draw Style */
- prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_VOLUMETRIC);
- RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in "
- "a volumetric effect");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Use High quality fill */
- prop = RNA_def_property(srna, "use_hq_fill", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_HQ_FILL);
- RNA_def_property_ui_text(prop, "High Quality Fill", "Fill strokes using high quality to avoid glitches "
- "(slower fps during animation play)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Read-only state props (for simpler UI code) */
- prop = RNA_def_property(srna, "is_stroke_visible", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_GPencilPaletteColor_is_stroke_visible_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Is Stroke Visible", "True when opacity of stroke is set high enough to be visible");
-
- prop = RNA_def_property(srna, "is_fill_visible", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_GPencilPaletteColor_is_fill_visible_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Is Fill Visible", "True when opacity of fill is set high enough to be visible");
-}
-
-/* palette colors api */
-static void rna_def_gpencil_palettecolors_api(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "GPencilPaletteColors");
- srna = RNA_def_struct(brna, "GPencilPaletteColors", NULL);
- RNA_def_struct_sdna(srna, "bGPDpalette");
- RNA_def_struct_ui_text(srna, "Palette colors", "Collection of palette colors");
-
- func = RNA_def_function(srna, "new", "rna_GPencilPalette_color_new");
- RNA_def_function_ui_description(func, "Add a new color to the palette");
- parm = RNA_def_pointer(func, "color", "GPencilPaletteColor", "", "The newly created color");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_GPencilPalette_color_remove");
- RNA_def_function_ui_description(func, "Remove a color from the palette");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "color", "GPencilPaletteColor", "", "The color to remove");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GPencilPaletteColor");
- RNA_def_property_pointer_funcs(prop, "rna_GPencilPalette_active_color_get", "rna_GPencilPalette_active_color_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Active Palette Color", "Current active color");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop,
- "rna_GPencilPaletteColor_index_get",
- "rna_GPencilPaletteColor_index_set",
- "rna_GPencilPaletteColor_index_range");
- RNA_def_property_ui_text(prop, "Active color Index", "Index of active palette color");
-}
-
-static void rna_def_gpencil_palette(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "GPencilPalette", NULL);
- RNA_def_struct_sdna(srna, "bGPDpalette");
- RNA_def_struct_ui_text(srna, "Grease Pencil Palette", "Collection of related palettes");
- RNA_def_struct_path_func(srna, "rna_GPencilPalette_path");
- RNA_def_struct_ui_icon(srna, ICON_COLOR);
-
- /* Name */
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "info");
- RNA_def_property_ui_text(prop, "Name", "Palette name");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilPalette_info_set");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- /* Colors */
- prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "colors", NULL);
- RNA_def_property_struct_type(prop, "GPencilPaletteColor");
- RNA_def_property_ui_text(prop, "Colors", "Colors of the palette");
- rna_def_gpencil_palettecolors_api(brna, prop);
-
-}
-
-static void rna_def_gpencil_palettes_api(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "GreasePencilPalettes");
- srna = RNA_def_struct(brna, "GreasePencilPalettes", NULL);
- RNA_def_struct_sdna(srna, "bGPdata");
- RNA_def_struct_ui_text(srna, "Grease Pencil Palettes", "Collection of grease pencil palettes");
-
- func = RNA_def_function(srna, "new", "rna_GPencil_palette_new");
- RNA_def_function_ui_description(func, "Add a new grease pencil palette");
- parm = RNA_def_string(func, "name", "GPencilPalette", MAX_NAME, "Name", "Name of the palette");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func, "set_active", true, "Set Active", "Activate the newly created palette");
- parm = RNA_def_pointer(func, "palette", "GPencilPalette", "", "The newly created palette");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_GPencil_palette_remove");
- RNA_def_function_ui_description(func, "Remove a grease pencil palette");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "palette", "GPencilPalette", "", "The palette to remove");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GPencilPalette");
- RNA_def_property_pointer_funcs(prop, "rna_GPencil_active_palette_get", "rna_GPencil_active_palette_set",
- NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Active Palette", "Current active palette");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop,
- "rna_GPencilPalette_index_get",
- "rna_GPencilPalette_index_set",
- "rna_GPencilPalette_index_range");
- RNA_def_property_ui_text(prop, "Active Palette Index", "Index of active palette");
}
static void rna_def_gpencil_data(BlenderRNA *brna)
@@ -1616,6 +1232,10 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
PropertyRNA *prop;
FunctionRNA *func;
+ static float default_1[4] = { 0.6f, 0.6f, 0.6f, 0.5f };
+ static float onion_dft1[3] = { 0.145098f, 0.419608f, 0.137255f }; /* green */
+ static float onion_dft2[3] = { 0.125490f, 0.082353f, 0.529412f }; /* blue */
+
srna = RNA_def_struct(brna, "GreasePencil", "ID");
RNA_def_struct_sdna(srna, "bGPdata");
RNA_def_struct_ui_text(srna, "Grease Pencil", "Freehand annotation sketchbook");
@@ -1628,28 +1248,52 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layers", "");
rna_def_gpencil_layers_api(brna, prop);
- /* Palettes */
- prop = RNA_def_property(srna, "palettes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "palettes", NULL);
- RNA_def_property_struct_type(prop, "GPencilPalette");
- RNA_def_property_ui_text(prop, "Palettes", "");
- rna_def_gpencil_palettes_api(brna, prop);
-
/* Animation Data */
rna_def_animdata_common(srna);
+ /* materials */
+ prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
+ RNA_def_property_struct_type(prop, "Material");
+ RNA_def_property_ui_text(prop, "Materials", "");
+ RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+
+ /* xray modes */
+ prop = RNA_def_property(srna, "xray_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "xray_mode");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_xraymodes_items);
+ RNA_def_property_ui_text(prop, "Xray", "");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Flags */
prop = RNA_def_property(srna, "use_stroke_edit_mode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_EDITMODE);
RNA_def_property_ui_text(prop, "Stroke Edit Mode", "Edit Grease Pencil strokes instead of viewport data");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_editmode_update");
+ prop = RNA_def_property(srna, "is_stroke_paint_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_PAINTMODE);
+ RNA_def_property_ui_text(prop, "Stroke Paint Mode", "Draw Grease Pencil strokes on click/drag");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_editmode_update");
+
+ prop = RNA_def_property(srna, "is_stroke_sculpt_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_SCULPTMODE);
+ RNA_def_property_ui_text(prop, "Stroke Sculpt Mode", "Sculpt Grease Pencil strokes instead of viewport data");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_editmode_update");
+
+ prop = RNA_def_property(srna, "is_stroke_weight_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_WEIGHTMODE);
+ RNA_def_property_ui_text(prop, "Stroke Weight Paint Mode", "Grease Pencil weight paint");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_editmode_update");
+
prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_SHOW_ONIONSKINS);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_use_onion_skinning_set");
- RNA_def_property_ui_text(prop, "Onion Skins",
- "Show ghosts of the frames before and after the current frame, toggle to enable on active layer or disable all");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ RNA_def_property_ui_text(prop, "Onion Skins", "Show ghosts of the frames before and after the current frame");
+ RNA_def_property_update(prop, NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL, "rna_GPencil_update");
prop = RNA_def_property(srna, "show_stroke_direction", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_SHOW_DIRECTION);
@@ -1657,6 +1301,102 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
"and smaller red dot (end) points");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "show_constant_thickness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_KEEPTHICKNESS);
+ RNA_def_property_ui_text(prop, "Keep Thickness", "Maintain the thickness of the stroke when the viewport zoom changes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "pixfactor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pixfactor");
+ RNA_def_property_range(prop, 0.1f, 30.0f);
+ RNA_def_property_ui_range(prop, 0.1f, 30.0f, 1, 2);
+ RNA_def_property_ui_text(prop, "Scale", "Scale conversion factor for pixel size (use larger values for thicker lines)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_multiedit", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_MULTIEDIT);
+ RNA_def_property_ui_text(prop, "MultiFrame", "Edit strokes from multiple grease pencil keyframes at the same time (keyframes must be selected to be included)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "edit_line_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "line_color");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, default_1);
+ RNA_def_property_ui_text(prop, "Edit Line Color", "Color for editing line");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ /* onion skinning */
+ prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gstep");
+ RNA_def_property_range(prop, 0, 120);
+ RNA_def_property_int_default(prop, 1);
+ RNA_def_property_ui_text(prop, "Frames Before",
+ "Maximum number of frames to show before current frame "
+ "(0 = don't show any frames before current)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gstep_next");
+ RNA_def_property_range(prop, 0, 120);
+ RNA_def_property_int_default(prop, 1);
+ RNA_def_property_ui_text(prop, "Frames After",
+ "Maximum number of frames to show after current frame "
+ "(0 = don't show any frames after current)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
+ RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, onion_dft1);
+ RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
+ RNA_def_property_update(prop, NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, onion_dft2);
+ RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
+ RNA_def_property_update(prop, NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_GHOST_ALWAYS);
+ RNA_def_property_ui_text(prop, "Always Show Ghosts",
+ "Ghosts are shown in renders and animation playback. Useful for special effects (e.g. motion blur)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "onion_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "onion_mode");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_onion_modes_items);
+ RNA_def_property_ui_text(prop, "Mode", "Mode to display frames");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_onion_fade", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_FADE);
+ RNA_def_property_ui_text(prop, "Fade",
+ "Display onion keyframes with a fade in color transparency");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_onion_loop", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_LOOP);
+ RNA_def_property_ui_text(prop, "Loop",
+ "Display first onion keyframes using next frame color to show indication of loop start frame");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "onion_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "onion_factor");
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Onion Opacity", "Change fade opacity of displayed onion frames");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* API Functions */
func = RNA_def_function(srna, "clear", "rna_GPencil_clear");
RNA_def_function_ui_description(func, "Remove all the grease pencil data");
@@ -1670,12 +1410,12 @@ void RNA_def_gpencil(BlenderRNA *brna)
rna_def_gpencil_layer(brna);
rna_def_gpencil_frame(brna);
- rna_def_gpencil_triangle(brna);
+
rna_def_gpencil_stroke(brna);
rna_def_gpencil_stroke_point(brna);
+ rna_def_gpencil_triangle(brna);
- rna_def_gpencil_palette(brna);
- rna_def_gpencil_palettecolor(brna);
+ rna_def_gpencil_mvert_group(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
new file mode 100644
index 00000000000..d4252601c6a
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -0,0 +1,1340 @@
+/*
+ * ***** 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/makesrna/intern/rna_gpencil_modifier.c
+ * \ingroup RNA
+ */
+
+
+#include <float.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_cachefile_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_animsys.h"
+#include "BKE_data_transfer.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_dynamicpaint.h"
+#include "BKE_effect.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_remap.h"
+#include "BKE_multires.h"
+#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
+ {0, "", 0, N_("Generate"), "" },
+ {eGpencilModifierType_Instance, "GP_INSTANCE", ICON_MOD_ARRAY, "Instance", "Create grid of duplicate instances"},
+ {eGpencilModifierType_Build, "GP_BUILD", ICON_MOD_BUILD, "Build", "Create duplication of strokes"},
+ {eGpencilModifierType_Simplify, "GP_SIMPLIFY", ICON_MOD_DECIM, "Simplify", "Simplify stroke reducing number of points"},
+ {eGpencilModifierType_Subdiv, "GP_SUBDIV", ICON_MOD_SUBSURF, "Subdivide", "Subdivide stroke adding more control points"},
+ {0, "", 0, N_("Deform"), "" },
+ {eGpencilModifierType_Hook, "GP_HOOK", ICON_HOOK, "Hook", "Deform stroke points using objects"},
+ {eGpencilModifierType_Lattice, "GP_LATTICE", ICON_MOD_LATTICE, "Lattice", "Deform strokes using lattice"},
+ {eGpencilModifierType_Mirror, "GP_MIRROR", ICON_MOD_MIRROR, "Mirror", "Duplicate strokes like a mirror"},
+ {eGpencilModifierType_Noise, "GP_NOISE", ICON_RNDCURVE, "Noise", "Add noise to strokes"},
+ {eGpencilModifierType_Offset, "GP_OFFSET", ICON_MOD_DISPLACE, "Offset", "Change stroke location, rotation or scale"},
+ {eGpencilModifierType_Smooth, "GP_SMOOTH", ICON_MOD_SMOOTH, "Smooth", "Smooth stroke"},
+ {eGpencilModifierType_Thick, "GP_THICK", ICON_MAN_ROT, "Thickness", "Change stroke thickness"},
+ {0, "", 0, N_("Color"), "" },
+ {eGpencilModifierType_Color, "GP_COLOR", ICON_GROUP_VCOL, "Hue/Saturation", "Apply changes to stroke colors"},
+ {eGpencilModifierType_Opacity, "GP_OPACITY", ICON_MOD_MASK, "Opacity", "Opacity of the strokes"},
+ {eGpencilModifierType_Tint, "GP_TINT", ICON_COLOR, "Tint", "Tint strokes with new color"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+#ifndef RNA_RUNTIME
+static const EnumPropertyItem modifier_modify_color_items[] = {
+ { GP_MODIFY_COLOR_BOTH, "BOTH", 0, "Both", "Modify fill and stroke colors" },
+ { GP_MODIFY_COLOR_STROKE, "STROKE", 0, "Stroke", "Modify stroke color only" },
+ { GP_MODIFY_COLOR_FILL, "FILL", 0, "Fill", "Modify fill color only" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static const EnumPropertyItem modifier_gphook_falloff_items[] = {
+ { eGPHook_Falloff_None, "NONE", 0, "No Falloff", "" },
+ { eGPHook_Falloff_Curve, "CURVE", 0, "Curve", "" },
+ { eGPHook_Falloff_Smooth, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "" },
+ { eGPHook_Falloff_Sphere, "SPHERE", ICON_SPHERECURVE, "Sphere", "" },
+ { eGPHook_Falloff_Root, "ROOT", ICON_ROOTCURVE, "Root", "" },
+ { eGPHook_Falloff_InvSquare, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "" },
+ { eGPHook_Falloff_Sharp, "SHARP", ICON_SHARPCURVE, "Sharp", "" },
+ { eGPHook_Falloff_Linear, "LINEAR", ICON_LINCURVE, "Linear", "" },
+ { eGPHook_Falloff_Const, "CONSTANT", ICON_NOCURVE, "Constant", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+static const EnumPropertyItem rna_enum_gpencil_lockshift_items[] = {
+ { GP_LOCKAXIS_X, "GP_LOCKAXIS_X", 0, "X", "Use X axis" },
+ { GP_LOCKAXIS_Y, "GP_LOCKAXIS_Y", 0, "Y", "Use Y axis" },
+ { GP_LOCKAXIS_Z, "GP_LOCKAXIS_Z", 0, "Z", "Use Z axis" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+#endif
+
+#ifdef RNA_RUNTIME
+
+#include "DNA_particle_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_smoke_types.h"
+
+#include "BKE_cachefile.h"
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_object.h"
+#include "BKE_gpencil.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
+{
+ GpencilModifierData *md = (GpencilModifierData *)ptr->data;
+
+ switch ((GpencilModifierType)md->type) {
+ case eGpencilModifierType_Noise:
+ return &RNA_NoiseGpencilModifier;
+ case eGpencilModifierType_Subdiv:
+ return &RNA_SubdivGpencilModifier;
+ case eGpencilModifierType_Simplify:
+ return &RNA_SimplifyGpencilModifier;
+ case eGpencilModifierType_Thick:
+ return &RNA_ThickGpencilModifier;
+ case eGpencilModifierType_Tint:
+ return &RNA_TintGpencilModifier;
+ case eGpencilModifierType_Color:
+ return &RNA_ColorGpencilModifier;
+ case eGpencilModifierType_Instance:
+ return &RNA_InstanceGpencilModifier;
+ case eGpencilModifierType_Build:
+ return &RNA_BuildGpencilModifier;
+ case eGpencilModifierType_Opacity:
+ return &RNA_OpacityGpencilModifier;
+ case eGpencilModifierType_Lattice:
+ return &RNA_LatticeGpencilModifier;
+ case eGpencilModifierType_Mirror:
+ return &RNA_MirrorGpencilModifier;
+ case eGpencilModifierType_Smooth:
+ return &RNA_SmoothGpencilModifier;
+ case eGpencilModifierType_Hook:
+ return &RNA_HookGpencilModifier;
+ case eGpencilModifierType_Offset:
+ return &RNA_OffsetGpencilModifier;
+ /* Default */
+ case eGpencilModifierType_None:
+ case NUM_GREASEPENCIL_MODIFIER_TYPES:
+ return &RNA_GpencilModifier;
+ }
+
+ return &RNA_GpencilModifier;
+}
+
+static void rna_GpencilModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ GpencilModifierData *gmd = ptr->data;
+ char oldname[sizeof(gmd->name)];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, gmd->name, sizeof(gmd->name));
+
+ /* copy the new name into the name slot */
+ BLI_strncpy_utf8(gmd->name, value, sizeof(gmd->name));
+
+ /* make sure the name is truly unique */
+ if (ptr->id.data) {
+ Object *ob = ptr->id.data;
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, gmd);
+ }
+
+ /* fix all the animation data which may link to this */
+ BKE_animdata_fix_paths_rename_all(NULL, "grease_pencil_modifiers", oldname, gmd->name);
+}
+
+static char *rna_GpencilModifier_path(PointerRNA *ptr)
+{
+ GpencilModifierData *gmd = ptr->data;
+ char name_esc[sizeof(gmd->name) * 2];
+
+ BLI_strescape(name_esc, gmd->name, sizeof(name_esc));
+ return BLI_sprintfN("grease_pencil_modifiers[\"%s\"]", name_esc);
+}
+
+static void rna_GpencilModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data);
+}
+
+static void rna_GpencilModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_GpencilModifier_update(bmain, scene, ptr);
+ DEG_relations_tag_update(bmain);
+}
+
+/* Vertex Groups */
+
+#define RNA_GP_MOD_VGROUP_NAME_SET(_type, _prop) \
+static void rna_##_type##GpencilModifier_##_prop##_set(PointerRNA *ptr, const char *value) \
+{ \
+ _type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \
+ rna_object_vgroup_name_set(ptr, value, tmd->_prop, sizeof(tmd->_prop)); \
+}
+
+RNA_GP_MOD_VGROUP_NAME_SET(Noise, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Thick, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Opacity, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Lattice, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Smooth, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Hook, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname);
+
+#undef RNA_GP_MOD_VGROUP_NAME_SET
+
+/* Objects */
+
+static void greasepencil_modifier_object_set(Object *self, Object **ob_p, int type, PointerRNA value)
+{
+ Object *ob = value.data;
+
+ if (!self || ob != self) {
+ if (!ob || type == OB_EMPTY || ob->type == type) {
+ id_lib_extern((ID *)ob);
+ *ob_p = ob;
+ }
+ }
+}
+
+#define RNA_GP_MOD_OBJECT_SET(_type, _prop, _obtype) \
+static void rna_##_type##GpencilModifier_##_prop##_set(PointerRNA *ptr, PointerRNA value) \
+{ \
+ _type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \
+ greasepencil_modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
+}
+
+RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
+RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
+
+#undef RNA_GP_MOD_OBJECT_SET
+
+static void rna_HookGpencilModifier_object_set(PointerRNA *ptr, PointerRNA value)
+{
+ HookGpencilModifierData *hmd = ptr->data;
+ Object *ob = (Object *)value.data;
+
+ hmd->object = ob;
+ id_lib_extern((ID *)ob);
+ BKE_object_modifier_gpencil_hook_reset(ob, hmd);
+}
+
+#else
+
+static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "NoiseGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Noise Modifier", "Noise effect modifier");
+ RNA_def_struct_sdna(srna, "NoiseGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_RNDCURVE);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NoiseGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0, 30.0);
+ RNA_def_property_ui_text(prop, "Factor", "Amount of noise to apply");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_USE_RANDOM);
+ RNA_def_property_ui_text(prop, "Random", "Use random values");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_LOCATION);
+ RNA_def_property_ui_text(prop, "Affect Position", "The modifier affects the position of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_strength", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_STRENGTH);
+ RNA_def_property_ui_text(prop, "Affect Strength", "The modifier affects the color strength of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_thickness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_THICKNESS);
+ RNA_def_property_ui_text(prop, "Affect Thickness", "The modifier affects the thickness of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_uv", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_UV);
+ RNA_def_property_ui_text(prop, "Affect UV", "The modifier affects the UV rotation factor of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "full_stroke", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_FULL_STROKE);
+ RNA_def_property_ui_text(prop, "Full Stroke", "The noise moves the stroke as a whole, not point by point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "move_extreme", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOVE_EXTREME);
+ RNA_def_property_ui_text(prop, "Move Extremes", "The noise moves the stroke extreme points");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "step");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_text(prop, "Step", "Number of frames before recalculate random values again");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SmoothGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Smooth Modifier", "Smooth effect modifier");
+ RNA_def_struct_sdna(srna, "SmoothGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SmoothGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0, 2);
+ RNA_def_property_ui_text(prop, "Factor", "Amount of smooth to apply");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_MOD_LOCATION);
+ RNA_def_property_ui_text(prop, "Affect Position", "The modifier affects the position of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_strength", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_MOD_STRENGTH);
+ RNA_def_property_ui_text(prop, "Affect Strength", "The modifier affects the color strength of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_thickness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_MOD_THICKNESS);
+ RNA_def_property_ui_text(prop, "Affect Thickness", "The modifier affects the thickness of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "affect_uv", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_MOD_UV);
+ RNA_def_property_ui_text(prop, "Affect UV", "The modifier affects the UV rotation factor of the point");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "step");
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Step", "Number of times to apply smooth (high numbers can reduce fps)");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SubdivGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Subdivision Modifier", "Subdivide Stroke modifier");
+ RNA_def_struct_sdna(srna, "SubdivGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_SUBSURF);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "level", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "level");
+ RNA_def_property_range(prop, 0, 5);
+ RNA_def_property_ui_text(prop, "Level", "Number of subdivisions");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "simple", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_SIMPLE);
+ RNA_def_property_ui_text(prop, "Simple", "The modifier only add control points");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_gpencil_simplify_mode_items[] = {
+ { GP_SIMPLIFY_FIXED, "FIXED", ICON_IPO_CONSTANT, "Fixed",
+ "Delete alternative vertices in the stroke, except extrems" },
+ { GP_SIMPLIFY_ADAPTATIVE, "ADAPTATIVE", ICON_IPO_EASE_IN_OUT, "Adaptative",
+ "Use a RDP algorithm to simplify" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ srna = RNA_def_struct(brna, "SimplifyGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Simplify Modifier", "Simplify Stroke modifier");
+ RNA_def_struct_sdna(srna, "SimplifyGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_DECIM);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0, 100.0);
+ RNA_def_property_ui_range(prop, 0, 100.0, 1.0f, 3);
+ RNA_def_property_ui_text(prop, "Factor", "Factor of Simplify");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SIMPLIFY_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SIMPLIFY_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Mode */
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_gpencil_simplify_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "How simplify the stroke");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "step");
+ RNA_def_property_range(prop, 1, 50);
+ RNA_def_property_ui_text(prop, "Iterations", "Number of times to apply simplify");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThickGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Thick Modifier", "Subdivide and Smooth Stroke modifier");
+ RNA_def_struct_sdna(srna, "ThickGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MAN_ROT);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ThickGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "thickness");
+ RNA_def_property_range(prop, -100, 500);
+ RNA_def_property_ui_text(prop, "Thickness", "Factor of thickness change");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_CUSTOM_CURVE);
+ RNA_def_property_ui_text(prop, "Custom Curve", "Use a custom curve to define thickness changes");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "normalize_thickness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_NORMALIZE);
+ RNA_def_property_ui_text(prop, "Normalize", "Normalize the full stroke to modifier thickness");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_thickness");
+ RNA_def_property_ui_text(prop, "Curve", "Custom Thickness Curve");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpenciloffset(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "OffsetGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Offset Modifier", "Offset Stroke modifier");
+ RNA_def_struct_sdna(srna, "OffsetGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_DISPLACE);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_OffsetGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_float_sdna(prop, NULL, "loc");
+ RNA_def_property_ui_text(prop, "Location", "Values for change location");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER);
+ RNA_def_property_float_sdna(prop, NULL, "rot");
+ RNA_def_property_ui_text(prop, "Rotation", "Values for chages in rotation");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_ui_text(prop, "Scale", "Values for changes in scale");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "TintGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Tint Modifier", "Tint Stroke Color modifier");
+ RNA_def_struct_sdna(srna, "TintGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_COLOR);
+
+ prop = RNA_def_property(srna, "modify_color", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, modifier_modify_color_items); /* share the enum */
+ RNA_def_property_ui_text(prop, "Mode", "Set what colors of the stroke are affected");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Color used for tinting");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Factor", "Factor for mixing color");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_CREATE_COLORS);
+ RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilcolor(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ColorGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Hue/Saturation Modifier", "Change Hue/Saturation modifier");
+ RNA_def_struct_sdna(srna, "ColorGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_GROUP_VCOL);
+
+ prop = RNA_def_property(srna, "modify_color", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, modifier_modify_color_items); /* share the enum */
+ RNA_def_property_ui_text(prop, "Mode", "Set what colors of the stroke are affected");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "hue", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_ui_range(prop, 0.0, 2.0, 0.1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "hsv[0]");
+ RNA_def_property_ui_text(prop, "Hue", "Color Hue");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "saturation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_ui_range(prop, 0.0, 2.0, 0.1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "hsv[1]");
+ RNA_def_property_ui_text(prop, "Saturation", "Color Saturation");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_ui_range(prop, 0.0, 2.0, 0.1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "hsv[2]");
+ RNA_def_property_ui_text(prop, "Value", "Color Value");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_CREATE_COLORS);
+ RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "OpacityGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Opacity Modifier", "Opacity of Strokes modifier");
+ RNA_def_struct_sdna(srna, "OpacityGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_MASK);
+
+ prop = RNA_def_property(srna, "modify_color", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, modifier_modify_color_items); /* share the enum */
+ RNA_def_property_ui_text(prop, "Mode", "Set what colors of the stroke are affected");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_OpacityGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Factor", "Factor of Opacity");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_CREATE_COLORS);
+ RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "InstanceGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Instance Modifier", "Create grid of duplicate instances");
+ RNA_def_struct_sdna(srna, "InstanceGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "count", PROP_INT, PROP_XYZ);
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_ui_range(prop, 1, 20, 1, -1);
+ RNA_def_property_ui_text(prop, "Count", "Number of items");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Offset parameters */
+ prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_float_sdna(prop, NULL, "offset");
+ RNA_def_property_ui_text(prop, "Offset", "Value for the distance between items");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "shift", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_float_sdna(prop, NULL, "shift");
+ RNA_def_property_ui_text(prop, "Shift", "Shiftness value");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "lock_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "lock_axis");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_lockshift_items);
+ //RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Axis", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER);
+ RNA_def_property_float_sdna(prop, NULL, "rot");
+ RNA_def_property_ui_text(prop, "Rotation", "Value for chages in rotation");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_ui_text(prop, "Scale", "Value for changes in scale");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "random_rot", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_RANDOM_ROT);
+ RNA_def_property_ui_text(prop, "Random Rotation", "Use random factors for rotation");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "rot_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "rnd_rot");
+ RNA_def_property_ui_text(prop, "Rotation Factor", "Random factor for rotation");
+ RNA_def_property_range(prop, -10.0, 10.0);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "random_scale", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_RANDOM_SIZE);
+ RNA_def_property_ui_text(prop, "Random Scale", "Use random factors for scale");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "scale_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "rnd_size");
+ RNA_def_property_ui_text(prop, "Scale Factor", "Random factor for scale");
+ RNA_def_property_range(prop, -10.0, 10.0);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "use_make_objects", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_MAKE_OBJECTS);
+ RNA_def_property_ui_text(prop, "Make Objects",
+ "When applying this modifier, instances get created as separate objects");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilbuild(BlenderRNA *brna)
+{
+ static EnumPropertyItem prop_gpencil_build_mode_items[] = {
+ {GP_BUILD_MODE_SEQUENTIAL, "SEQUENTIAL", ICON_PARTICLE_POINT, "Sequential",
+ "Strokes appear/disappear one after the other, but only a single one changes at a time"},
+ {GP_BUILD_MODE_CONCURRENT, "CONCURRENT", ICON_PARTICLE_TIP, "Concurrent",
+ "Multiple strokes appear/disappear at once"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_gpencil_build_transition_items[] = {
+ {GP_BUILD_TRANSITION_GROW, "GROW", 0, "Grow",
+ "Show points in the order they occur in each stroke "
+ "(e.g. for animating lines being drawn)"},
+ {GP_BUILD_TRANSITION_SHRINK, "SHRINK", 0, "Shrink",
+ "Hide points from the end of each stroke to the start "
+ "(e.g. for animating lines being erased)"},
+ {GP_BUILD_TRANSITION_FADE, "FADE", 0, "Fade",
+ "Hide points in the order they occur in each stroke "
+ "(e.g. for animating ink fading or vanishing after getting drawn)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_gpencil_build_time_align_items[] = {
+ {GP_BUILD_TIMEALIGN_START, "START", 0, "Align Start",
+ "All strokes start at same time (i.e. short strokes finish earlier)"},
+ {GP_BUILD_TIMEALIGN_END, "END", 0, "Align End",
+ "All strokes end at same time (i.e. short strokes start later)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "BuildGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Build Modifier", "Animate strokes appearing and disappearing");
+ RNA_def_struct_sdna(srna, "BuildGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD);
+
+ /* Mode */
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_gpencil_build_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "How many strokes are being animated at a time");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Direction */
+ prop = RNA_def_property(srna, "transition", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_gpencil_build_transition_items);
+ RNA_def_property_ui_text(prop, "Transition", "How are strokes animated (i.e. are they appearing or disappearing)");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+
+ /* Transition Onset Delay + Length */
+ prop = RNA_def_property(srna, "start_delay", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start_delay");
+ RNA_def_property_ui_text(prop, "Start Delay", "Number of frames after each GP keyframe before the modifier has any effect");
+ RNA_def_property_range(prop, 0, MAXFRAMEF);
+ RNA_def_property_ui_range(prop, 0, 200, 1, -1);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "length");
+ RNA_def_property_ui_text(prop, "Length",
+ "Maximum number of frames that the build effect can run for "
+ "(unless another GP keyframe occurs before this time has elapsed)");
+ RNA_def_property_range(prop, 1, MAXFRAMEF);
+ RNA_def_property_ui_range(prop, 1, 1000, 1, -1);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+
+ /* Concurrent Mode Settings */
+ prop = RNA_def_property(srna, "concurrent_time_alignment", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "time_alignment");
+ RNA_def_property_enum_items(prop, prop_gpencil_build_time_align_items);
+ RNA_def_property_ui_text(prop, "Time Alignment", "When should strokes start to appear/disappear");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+
+
+ /* Time Limits */
+ prop = RNA_def_property(srna, "use_restrict_frame_range", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_RESTRICT_TIME);
+ RNA_def_property_ui_text(prop, "Restrict Frame Range", "Only modify strokes during the specified frame range");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start_frame");
+ RNA_def_property_ui_text(prop, "Start Frame", "Start Frame (when Restrict Frame Range is enabled)");
+ RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "end_frame");
+ RNA_def_property_ui_text(prop, "End Frame", "End Frame (when Restrict Frame Range is enabled)");
+ RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+
+ /* Filters - Layer */
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Filters - Pass Index */
+#if 0
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+#endif
+}
+
+static void rna_def_modifier_gpencillattice(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LatticeGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Lattice Modifier", "Change stroke using lattice to deform modifier");
+ RNA_def_struct_sdna(srna, "LatticeGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_LATTICE);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_LatticeGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Lattice object to deform with");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_LatticeGpencilModifier_object_set", NULL, "rna_Lattice_object_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, 1, 10, 2);
+ RNA_def_property_ui_text(prop, "Strength", "Strength of modifier effect");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilmirror(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MirrorGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Mirror Modifier", "Change stroke using lattice to deform modifier");
+ RNA_def_struct_sdna(srna, "MirrorGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_MIRROR);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object used as center");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_MirrorGpencilModifier_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "clip", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_CLIPPING);
+ RNA_def_property_ui_text(prop, "Clip", "Clip points");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "x_axis", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_AXIS_X);
+ RNA_def_property_ui_text(prop, "X", "Mirror this axis");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "y_axis", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_AXIS_Y);
+ RNA_def_property_ui_text(prop, "Y", "Mirror this axis");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "z_axis", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_AXIS_Z);
+ RNA_def_property_ui_text(prop, "Z", "Mirror this axis");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+
+static void rna_def_modifier_gpencilhook(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "HookGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Hook Modifier", "Hook modifier to modify the location of stroke points");
+ RNA_def_struct_sdna(srna, "HookGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_HOOK);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Parent Object for hook, also recalculates and clears offset");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_HookGpencilModifier_object_set", NULL, NULL);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "subtarget");
+ RNA_def_property_ui_text(prop, "Sub-Target",
+ "Name of Parent Bone for hook (if applicable), also recalculates and clears offset");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "force");
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Strength", "Relative force of the hook");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, modifier_gphook_falloff_items); /* share the enum */
+ RNA_def_property_ui_text(prop, "Falloff Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "falloff_radius", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "falloff");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, 100, 100, 2);
+ RNA_def_property_ui_text(prop, "Radius", "If not zero, the distance from the hook where influence ends");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curfalloff");
+ RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "cent");
+ RNA_def_property_ui_text(prop, "Hook Center", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "matrix_inverse", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "parentinv");
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Matrix", "Reverse the transformation between this object and its target");
+ RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "use_falloff_uniform", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_UNIFORM_SPACE);
+ RNA_def_property_ui_text(prop, "Uniform Falloff", "Compensate for non-uniform object scale");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+}
+void RNA_def_greasepencil_modifier(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* data */
+ srna = RNA_def_struct(brna, "GpencilModifier", NULL);
+ RNA_def_struct_ui_text(srna, "GpencilModifier", "Modifier affecting the grease pencil object");
+ RNA_def_struct_refine_func(srna, "rna_GpencilModifier_refine");
+ RNA_def_struct_path_func(srna, "rna_GpencilModifier_path");
+ RNA_def_struct_sdna(srna, "GpencilModifierData");
+
+ /* strings */
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GpencilModifier_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Modifier name");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER | NA_RENAME, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* enums */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rna_enum_object_greasepencil_modifier_type_items);
+ RNA_def_property_ui_text(prop, "Type", "");
+
+ /* flags */
+ prop = RNA_def_property(srna, "show_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eGpencilModifierMode_Realtime);
+ RNA_def_property_ui_text(prop, "Realtime", "Display modifier in viewport");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0);
+
+ prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eGpencilModifierMode_Render);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_text(prop, "Render", "Use modifier during render");
+ RNA_def_property_ui_icon(prop, ICON_SCENE, 0);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "show_in_editmode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eGpencilModifierMode_Editmode);
+ RNA_def_property_ui_text(prop, "Edit Mode", "Display modifier in Edit mode");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ RNA_def_property_ui_icon(prop, ICON_EDITMODE_HLT, 0);
+
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eGpencilModifierMode_Expanded);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface");
+ RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
+
+ /* types */
+ rna_def_modifier_gpencilnoise(brna);
+ rna_def_modifier_gpencilsmooth(brna);
+ rna_def_modifier_gpencilsubdiv(brna);
+ rna_def_modifier_gpencilsimplify(brna);
+ rna_def_modifier_gpencilthick(brna);
+ rna_def_modifier_gpenciloffset(brna);
+ rna_def_modifier_gpenciltint(brna);
+ rna_def_modifier_gpencilcolor(brna);
+ rna_def_modifier_gpencilinstance(brna);
+ rna_def_modifier_gpencilbuild(brna);
+ rna_def_modifier_gpencilopacity(brna);
+ rna_def_modifier_gpencillattice(brna);
+ rna_def_modifier_gpencilmirror(brna);
+ rna_def_modifier_gpencilhook(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index f9c1e497716..d5923a05b80 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -153,6 +153,8 @@ void RNA_def_dynamic_paint(struct BlenderRNA *brna);
void RNA_def_fluidsim(struct BlenderRNA *brna);
void RNA_def_fcurve(struct BlenderRNA *brna);
void RNA_def_gpencil(struct BlenderRNA *brna);
+void RNA_def_greasepencil_modifier(struct BlenderRNA *brna);
+void RNA_def_shader_fx(struct BlenderRNA *brna);
void RNA_def_image(struct BlenderRNA *brna);
void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_light(struct BlenderRNA *brna);
@@ -285,6 +287,7 @@ void rna_TextureSlot_update(struct bContext *C, struct PointerRNA *ptr);
bool rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Camera_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Curve_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
+bool rna_GPencil_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Light_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Lattice_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Mesh_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
@@ -293,6 +296,10 @@ bool rna_Mesh_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Action_id_poll(struct PointerRNA *ptr, struct PointerRNA value);
bool rna_Action_actedit_assign_poll(struct PointerRNA *ptr, struct PointerRNA value);
+/* Grease Pencil datablock polling functions - for filtering GP Object vs Annotation datablocks */
+bool rna_GPencil_datablocks_annotations_poll(struct PointerRNA *ptr, const struct PointerRNA value);
+bool rna_GPencil_datablocks_obdata_poll(struct PointerRNA *ptr, const struct PointerRNA value);
+
char *rna_TextureSlot_path(struct PointerRNA *ptr);
char *rna_Node_ImageUser_path(struct PointerRNA *ptr);
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index 573540ee641..126c5e82206 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -124,6 +124,7 @@ static void rna_def_light(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ static float default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
srna = RNA_def_struct(brna, "Light", "ID");
RNA_def_struct_sdna(srna, "Lamp");
@@ -146,6 +147,7 @@ static void rna_def_light(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_ui_range(prop, 0, 10, 1, 3);
RNA_def_property_ui_text(prop, "Energy", "Amount of light emitted");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
@@ -153,11 +155,13 @@ static void rna_def_light(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_float_array_default(prop, default_color);
RNA_def_property_ui_text(prop, "Color", "Light color");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "specular_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "spec_fac");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
RNA_def_property_ui_text(prop, "Specular Factor", "Specular reflection multiplier");
@@ -256,6 +260,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "shadow_buffer_clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipsta");
+ RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Shadow Buffer Clip Start",
"Shadow map clip start, below which objects will not generate shadows");
@@ -263,6 +268,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "shadow_buffer_clip_end", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipend");
+ RNA_def_property_float_default(prop, 40.0f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Shadow Buffer Clip End",
"Shadow map clip end, beyond which objects will not generate shadows");
@@ -270,6 +276,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "shadow_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bias");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.001f, 9999.0f);
RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Bias for reducing self shadowing");
@@ -283,12 +290,14 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "shadow_buffer_exp", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bleedexp");
+ RNA_def_property_float_default(prop, 2.5f);
RNA_def_property_range(prop, 1.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Shadow Buffer Exponent", "Bias for reducing light-bleed on exponential shadow maps");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_buffer_soft", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "soft");
+ RNA_def_property_float_default(prop, 3.0f);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Shadow Buffer Soft", "Size of shadow buffer sampling area");
RNA_def_property_update(prop, 0, "rna_Light_update");
@@ -307,6 +316,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "shadow_soft_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "area_size");
+ RNA_def_property_float_default(prop, 0.25f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(prop, "Shadow Soft Size", "Light size for ray shadow sampling (Raytraced shadows)");
@@ -322,6 +332,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "contact_shadow_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "contact_dist");
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Contact Shadow Distance", "World space distance in which to search for "
"screen space occluder");
@@ -329,6 +340,7 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "contact_shadow_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "contact_bias");
+ RNA_def_property_float_default(prop, 0.03f);
RNA_def_property_range(prop, 0.001f, 9999.0f);
RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Contact Shadow Bias", "Bias to avoid self shadowing");
@@ -336,12 +348,14 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
prop = RNA_def_property(srna, "contact_shadow_soft_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "contact_spread");
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Contact Shadow Soft", "Control how soft the contact shadows will be");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "contact_shadow_thickness", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "contact_thickness");
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(prop, "Contact Shadow Thickness", "Pixel thickness used to detect occlusion");
@@ -350,24 +364,28 @@ static void rna_def_light_shadow(StructRNA *srna, int sun)
if (sun) {
prop = RNA_def_property(srna, "shadow_cascade_max_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "cascade_max_dist");
+ RNA_def_property_float_default(prop, 1000.0f);
RNA_def_property_range(prop, 0.0f, 9999.0f);
RNA_def_property_ui_text(prop, "Cascade Max Distance", "End distance of the cascaded shadow map (only in perspective view)");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_count", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "cascade_count");
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_range(prop, 1, 4);
RNA_def_property_ui_text(prop, "Cascade Count", "Number of texture used by the cascaded shadow map");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_exponent", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "cascade_exponent");
+ RNA_def_property_float_default(prop, 0.8f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Exponential Distribution", "Higher value increase resolution towards the viewpoint");
RNA_def_property_update(prop, 0, "rna_Light_update");
prop = RNA_def_property(srna, "shadow_cascade_fade", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "cascade_fade");
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Cascade Fade", "How smooth is the transition between each cascade");
RNA_def_property_update(prop, 0, "rna_Light_update");
@@ -416,14 +434,16 @@ static void rna_def_area_light(BlenderRNA *brna)
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "area_size");
+ RNA_def_property_float_default(prop, 0.25f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(prop, "Size", "Size of the area of the area light, X direction size for rectangle shapes");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_float_sdna(prop, NULL, "area_sizey");
+ RNA_def_property_float_default(prop, 0.25f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(prop, "Size Y",
"Size of the area of the area light in the Y direction for rectangle shapes");
@@ -450,12 +470,14 @@ static void rna_def_spot_light(BlenderRNA *brna)
prop = RNA_def_property(srna, "spot_blend", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spotblend");
+ RNA_def_property_float_default(prop, 0.15f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Spot Blend", "The softness of the spotlight edge");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
prop = RNA_def_property(srna, "spot_size", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "spotsize");
+ RNA_def_property_float_default(prop, DEG2RADF(45.0f));
RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Spot Size", "Angle of the spotlight beam");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 7d770a99c0c..d425534fe53 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -230,6 +230,18 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
+
+ prop = RNA_def_property(srna, "holdout", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HOLDOUT);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Holdout", "Mask out objects in collection from view layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
+
+ prop = RNA_def_property(srna, "indirect_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_INDIRECT_ONLY);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Indirect Only", "Objects in collection only contribute indirectly (through shadows and reflections) in the view layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
}
static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
index a14699691a6..f54c01fab8e 100644
--- a/source/blender/makesrna/intern/rna_lightprobe.c
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -83,6 +83,7 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipsta");
+ RNA_def_property_float_default(prop, 0.8f);
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip Start",
@@ -91,6 +92,7 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipend");
+ RNA_def_property_float_default(prop, 40.0f);
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip End",
@@ -115,11 +117,13 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop = RNA_def_property(srna, "influence_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "distinf");
+ RNA_def_property_float_default(prop, 2.5f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop, "Influence Distance", "Influence distance of the probe");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Falloff", "Control how fast the probe influence decreases");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
@@ -141,6 +145,7 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop = RNA_def_property(srna, "parallax_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "distpar");
+ RNA_def_property_float_default(prop, 2.5f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop, "Parallax Radius", "Lowest corner of the parallax bounding box");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
@@ -148,21 +153,25 @@ static void rna_def_lightprobe(BlenderRNA *brna)
/* irradiance grid */
prop = RNA_def_property(srna, "grid_resolution_x", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_ui_text(prop, "Resolution X", "Number of sample along the x axis of the volume");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "grid_resolution_y", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_ui_text(prop, "Resolution Y", "Number of sample along the y axis of the volume");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "grid_resolution_z", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_ui_text(prop, "Resolution Z", "Number of sample along the z axis of the volume");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "visibility_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vis_bias");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.001f, 9999.0f);
RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Visibility Bias", "Bias for reducing self shadowing");
@@ -170,18 +179,21 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop = RNA_def_property(srna, "visibility_bleed_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vis_bleedbias");
+ RNA_def_property_float_default(prop, 0.0f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Visibility Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
prop = RNA_def_property(srna, "visibility_blur", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vis_blur");
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Visibility Blur", "Filter size of the visibilty blur");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "intensity");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 3.0f, 1.0, 3);
RNA_def_property_ui_text(prop, "Intensity", "Modify the intensity of the lighting captured by this probe");
@@ -206,11 +218,6 @@ static void rna_def_lightprobe(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Data", "Show captured lighting data into the 3D view for debuging purpose");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
- prop = RNA_def_property(srna, "data_draw_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.05f, 10.0f);
- RNA_def_property_ui_text(prop, "Data Draw Size", "Size of the spheres to debug captured light");
- RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
-
/* common */
rna_def_animdata_common(srna);
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index febe74f63c9..9fd9a04ae25 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -231,6 +231,9 @@ static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char
case ID_LT:
type = OB_LATTICE;
break;
+ case ID_GD:
+ type = OB_GPENCIL;
+ break;
case ID_AR:
type = OB_ARMATURE;
break;
@@ -266,6 +269,13 @@ static Material *rna_Main_materials_new(Main *bmain, const char *name)
return (Material *)id;
}
+static void rna_Main_materials_gpencil_data(Main *UNUSED(bmain), PointerRNA *id_ptr)
+{
+ ID *id = id_ptr->data;
+ Material *ma = (Material *)id;
+ BKE_material_init_gpencil_settings(ma);
+}
+
static const EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
return rna_node_tree_type_itemf(NULL, NULL, r_free);
@@ -433,6 +443,14 @@ static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
return brush;
}
+static void rna_Main_brush_gpencil_data(Main *UNUSED(bmain), PointerRNA *id_ptr)
+{
+ ID *id = id_ptr->data;
+ Brush *brush = (Brush *)id;
+ BKE_brush_init_gpencil_settings(brush);
+}
+
+
static World *rna_Main_worlds_new(Main *bmain, const char *name)
{
char safe_name[MAX_ID_NAME - 2];
@@ -783,6 +801,11 @@ void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "material", "Material", "", "New material data-block");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "create_gpencil_data", "rna_Main_materials_gpencil_data");
+ RNA_def_function_ui_description(func, "Add grease pencil material settings");
+ parm = RNA_def_pointer(func, "material", "Material", "", "Material");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+
func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a material from the current blendfile");
@@ -1257,6 +1280,11 @@ void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "tag", "rna_Main_brushes_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "create_gpencil_data", "rna_Main_brush_gpencil_data");
+ RNA_def_function_ui_description(func, "Add grease pencil brush settings");
+ parm = RNA_def_pointer(func, "brush", "Brush", "", "Brush");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
}
void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 0a8ea99b8fb..44d14975ab0 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -72,6 +72,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_main.h"
+#include "BKE_gpencil.h"
#include "BKE_material.h"
#include "BKE_texture.h"
#include "BKE_node.h"
@@ -85,6 +86,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
#include "ED_node.h"
#include "ED_image.h"
#include "ED_screen.h"
+#include "ED_gpencil.h"
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -104,6 +106,31 @@ static void rna_Material_update_previews(Main *UNUSED(bmain), Scene *UNUSED(scen
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_PREVIEW, ma);
}
+static void rna_MaterialGpencil_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Material *ma = ptr->id.data;
+ PreviewImage *preview = ma->preview;
+
+ rna_Material_update(bmain, scene, ptr);
+
+ /* update previews (icon and thumbnail) */
+ if (preview != NULL) {
+ preview->flag[ICON_SIZE_ICON] |= PRV_CHANGED;
+ preview->flag[ICON_SIZE_PREVIEW] |= PRV_CHANGED;
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_PREVIEW, ma);
+ }
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma);
+}
+
+static void rna_MaterialGpencil_nopreview_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Material *ma = ptr->id.data;
+
+ rna_Material_update(bmain, scene, ptr);
+
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma);
+}
+
static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Material *ma = ptr->id.data;
@@ -243,6 +270,59 @@ void rna_mtex_texture_slots_clear(ID *self_id, struct bContext *C, ReportList *r
WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
}
+static bool rna_is_grease_pencil_get(PointerRNA *ptr)
+{
+ Material *ma = (Material *)ptr->data;
+ if (ma->gp_style != NULL)
+ return true;
+
+ return false;
+}
+
+static void rna_gpcolordata_uv_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ /* update all uv strokes of this color */
+ Material *ma = ptr->id.data;
+ ED_gpencil_update_color_uv(bmain, ma);
+
+ rna_MaterialGpencil_update(bmain, scene, ptr);
+}
+
+static char *rna_GpencilColorData_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("grease_pencil");
+}
+
+static int rna_GpencilColorData_is_stroke_visible_get(PointerRNA *ptr)
+{
+ MaterialGPencilStyle *pcolor = ptr->data;
+ return (pcolor->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH);
+}
+
+static int rna_GpencilColorData_is_fill_visible_get(PointerRNA *ptr)
+{
+ MaterialGPencilStyle *pcolor = (MaterialGPencilStyle *)ptr->data;
+ return ((pcolor->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (pcolor->fill_style > 0));
+}
+
+static void rna_GpencilColorData_stroke_image_set(PointerRNA *ptr, PointerRNA value)
+{
+ MaterialGPencilStyle *pcolor = ptr->data;
+ ID *id = value.data;
+
+ id_us_plus(id);
+ pcolor->sima = (struct Image *)id;
+}
+
+static void rna_GpencilColorData_fill_image_set(PointerRNA *ptr, PointerRNA value)
+{
+ MaterialGPencilStyle *pcolor = (MaterialGPencilStyle *)ptr->data;
+ ID *id = value.data;
+
+ id_us_plus(id);
+ pcolor->ima = (struct Image *)id;
+}
+
#else
static void rna_def_material_display(StructRNA *srna)
@@ -296,6 +376,251 @@ static void rna_def_material_display(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Material_update");
}
+static void rna_def_material_greasepencil(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* mode type styles */
+ static EnumPropertyItem gpcolordata_mode_types_items[] = {
+ { GP_STYLE_MODE_LINE, "LINE", 0, "Line", "Draw strokes using a continuous line" },
+ { GP_STYLE_MODE_DOTS, "DOTS", 0, "Dots", "Draw strokes using separated dots" },
+ { GP_STYLE_MODE_BOX, "BOX", 0, "Boxes", "Draw strokes using separated rectangle boxes" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* stroke styles */
+ static EnumPropertyItem stroke_style_items[] = {
+ { GP_STYLE_STROKE_STYLE_SOLID, "SOLID", 0, "Solid", "Draw strokes with solid color" },
+ { GP_STYLE_STROKE_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Draw strokes using texture" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ /* fill styles */
+ static EnumPropertyItem fill_style_items[] = {
+ { GP_STYLE_FILL_STYLE_SOLID, "SOLID", 0, "Solid", "Fill area with solid color" },
+ { GP_STYLE_FILL_STYLE_GRADIENT, "GRADIENT", 0, "Gradient", "Fill area with gradient color" },
+ { GP_STYLE_FILL_STYLE_CHESSBOARD, "CHESSBOARD", 0, "Checker Board", "Fill area with chessboard pattern" },
+ { GP_STYLE_FILL_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Fill area with image texture" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ static EnumPropertyItem fill_gradient_items[] = {
+ { GP_STYLE_GRADIENT_LINEAR, "LINEAR", 0, "Linear", "Fill area with gradient color" },
+ { GP_STYLE_GRADIENT_RADIAL, "RADIAL", 0, "Radial", "Fill area with radial gradient" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ srna = RNA_def_struct(brna, "MaterialGPencilStyle", NULL);
+ RNA_def_struct_sdna(srna, "MaterialGPencilStyle");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Color", "");
+ RNA_def_struct_path_func(srna, "rna_GpencilColorData_path");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "stroke_rgba");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Fill Drawing Color */
+ prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "fill_rgba");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Fill Color", "Color for filling region bounded by each stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Secondary Drawing Color */
+ prop = RNA_def_property(srna, "mix_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "mix_rgba");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Mix Color", "Color for mixing with primary filling color");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Mix factor */
+ prop = RNA_def_property(srna, "mix_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "mix_factor");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Mix", "Mix Adjustment Factor");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Scale factor for uv coordinates */
+ prop = RNA_def_property(srna, "pattern_scale", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "gradient_scale");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Scale", "Scale Factor for UV coordinates");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Shift factor to move pattern filling in 2d space */
+ prop = RNA_def_property(srna, "pattern_shift", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "gradient_shift");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Shift", "Shift filling pattern in 2d space");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Gradient angle */
+ prop = RNA_def_property(srna, "pattern_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "gradient_angle");
+ RNA_def_property_ui_text(prop, "Angle", "Pattern Orientation Angle");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Gradient radius */
+ prop = RNA_def_property(srna, "pattern_radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "gradient_radius");
+ RNA_def_property_range(prop, 0.0001f, 10.0f);
+ RNA_def_property_ui_text(prop, "Radius", "Pattern Radius");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Box size */
+ prop = RNA_def_property(srna, "pattern_gridsize", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pattern_gridsize");
+ RNA_def_property_range(prop, 0.0001f, 10.0f);
+ RNA_def_property_ui_text(prop, "Size", "Box Size");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Texture angle */
+ prop = RNA_def_property(srna, "texture_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "texture_angle");
+ RNA_def_property_ui_text(prop, "Angle", "Texture Orientation Angle");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Scale factor for texture */
+ prop = RNA_def_property(srna, "texture_scale", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "texture_scale");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Scale", "Scale Factor for Texture");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Shift factor to move texture in 2d space */
+ prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "texture_offset");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Offset", "Shift Texture in 2d Space");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Texture opacity size */
+ prop = RNA_def_property(srna, "texture_opacity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "texture_opacity");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Opacity", "Texture Opacity");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* texture pixsize factor (used for UV along the stroke) */
+ prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "texture_pixsize");
+ RNA_def_property_range(prop, 1, 5000);
+ RNA_def_property_ui_text(prop, "UV Factor", "Texture Pixel Size factor along the stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_gpcolordata_uv_update");
+
+ /* Flags */
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_HIDE);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
+ RNA_def_property_ui_text(prop, "Hide", "Set color Visibility");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
+
+ prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_LOCKED);
+ RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
+ RNA_def_property_ui_text(prop, "Locked", "Protect color from further editing and/or frame changes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
+
+ prop = RNA_def_property(srna, "ghost", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_ONIONSKIN);
+ RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0);
+ RNA_def_property_ui_text(prop, "Show in Ghosts", "Display strokes using this color when showing onion skins");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
+
+ prop = RNA_def_property(srna, "texture_clamp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_TEX_CLAMP);
+ RNA_def_property_ui_text(prop, "Clamp", "Do not repeat texture and clamp to one instance only");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ prop = RNA_def_property(srna, "texture_mix", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_TEX_MIX);
+ RNA_def_property_ui_text(prop, "Mix Texture", "Mix texture image with filling colors");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ prop = RNA_def_property(srna, "flip", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_FLIP_FILL);
+ RNA_def_property_ui_text(prop, "Flip", "Flip filling colors");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ prop = RNA_def_property(srna, "use_stroke_pattern", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_STROKE_PATTERN);
+ RNA_def_property_ui_text(prop, "Pattern", "Use Stroke Texture as a pattern to apply color");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ prop = RNA_def_property(srna, "use_fill_pattern", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_FILL_PATTERN);
+ RNA_def_property_ui_text(prop, "Pattern", "Use Fill Texture as a pattern to apply color");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* pass index for future compositing and editing tools */
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "index");
+ RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Color Index\" pass");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
+
+ /* mode type */
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, gpcolordata_mode_types_items);
+ RNA_def_property_ui_text(prop, "Mode Type", "Select draw mode for stroke");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* stroke style */
+ prop = RNA_def_property(srna, "stroke_style", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "stroke_style");
+ RNA_def_property_enum_items(prop, stroke_style_items);
+ RNA_def_property_ui_text(prop, "Stroke Style", "Select style used to draw strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* stroke image texture */
+ prop = RNA_def_property(srna, "stroke_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "sima");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_GpencilColorData_stroke_image_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Image", "");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* fill style */
+ prop = RNA_def_property(srna, "fill_style", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "fill_style");
+ RNA_def_property_enum_items(prop, fill_style_items);
+ RNA_def_property_ui_text(prop, "Fill Style", "Select style used to fill strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* gradient type */
+ prop = RNA_def_property(srna, "gradient_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "gradient_type");
+ RNA_def_property_enum_items(prop, fill_gradient_items);
+ RNA_def_property_ui_text(prop, "Gradient Type", "Select type of gradient used to fill strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* fill image texture */
+ prop = RNA_def_property(srna, "fill_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ima");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_GpencilColorData_fill_image_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Image", "");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
+ /* Read-only state props (for simpler UI code) */
+ prop = RNA_def_property(srna, "is_stroke_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GpencilColorData_is_stroke_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Stroke Visible", "True when opacity of stroke is set high enough to be visible");
+
+ prop = RNA_def_property(srna, "is_fill_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_GpencilColorData_is_fill_visible_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Fill Visible", "True when opacity of fill is set high enough to be visible");
+
+}
+
void RNA_def_material(BlenderRNA *brna)
{
StructRNA *srna;
@@ -363,11 +688,6 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Screen Space Refraction", "Use raytraced screen space refractions");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
- prop = RNA_def_property(srna, "use_screen_subsurface", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_SS_SUBSURFACE);
- RNA_def_property_ui_text(prop, "Screen Space Subsurface Scattering", "Use post process subsurface scattering");
- RNA_def_property_update(prop, 0, "rna_Material_draw_update");
-
prop = RNA_def_property(srna, "use_sss_translucency", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_TRANSLUCENCY);
RNA_def_property_ui_text(prop, "Subsurface Translucency", "Add translucency effect to subsurface");
@@ -410,6 +730,19 @@ void RNA_def_material(BlenderRNA *brna)
rna_def_material_display(srna);
+ /* grease pencil */
+ prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "gp_style");
+ RNA_def_property_ui_text(prop, "Grease Pencil Settings", "Grease pencil color settings for material");
+
+ prop = RNA_def_property(srna, "is_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_is_grease_pencil_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Grease Pencil", "True if this material has grease pencil data");
+
+ rna_def_material_greasepencil(brna);
+
+
RNA_api_material(srna);
}
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 92b7fd1760f..50f2d49c1b5 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3140,7 +3140,9 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
prop = RNA_def_property(srna, "use_root", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MVERT_SKIN_ROOT);
- RNA_def_property_ui_text(prop, "Root", "Vertex is a root for rotation calculations and armature generation");
+ RNA_def_property_ui_text(prop, "Root",
+ "Vertex is a root for rotation calculations and armature generation, "
+ "setting this flag does not clear other roots in the same mesh island");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "use_loose", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index a25684b0f80..5d9ca8c6f4e 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -68,6 +68,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
{eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""},
{eModifierType_MeshSequenceCache, "MESH_SEQUENCE_CACHE", ICON_MOD_MESHDEFORM, "Mesh Sequence Cache", ""},
{eModifierType_NormalEdit, "NORMAL_EDIT", ICON_MOD_NORMALEDIT, "Normal Edit", ""},
+ {eModifierType_WeightedNormal, "WEIGHTED_NORMAL", ICON_MOD_NORMALEDIT, "Weighted Normal", ""},
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
{eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""},
{eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Edit", ""},
@@ -421,6 +422,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_MeshSequenceCacheModifier;
case eModifierType_SurfaceDeform:
return &RNA_SurfaceDeformModifier;
+ case eModifierType_WeightedNormal:
+ return &RNA_WeightedNormalModifier;
case eModifierType_Hair:
return &RNA_HairModifier;
/* Default */
@@ -513,6 +516,7 @@ RNA_MOD_VGROUP_NAME_SET(WeightVGMix, defgrp_name_b);
RNA_MOD_VGROUP_NAME_SET(WeightVGMix, mask_defgrp_name);
RNA_MOD_VGROUP_NAME_SET(WeightVGProximity, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(WeightVGProximity, mask_defgrp_name);
+RNA_MOD_VGROUP_NAME_SET(WeightedNormal, defgrp_name);
RNA_MOD_VGROUP_NAME_SET(Wireframe, defgrp_name);
static void rna_ExplodeModifier_vgroup_get(PointerRNA *ptr, char *value)
@@ -1236,8 +1240,8 @@ static void rna_Hair_fiber_curves_apply(ID *id, HairModifierData *hmd, bContext
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
{
static const EnumPropertyItem prop_subdivision_type_items[] = {
- {0, "CATMULL_CLARK", 0, "Catmull-Clark", ""},
- {1, "SIMPLE", 0, "Simple", ""},
+ {SUBSURF_TYPE_CATMULL_CLARK, "CATMULL_CLARK", 0, "Catmull-Clark", ""},
+ {SUBSURF_TYPE_SIMPLE, "SIMPLE", 0, "Simple", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3062,6 +3066,14 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_harden_normals_items[] = {
+ { MOD_BEVEL_HN_NONE, "HN_NONE", 0, "Off", "Do not use Harden Normals" },
+ { MOD_BEVEL_HN_FACE, "HN_FACE", 0, "Face Area", "Use faces as weight" },
+ { MOD_BEVEL_HN_ADJ, "HN_ADJ", 0, "Vertex average", "Use adjacent vertices as weight" },
+ { MOD_BEVEL_FIX_SHA, "FIX_SHA", 0, "Fix shading", "Fix normal shading continuity" },
+ { 0, NULL, 0, NULL, NULL },
+ };
+
srna = RNA_def_struct(brna, "BevelModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Bevel Modifier", "Bevel modifier to make edges and vertices more rounded");
RNA_def_struct_sdna(srna, "BevelModifierData");
@@ -3138,6 +3150,33 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "flags", MOD_BEVEL_EVEN_WIDTHS);
RNA_def_property_ui_text(prop, "Loop Slide", "Prefer sliding along edges to having even widths");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mark_seam", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_flags", MOD_BEVEL_MARK_SEAM);
+ RNA_def_property_ui_text(prop, "Mark Seams", "Mark Seams along beveled edges");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mark_sharp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_flags", MOD_BEVEL_MARK_SHARP);
+ RNA_def_property_ui_text(prop, "Mark Sharp", "Mark beveled edges as sharp");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "hnmode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_harden_normals_items);
+ RNA_def_property_ui_text(prop, "Normal Mode", "Weighting mode for Harden Normals");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "hn_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_range(prop, 0, 1, 1, 2);
+ RNA_def_property_ui_text(prop, "Normal Strength", "Strength of calculated normal");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "set_wn_strength", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_BEVEL_SET_WN_STR);
+ RNA_def_property_ui_text(prop, "Face Strength", "Set face strength of beveled faces for use in WN Modifier");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
@@ -4984,6 +5023,68 @@ static void rna_def_modifier_hair_fiber_curves_api(BlenderRNA *brna, PropertyRNA
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
}
+static void rna_def_modifier_weightednormal(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_weighting_mode_items[] = {
+ {MOD_WEIGHTEDNORMAL_MODE_FACE, "FACE_AREA", 0, "Face Area", "Generate face area weighted normals"},
+ {MOD_WEIGHTEDNORMAL_MODE_ANGLE, "CORNER_ANGLE", 0, "Corner Angle", "Generate corner angle weighted normals"},
+ {MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE, "FACE_AREA_WITH_ANGLE", 0, "Face Area And Angle",
+ "Generated normals weighted by both face area and angle"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "WeightedNormalModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "WeightedNormal Modifier", "");
+ RNA_def_struct_sdna(srna, "WeightedNormalModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+
+ prop = RNA_def_property(srna, "weight", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 1, 100, 1, -1);
+ RNA_def_property_ui_text(prop, "Weight",
+ "Corrective factor applied to faces' weights, 50 is neutral, "
+ "lower values increase weight of weak faces, "
+ "higher values increase weight of strong faces");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_weighting_mode_items);
+ RNA_def_property_ui_text(prop, "Weighting Mode", "Weighted vertex normal mode to use");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "thresh", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_range(prop, 0, 10, 1, 2);
+ RNA_def_property_ui_text(prop, "Threshold", "Threshold value for different weights to be considered equal");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "keep_sharp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_KEEP_SHARP);
+ RNA_def_property_ui_text(prop, "Keep Sharp",
+ "Keep sharp edges as computed for default split normals, "
+ "instead of setting a single weighted normal for each vertex.");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modifying the selected areas");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightedNormalModifier_defgrp_name_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "face_influence", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_FACE_INFLUENCE);
+ RNA_def_property_ui_text(prop, "Face Influence", "Use influence of face for weighting");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
static void rna_def_modifier_hair(BlenderRNA *brna)
{
StructRNA *srna;
@@ -5142,6 +5243,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_normaledit(brna);
rna_def_modifier_meshseqcache(brna);
rna_def_modifier_surfacedeform(brna);
+ rna_def_modifier_weightednormal(brna);
rna_def_modifier_hair(brna);
}
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index aded4229a3c..81c3c9b43b9 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -338,6 +338,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index c0eda3dc053..a6172bd9cc2 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -2874,6 +2874,48 @@ static void rna_NodeColorBalance_update_cdl(Main *bmain, Scene *scene, PointerRN
rna_Node_update(bmain, scene, ptr);
}
+static void rna_NodeCryptomatte_matte_get(PointerRNA *ptr, char *value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeCryptomatte *nc = node->storage;
+
+ strcpy(value, (nc->matte_id) ? nc->matte_id : "");
+}
+
+static int rna_NodeCryptomatte_matte_length(PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeCryptomatte *nc = node->storage;
+
+ return (nc->matte_id) ? strlen(nc->matte_id) : 0;
+}
+
+static void rna_NodeCryptomatte_matte_set(PointerRNA *ptr, const char *value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeCryptomatte *nc = node->storage;
+
+ if (nc->matte_id)
+ MEM_freeN(nc->matte_id);
+
+ if (value && value[0])
+ nc->matte_id = BLI_strdup(value);
+ else
+ nc->matte_id = NULL;
+}
+
+static void rna_NodeCryptomatte_update_add(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ntreeCompositCryptomatteSyncFromAdd(ptr->id.data, ptr->data);
+ rna_Node_update(bmain, scene, ptr);
+}
+
+static void rna_NodeCryptomatte_update_remove(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ ntreeCompositCryptomatteSyncFromRemove(ptr->id.data, ptr->data);
+ rna_Node_update(bmain, scene, ptr);
+}
+
/* ******** Node Socket Types ******** */
static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator *iter)
@@ -3297,6 +3339,13 @@ static const EnumPropertyItem node_hair_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static const EnumPropertyItem node_principled_hair_items[] = {
+ {SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION, "ABSORPTION", 0, "Absorption coefficient", "Directly set the absorption coefficient sigma_a. This is not the most intuitive way to color hair."},
+ {SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION, "MELANIN", 0, "Melanin concentration", "Define the melanin concentrations below to get the most realistic-looking hair. You can get the concentrations for different types of hair online."},
+ {SHD_PRINCIPLED_HAIR_REFLECTANCE, "COLOR", 0, "Direct coloring", "Choose the color of your preference, and the shader will approximate the absorption coefficient to render lookalike hair."},
+ {0, NULL, 0, NULL, NULL}
+};
+
static const EnumPropertyItem node_script_mode_items[] = {
{NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text data-block"},
{NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or .oso file"},
@@ -4295,6 +4344,21 @@ static void def_hair(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+/* RNA initialization for the custom property. */
+static void def_hair_principled(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "parametrization", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_ui_text(prop, "Color parametrization", "Select the shader's color parametrization");
+ RNA_def_property_enum_items(prop, node_principled_hair_items);
+ RNA_def_property_enum_default(prop, SHD_PRINCIPLED_HAIR_REFLECTANCE);
+ /* Upon editing, update both the node data AND the UI representation */
+ /* (This effectively shows/hides the relevant sockets) */
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
+}
+
static void def_sh_uvmap(StructRNA *srna)
{
PropertyRNA *prop;
@@ -6905,6 +6969,33 @@ static void def_cmp_sunbeams(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_cryptomatte(StructRNA *srna)
+{
+ PropertyRNA *prop;
+ static float default_1[3] = {1.f, 1.f, 1.f};
+
+ RNA_def_struct_sdna_from(srna, "NodeCryptomatte", "storage");
+ prop = RNA_def_property(srna, "matte_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(
+ prop, "rna_NodeCryptomatte_matte_get", "rna_NodeCryptomatte_matte_length",
+ "rna_NodeCryptomatte_matte_set");
+ RNA_def_property_ui_text(prop, "Matte Objects", "List of object and material crypto IDs to include in matte");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+
+ prop = RNA_def_property(srna, "add", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_array_default(prop, default_1);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Add", "Add object or material to matte, by picking a color from the Pick output");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeCryptomatte_update_add");
+
+ prop = RNA_def_property(srna, "remove", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_array_default(prop, default_1);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Remove", "Remove object or material from matte, by picking a color from the Pick output");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeCryptomatte_update_remove");
+}
+
/* -- Texture Nodes --------------------------------------------------------- */
static void def_tex_output(StructRNA *srna)
@@ -8267,6 +8358,7 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block");
RNA_def_property_update(prop, NC_NODE, NULL);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 2bdfbade53a..2d1814532a2 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -37,6 +37,8 @@
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
#include "DNA_workspace_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_shader_fx_types.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
@@ -71,7 +73,10 @@ const EnumPropertyItem rna_enum_object_mode_items[] = {
{OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
{OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""},
- {OB_MODE_GPENCIL, "GPENCIL_EDIT", ICON_GREASEPENCIL, "Edit Strokes", "Edit Grease Pencil Strokes"},
+ {OB_MODE_GPENCIL_EDIT, "GPENCIL_EDIT", ICON_EDITMODE_HLT, "Edit Mode", "Edit Grease Pencil Strokes"},
+ {OB_MODE_GPENCIL_SCULPT, "GPENCIL_SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", "Sculpt Grease Pencil Strokes"},
+ {OB_MODE_GPENCIL_PAINT, "GPENCIL_PAINT", ICON_GREASEPENCIL, "Draw", "Paint Grease Pencil Strokes"},
+ {OB_MODE_GPENCIL_WEIGHT, "GPENCIL_WEIGHT", ICON_WPAINT_HLT, "Weight Paint", "Grease Pencil Weight Paint Strokes" },
{0, NULL, 0, NULL, NULL}
};
@@ -87,6 +92,12 @@ const EnumPropertyItem rna_enum_object_empty_drawtype_items[] = {
{0, NULL, 0, NULL, NULL}
};
+const EnumPropertyItem rna_enum_object_gpencil_type_items[] = {
+ { GP_EMPTY, "EMPTY", ICON_OUTLINER_OB_GREASEPENCIL, "Blank", "Create an empty grease pencil object" },
+ { GP_STROKE, "STROKE", ICON_OUTLINER_OB_CURVE, "Stroke", "Create a simple stroke with basic colors" },
+ { GP_MONKEY, "MONKEY", ICON_MONKEY, "Monkey", "Construct a Suzanne grease pencil object" },
+ { 0, NULL, 0, NULL, NULL }
+};
static const EnumPropertyItem parent_type_items[] = {
{PAROBJECT, "OBJECT", 0, "Object", "The object is parented to an object"},
@@ -144,6 +155,7 @@ const EnumPropertyItem rna_enum_object_type_items[] = {
{OB_ARMATURE, "ARMATURE", 0, "Armature", ""},
{OB_LATTICE, "LATTICE", 0, "Lattice", ""},
{OB_EMPTY, "EMPTY", 0, "Empty", ""},
+ {OB_GPENCIL, "GPENCIL", 0, "GPencil", ""},
{0, "", 0, NULL, NULL},
{OB_CAMERA, "CAMERA", 0, "Camera", ""},
{OB_LAMP, "LIGHT", 0, "Light", ""},
@@ -175,6 +187,7 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
#include "DNA_key_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_ID.h"
#include "DNA_lattice_types.h"
#include "DNA_node_types.h"
@@ -356,10 +369,12 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
ob->data = id;
test_object_materials(G_MAIN, ob, id);
- if (GS(id->name) == ID_CU)
+ if (GS(id->name) == ID_CU) {
BKE_curve_type_test(ob);
- else if (ob->type == OB_ARMATURE)
- BKE_pose_rebuild(ob, ob->data);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ BKE_pose_rebuild(G_MAIN, ob, ob->data, true);
+ }
}
}
@@ -381,10 +396,24 @@ static StructRNA *rna_Object_data_typef(PointerRNA *ptr)
case OB_ARMATURE: return &RNA_Armature;
case OB_SPEAKER: return &RNA_Speaker;
case OB_LIGHTPROBE: return &RNA_LightProbe;
+ case OB_GPENCIL: return &RNA_GreasePencil;
default: return &RNA_ID;
}
}
+static bool rna_Object_data_poll(PointerRNA *ptr, const PointerRNA value)
+{
+ Object *ob = (Object *)ptr->data;
+
+ if (ob->type == OB_GPENCIL) {
+ /* GP Object - Don't allow using "Annotation" GP datablocks here */
+ bGPdata *gpd = value.data;
+ return (gpd->flag & GP_DATA_ANNOTATIONS) == 0;
+ }
+
+ return true;
+}
+
static void rna_Object_parent_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->data;
@@ -940,6 +969,21 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr, PointerRNA value)
assign_material(G_MAIN, ob, value.data, index + 1, BKE_MAT_ASSIGN_EXISTING);
}
+static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ Material *ma = (Material *)value.data;
+
+ if (ob->type == OB_GPENCIL) {
+ /* GP Materials only */
+ return (ma->gp_style != NULL);
+ }
+ else {
+ /* Everything except GP materials */
+ return (ma->gp_style == NULL);
+ }
+}
+
static int rna_MaterialSlot_link_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
@@ -1005,7 +1049,6 @@ static char *rna_MaterialSlot_path(PointerRNA *ptr)
Object *ob = (Object *)ptr->id.data;
int index = (Material **)ptr->data - ob->mat;
- /* from armature... */
return BLI_sprintfN("material_slots[%d]", index);
}
@@ -1273,6 +1316,61 @@ bool rna_Object_modifiers_override_apply(
return true;
}
+static GpencilModifierData *rna_Object_greasepencil_modifier_new(
+ Object *object, bContext *C, ReportList *reports,
+ const char *name, int type)
+{
+ return ED_object_gpencil_modifier_add(reports, CTX_data_main(C), CTX_data_scene(C), object, name, type);
+}
+
+static void rna_Object_greasepencil_modifier_remove(
+ Object *object, bContext *C, ReportList *reports, PointerRNA *gmd_ptr)
+{
+ GpencilModifierData *gmd = gmd_ptr->data;
+ if (ED_object_gpencil_modifier_remove(reports, CTX_data_main(C), object, gmd) == false) {
+ /* error is already set */
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(gmd_ptr);
+
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
+}
+
+static void rna_Object_greasepencil_modifier_clear(Object *object, bContext *C)
+{
+ ED_object_gpencil_modifier_clear(CTX_data_main(C), object);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
+}
+
+/* shader fx */
+static ShaderFxData *rna_Object_shaderfx_new(
+ Object *object, bContext *C, ReportList *reports,
+ const char *name, int type)
+{
+ return ED_object_shaderfx_add(reports, CTX_data_main(C), CTX_data_scene(C), object, name, type);
+}
+
+static void rna_Object_shaderfx_remove(
+ Object *object, bContext *C, ReportList *reports, PointerRNA *gmd_ptr)
+{
+ ShaderFxData *gmd = gmd_ptr->data;
+ if (ED_object_shaderfx_remove(reports, CTX_data_main(C), object, gmd) == false) {
+ /* error is already set */
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(gmd_ptr);
+
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
+}
+
+static void rna_Object_shaderfx_clear(Object *object, bContext *C)
+{
+ ED_object_shaderfx_clear(CTX_data_main(C), object);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
+}
+
static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
{
Object *ob = (Object *)ptr->id.data;
@@ -1451,6 +1549,11 @@ bool rna_Light_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
return ((Object *)value.id.data)->type == OB_LAMP;
}
+bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
+{
+ return ((Object *)value.id.data)->type == OB_GPENCIL;
+}
+
int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
{
SculptSession *ss = ((Object *)ptr->id.data)->sculpt;
@@ -1599,7 +1702,7 @@ static void rna_def_material_slot(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_editable_func(prop, "rna_MaterialSlot_material_editable");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_pointer_funcs(prop, "rna_MaterialSlot_material_get", "rna_MaterialSlot_material_set", NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_MaterialSlot_material_get", "rna_MaterialSlot_material_set", NULL, "rna_MaterialSlot_material_poll");
RNA_def_property_ui_text(prop, "Material", "Material data-block used by this material slot");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_MaterialSlot_update");
@@ -1713,6 +1816,88 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Remove all modifiers from the object");
}
+/* object.grease_pencil_modifiers */
+static void rna_def_object_grease_pencil_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "ObjectGpencilModifiers");
+ srna = RNA_def_struct(brna, "ObjectGpencilModifiers", NULL);
+ RNA_def_struct_sdna(srna, "Object");
+ RNA_def_struct_ui_text(srna, "Object Grease Pencil Modifiers", "Collection of object grease pencil modifiers");
+
+ /* add greasepencil modifier */
+ func = RNA_def_function(srna, "new", "rna_Object_greasepencil_modifier_new");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Add a new greasepencil_modifier");
+ parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the greasepencil_modifier");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* greasepencil_modifier to add */
+ parm = RNA_def_enum(func, "type", rna_enum_object_greasepencil_modifier_type_items, 1, "", "Modifier type to add");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "greasepencil_modifier", "GpencilModifier", "", "Newly created modifier");
+ RNA_def_function_return(func, parm);
+
+ /* remove greasepencil_modifier */
+ func = RNA_def_function(srna, "remove", "rna_Object_greasepencil_modifier_remove");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove an existing greasepencil_modifier from the object");
+ /* greasepencil_modifier to remove */
+ parm = RNA_def_pointer(func, "greasepencil_modifier", "GpencilModifier", "", "Modifier to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ /* clear all greasepencil modifiers */
+ func = RNA_def_function(srna, "clear", "rna_Object_greasepencil_modifier_clear");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Remove all grease pencil modifiers from the object");
+}
+
+/* object.shaderfxs */
+static void rna_def_object_shaderfxs(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "ObjectShaderFx");
+ srna = RNA_def_struct(brna, "ObjectShaderFx", NULL);
+ RNA_def_struct_sdna(srna, "Object");
+ RNA_def_struct_ui_text(srna, "Object Shader Effects", "Collection of object effects");
+
+ /* add shader_fx */
+ func = RNA_def_function(srna, "new", "rna_Object_shaderfx_new");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Add a new shader fx");
+ parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the effect");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* shader to add */
+ parm = RNA_def_enum(func, "type", rna_enum_object_shaderfx_type_items, 1, "", "Effect type to add");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "shader_fx", "ShaderFx", "", "Newly created effect");
+ RNA_def_function_return(func, parm);
+
+ /* remove shader_fx */
+ func = RNA_def_function(srna, "remove", "rna_Object_shaderfx_remove");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove an existing effect from the object");
+ /* shader to remove */
+ parm = RNA_def_pointer(func, "shader_fx", "ShaderFx", "", "Effect to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ /* clear all shader fx */
+ func = RNA_def_function(srna, "clear", "rna_Object_shaderfx_clear");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Remove all effects from the object");
+}
+
/* object.particle_systems */
static void rna_def_object_particle_systems(BlenderRNA *brna, PropertyRNA *cprop)
{
@@ -1917,7 +2102,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", NULL);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", "rna_Object_data_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Data", "Object data");
@@ -2015,7 +2200,8 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "active_material", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_pointer_funcs(prop, "rna_Object_active_material_get",
- "rna_Object_active_material_set", NULL, NULL);
+ "rna_Object_active_material_set", NULL,
+ "rna_MaterialSlot_material_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_editable_func(prop, "rna_Object_active_material_editable");
@@ -2209,6 +2395,20 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC | PROPOVERRIDE_STATIC_INSERTION);
rna_def_object_modifiers(brna, prop);
+ /* Grease Pencil modifiers. */
+ prop = RNA_def_property(srna, "grease_pencil_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "greasepencil_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "GpencilModifier");
+ RNA_def_property_ui_text(prop, "Grease Pencil Modifiers", "Modifiers affecting the data of the grease pencil object");
+ rna_def_object_grease_pencil_modifiers(brna, prop);
+
+ /* Shader FX. */
+ prop = RNA_def_property(srna, "shader_effects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "shader_fx", NULL);
+ RNA_def_property_struct_type(prop, "ShaderFx");
+ RNA_def_property_ui_text(prop, "Shader Effects", "Effects affecting display of object");
+ rna_def_object_shaderfxs(brna, prop);
+
/* constraints */
prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Constraint");
@@ -2480,12 +2680,15 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
/* Grease Pencil */
+#if 1 /* FIXME: Remove this code when all Open-Movie assets have been fixed */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_obdata_poll"); /* XXX */
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
- RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block");
+ RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block (deprecated)");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+#endif
/* pose */
prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 1a2b3854668..3adf9f790d9 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -128,11 +128,11 @@ static bool rna_Object_select_get(Object *ob, bContext *C, ReportList *reports)
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
- return -1;
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return false;
}
- return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0;
+ return ((base->flag & BASE_SELECTED) != 0);
}
static bool rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
@@ -141,11 +141,35 @@ static bool rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
- return -1;
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return false;
+ }
+
+ return ((base->flag & BASE_VISIBLE) != 0);
+}
+
+static bool rna_Object_holdout_get(Object *ob, ReportList *reports, ViewLayer *view_layer)
+{
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return false;
}
- return ((base->flag & BASE_VISIBLE) != 0) ? 1 : 0;
+ return ((base->flag & BASE_HOLDOUT) != 0);
+}
+
+static bool rna_Object_indirect_only_get(Object *ob, ReportList *reports, ViewLayer *view_layer)
+{
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return false;
+ }
+
+ return ((base->flag & BASE_INDIRECT_ONLY) != 0);
}
/* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
@@ -309,8 +333,10 @@ static void rna_Object_ray_cast(
/* Test BoundBox first (efficiency) */
BoundBox *bb = BKE_object_boundbox_get(ob);
float distmin;
- if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) {
-
+ normalize_v3(direction); /* Needed for valid distance check from isect_ray_aabb_v3_simple() call. */
+ if (!bb ||
+ (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance))
+ {
BVHTreeFromMesh treeData = {NULL};
/* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
@@ -323,9 +349,6 @@ static void rna_Object_ray_cast(
hit.index = -1;
hit.dist = distance;
- normalize_v3(direction);
-
-
if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
treeData.raycast_callback, &treeData) != -1)
{
@@ -470,31 +493,47 @@ void RNA_api_object(StructRNA *srna)
#endif
static EnumPropertyItem object_select_items[] = {
- {0, "SELECT", 0, "Select", "Select object from the active render layer"},
- {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"},
- {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"},
+ {0, "SELECT", 0, "Select", "Select object from the active view layer"},
+ {1, "DESELECT", 0, "Deselect", "Deselect object from the active view layer"},
+ {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active view layer"},
{0, NULL, 0, NULL, NULL}
};
/* Special wrapper to access the base selection value */
func = RNA_def_function(srna, "select_set", "rna_Object_select_set");
- RNA_def_function_ui_description(func, "Select the object (for the active render layer)");
+ RNA_def_function_ui_description(func, "Select the object (for the active view layer)");
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "select_get", "rna_Object_select_get");
- RNA_def_function_ui_description(func, "Get the object selection for the active render layer");
+ RNA_def_function_ui_description(func, "Get the object selection for the active view layer");
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
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_ui_description(func, "Get the object visibility for the active view 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);
+ func = RNA_def_function(srna, "holdout_get", "rna_Object_holdout_get");
+ RNA_def_function_ui_description(func, "Test if object is masked in the view layer");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object holdout");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "indirect_only_get", "rna_Object_indirect_only_get");
+ RNA_def_function_ui_description(func, "Test if object is set to contribute only indirectly (through shadows and reflections) in the view layer");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object indirect only");
+ RNA_def_function_return(func, parm);
+
/* Matrix space conversion */
func = RNA_def_function(srna, "convert_space", "rna_Object_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_palette.c b/source/blender/makesrna/intern/rna_palette.c
index 4d6b94bf709..547cac9f38d 100644
--- a/source/blender/makesrna/intern/rna_palette.c
+++ b/source/blender/makesrna/intern/rna_palette.c
@@ -39,7 +39,6 @@
#include "BKE_paint.h"
#include "BKE_report.h"
-
static PaletteColor *rna_Palette_color_new(Palette *palette)
{
PaletteColor *color = BKE_palette_color_add(palette);
@@ -139,6 +138,7 @@ static void rna_def_palettecolor(BlenderRNA *brna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
@@ -153,6 +153,7 @@ static void rna_def_palettecolor(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "value");
RNA_def_property_ui_text(prop, "Weight", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
}
static void rna_def_palette(BlenderRNA *brna)
@@ -167,6 +168,7 @@ static void rna_def_palette(BlenderRNA *brna)
prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "PaletteColor");
rna_def_palettecolors(brna, prop);
+
}
void RNA_def_palette(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 4b8299b9245..979e5d433e7 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -1132,6 +1132,9 @@ static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int
static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str)
{
+ ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ psys_find_group_weights(part);
+
ParticleDupliWeight *dw = ptr->data;
if (dw->ob)
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 592f8ee38c0..899439e1a02 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -76,6 +76,12 @@ const EnumPropertyItem rna_enum_rigidbody_constraint_type_items[] = {
{RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"},
{0, NULL, 0, NULL, NULL}};
+/* bullet spring type */
+static const EnumPropertyItem rna_enum_rigidbody_constraint_spring_type_items[] = {
+ {RBC_SPRING_TYPE1, "SPRING1", ICON_NONE, "Blender 2.7", "Spring implementation used in blender 2.7. Damping is capped at 1.0"},
+ {RBC_SPRING_TYPE2, "SPRING2", ICON_NONE, "Blender 2.8", "New implementation available since 2.8"},
+ {0, NULL, 0, NULL, NULL}};
+
#ifndef RNA_RUNTIME
/* mesh source for collision shape creation */
static const EnumPropertyItem rigidbody_mesh_source_items[] = {
@@ -375,6 +381,14 @@ static void rna_RigidBodyCon_type_set(PointerRNA *ptr, int value)
rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
}
+static void rna_RigidBodyCon_spring_type_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_type = value;
+ rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
+}
+
static void rna_RigidBodyCon_enabled_set(PointerRNA *ptr, bool value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@@ -467,6 +481,22 @@ static void rna_RigidBodyCon_num_solver_iterations_set(PointerRNA *ptr, int valu
#endif
}
+#ifdef WITH_BULLET
+static void rna_RigidBodyCon_do_set_spring_stiffness(RigidBodyCon *rbc, float value, int flag, int axis)
+{
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) {
+ switch (rbc->spring_type) {
+ case RBC_SPRING_TYPE1:
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, axis, value);
+ break;
+ case RBC_SPRING_TYPE2:
+ RB_constraint_set_stiffness_6dof_spring2(rbc->physics_constraint, axis, value);
+ break;
+ }
+ }
+}
+#endif
+
static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@@ -474,9 +504,7 @@ static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value
rbc->spring_stiffness_x = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X);
#endif
}
@@ -487,9 +515,7 @@ static void rna_RigidBodyCon_spring_stiffness_y_set(PointerRNA *ptr, float value
rbc->spring_stiffness_y = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y);
#endif
}
@@ -500,9 +526,7 @@ static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value
rbc->spring_stiffness_z = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z);
#endif
}
@@ -513,9 +537,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_x_set(PointerRNA *ptr, float v
rbc->spring_stiffness_ang_x = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X);
#endif
}
@@ -526,9 +548,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_y_set(PointerRNA *ptr, float v
rbc->spring_stiffness_ang_y = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y);
#endif
}
@@ -539,12 +559,26 @@ static void rna_RigidBodyCon_spring_stiffness_ang_z_set(PointerRNA *ptr, float v
rbc->spring_stiffness_ang_z = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) {
- RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value);
- }
+ rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z);
#endif
}
+#ifdef WITH_BULLET
+static void rna_RigidBodyCon_do_set_spring_damping(RigidBodyCon *rbc, float value, int flag, int axis)
+{
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) {
+ switch (rbc->spring_type) {
+ case RBC_SPRING_TYPE1:
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, axis, value);
+ break;
+ case RBC_SPRING_TYPE2:
+ RB_constraint_set_damping_6dof_spring2(rbc->physics_constraint, axis, value);
+ break;
+ }
+ }
+}
+#endif
+
static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value)
{
RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
@@ -552,9 +586,7 @@ static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value)
rbc->spring_damping_x = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X);
#endif
}
@@ -564,9 +596,7 @@ static void rna_RigidBodyCon_spring_damping_y_set(PointerRNA *ptr, float value)
rbc->spring_damping_y = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y);
#endif
}
@@ -576,9 +606,7 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value)
rbc->spring_damping_z = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z);
#endif
}
@@ -589,9 +617,7 @@ static void rna_RigidBodyCon_spring_damping_ang_x_set(PointerRNA *ptr, float val
rbc->spring_damping_ang_x = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X);
#endif
}
@@ -601,9 +627,7 @@ static void rna_RigidBodyCon_spring_damping_ang_y_set(PointerRNA *ptr, float val
rbc->spring_damping_ang_y = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y);
#endif
}
@@ -613,9 +637,7 @@ static void rna_RigidBodyCon_spring_damping_ang_z_set(PointerRNA *ptr, float val
rbc->spring_damping_ang_z = value;
#ifdef WITH_BULLET
- if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) {
- RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value);
- }
+ rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z);
#endif
}
@@ -1031,6 +1053,14 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+ prop = RNA_def_property(srna, "spring_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "spring_type");
+ RNA_def_property_enum_items(prop, rna_enum_rigidbody_constraint_spring_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyCon_spring_type_set", NULL);
+ RNA_def_property_ui_text(prop, "Spring Type", "Which implementation of spring to use");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_ENABLED);
RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_enabled_set");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index f8d6757c601..21731a54aa1 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -51,6 +51,7 @@
#include "BKE_paint.h"
#include "ED_object.h"
+#include "ED_gpencil.h"
#include "GPU_extensions.h"
@@ -165,6 +166,14 @@ const EnumPropertyItem rna_enum_mesh_select_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[] = {
+ {UV_SELECT_VERTEX, "VERTEX", ICON_UV_VERTEXSEL, "Vertex", "Vertex selection mode"},
+ {UV_SELECT_EDGE, "EDGE", ICON_UV_EDGESEL, "Edge", "Edge selection mode"},
+ {UV_SELECT_FACE, "FACE", ICON_UV_FACESEL, "Face", "Face selection mode"},
+ {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"},
+ {0, NULL, 0, NULL, NULL}
+};
+
const EnumPropertyItem rna_enum_snap_element_items[] = {
{SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"},
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
@@ -522,6 +531,27 @@ static const EnumPropertyItem transform_orientation_items[] = {
#include "FRS_freestyle.h"
#endif
+/* Grease Pencil update cache */
+static void rna_GPencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ /* mark all grease pencil datablocks of the scene */
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
+ {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
+ {
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+}
+
/* Grease Pencil Interpolation settings */
static char *rna_GPencilInterpolateSettings_path(PointerRNA *UNUSED(ptr))
{
@@ -543,110 +573,8 @@ static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value)
{
settings->custom_ipo = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-}
-
-/* Grease pencil Drawing Brushes */
-static bGPDbrush *rna_GPencil_brush_new(ToolSettings *ts, const char *name, bool setactive)
-{
- bGPDbrush *brush = BKE_gpencil_brush_addnew(ts, name, setactive != 0);
-
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return brush;
-}
-
-static void rna_GPencil_brush_remove(ToolSettings *ts, ReportList *reports, PointerRNA *brush_ptr)
-{
- bGPDbrush *brush = brush_ptr->data;
- if (BLI_findindex(&ts->gp_brushes, brush) == -1) {
- BKE_report(reports, RPT_ERROR, "Brush not found in grease pencil data");
- return;
- }
-
- BKE_gpencil_brush_delete(ts, brush);
- RNA_POINTER_INVALIDATE(brush_ptr);
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-
-static PointerRNA rna_GPencilBrushes_active_get(PointerRNA *ptr)
-{
- ToolSettings *ts = (ToolSettings *) ptr->data;
-
- bGPDbrush *brush;
-
- for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
- if (brush->flag & GP_BRUSH_ACTIVE) {
- break;
- }
- }
-
- if (brush) {
- return rna_pointer_inherit_refine(ptr, &RNA_GPencilBrush, brush);
- }
-
- return rna_pointer_inherit_refine(ptr, NULL, NULL);
-}
-
-static void rna_GPencilBrushes_active_set(PointerRNA *ptr, PointerRNA value)
-{
- ToolSettings *ts = (ToolSettings *) ptr->data;
-
- bGPDbrush *brush;
-
- for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
- if (brush == value.data) {
- brush->flag |= GP_BRUSH_ACTIVE;
- }
- else {
- brush->flag &= ~GP_BRUSH_ACTIVE;
- }
- }
- WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
-}
-
-static int rna_GPencilBrushes_index_get(PointerRNA *ptr)
-{
- ToolSettings *ts = (ToolSettings *) ptr->data;
- bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
-
- return BLI_findindex(&ts->gp_brushes, brush);
-}
-
-static void rna_GPencilBrushes_index_set(PointerRNA *ptr, int value)
-{
- ToolSettings *ts = (ToolSettings *) ptr->data;
-
- bGPDbrush *brush = BLI_findlink(&ts->gp_brushes, value);
-
- BKE_gpencil_brush_setactive(ts, brush);
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-}
-
-static void rna_GPencilBrushes_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
-{
- ToolSettings *ts = (ToolSettings *) ptr->data;
-
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&ts->gp_brushes) - 1);
-
- *softmin = *min;
- *softmax = *max;
-}
-
-static void rna_GPencilBrush_name_set(PointerRNA *ptr, const char *value)
-{
- ToolSettings *ts = ((Scene *) ptr->id.data)->toolsettings;
- bGPDbrush *brush = ptr->data;
-
- /* copy the new name into the name slot */
- BLI_strncpy_utf8(brush->info, value, sizeof(brush->info));
-
- BLI_uniquename(&ts->gp_brushes, brush, DATA_("GP_Brush"), '.', offsetof(bGPDbrush, info), sizeof(brush->info));
-}
-
-/* ----------------- end of Grease pencil drawing brushes ------------*/
-
static void rna_ToolSettings_gizmo_flag_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
ToolSettings *ts = scene->toolsettings;
@@ -2024,11 +1952,6 @@ static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), Pointer
}
}
-static bool rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr))
-{
- return true;
-}
-
static ViewLayer *rna_ViewLayer_new(
ID *id, Scene *UNUSED(sce), Main *bmain, const char *name)
{
@@ -2187,205 +2110,6 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
-/* Grease Pencil Drawing Brushes */
-static void rna_def_gpencil_brush(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "GPencilBrush", NULL);
- RNA_def_struct_sdna(srna, "bGPDbrush");
- RNA_def_struct_ui_text(srna, "Grease Pencil Brush",
- "Collection of brushes being used to control the line style of new strokes");
- RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
-
- /* Name */
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "info");
- RNA_def_property_ui_text(prop, "Name", "Brush name");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilBrush_name_set");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Line Thickness */
- prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "thickness");
- RNA_def_property_range(prop, 1, 300);
- RNA_def_property_ui_range(prop, 1, 10, 1, 0);
- RNA_def_property_ui_text(prop, "Thickness", "Thickness of strokes (in pixels)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Sensitivity factor for new strokes */
- prop = RNA_def_property(srna, "pen_sensitivity_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_sensitivity");
- RNA_def_property_range(prop, 0.1f, 3.0f);
- RNA_def_property_ui_text(prop, "Sensitivity", "Pressure sensitivity factor for new strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Strength factor for new strokes */
- prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_strength");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Strength", "Color strength for new strokes (affect alpha factor of color)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Jitter factor for new strokes */
- prop = RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_jitter");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Jitter", "Jitter factor for new strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Randomnes factor for sensitivity and strength */
- prop = RNA_def_property(srna, "random_press", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_random_press");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Randomness", "Randomness factor for pressure and strength in new strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Randomnes factor for subdivision */
- prop = RNA_def_property(srna, "random_subdiv", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_random_sub");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Subdivision", "Randomness factor for new strokes after subdivision");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Angle when brush is full size */
- prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_sdna(prop, NULL, "draw_angle");
- RNA_def_property_range(prop, -M_PI_2, M_PI_2);
- RNA_def_property_ui_text(prop, "Angle",
- "Direction of the stroke at which brush gives maximal thickness "
- "(0° for horizontal)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Factor to change brush size depending of angle */
- prop = RNA_def_property(srna, "angle_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_angle_factor");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Angle Factor",
- "Reduce brush thickness by this factor when stroke is perpendicular to 'Angle' direction");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Smoothing factor for new strokes */
- prop = RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "draw_smoothfac");
- RNA_def_property_range(prop, 0.0, 2.0f);
- RNA_def_property_ui_text(prop, "Smooth",
- "Amount of smoothing to apply to newly created strokes, to reduce jitter/noise");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Iterations of the Smoothing factor */
- prop = RNA_def_property(srna, "pen_smooth_steps", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "draw_smoothlvl");
- RNA_def_property_range(prop, 1, 3);
- RNA_def_property_ui_text(prop, "Iterations",
- "Number of times to smooth newly created strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Subdivision level for new strokes */
- prop = RNA_def_property(srna, "pen_subdivision_steps", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "sublevel");
- RNA_def_property_range(prop, 0, 3);
- RNA_def_property_ui_text(prop, "Subdivision Steps",
- "Number of times to subdivide newly created strokes, for less jagged strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Curves for pressure */
- prop = RNA_def_property(srna, "curve_sensitivity", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "cur_sensitivity");
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "curve_strength", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "cur_strength");
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_ui_text(prop, "Curve Strength", "Curve used for the strength");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "curve_jitter", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "cur_jitter");
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_ui_text(prop, "Curve Jitter", "Curve used for the jitter effect");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- /* Flags */
- prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_PRESSURE);
- RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
- RNA_def_property_ui_text(prop, "Use Pressure", "Use tablet pressure");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "use_strength_pressure", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_STENGTH_PRESSURE);
- RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
- RNA_def_property_ui_text(prop, "Use Pressure Strength", "Use tablet pressure for color strength");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "use_jitter_pressure", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_JITTER_PRESSURE);
- RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
- RNA_def_property_ui_text(prop, "Use Pressure Jitter", "Use tablet pressure for jitter");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "use_random_pressure", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_RANDOM_PRESSURE);
- RNA_def_property_ui_icon(prop, ICON_PARTICLES, 0);
- RNA_def_property_ui_text(prop, "Random Pressure", "Use random value for pressure");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
- prop = RNA_def_property(srna, "use_random_strength", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_RANDOM_STRENGTH);
- RNA_def_property_ui_icon(prop, ICON_PARTICLES, 0);
- RNA_def_property_ui_text(prop, "Random Strength", "Use random value for strength");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
-
-}
-
-/* Grease Pencil Drawing Brushes API */
-static void rna_def_gpencil_brushes(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "GreasePencilBrushes");
- srna = RNA_def_struct(brna, "GreasePencilBrushes", NULL);
- RNA_def_struct_sdna(srna, "ToolSettings");
- RNA_def_struct_ui_text(srna, "Grease Pencil Brushes", "Collection of grease pencil brushes");
-
- func = RNA_def_function(srna, "new", "rna_GPencil_brush_new");
- RNA_def_function_ui_description(func, "Add a new grease pencil brush");
- parm = RNA_def_string(func, "name", "GPencilBrush", MAX_NAME, "Name", "Name of the brush");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func, "set_active", 0, "Set Active", "Set the newly created brush to the active brush");
- parm = RNA_def_pointer(func, "palette", "GPencilBrush", "", "The newly created brush");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_GPencil_brush_remove");
- RNA_def_function_ui_description(func, "Remove a grease pencil brush");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "brush", "GPencilBrush", "", "The brush to remove");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GPencilBrush");
- RNA_def_property_pointer_funcs(prop, "rna_GPencilBrushes_active_get", "rna_GPencilBrushes_active_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Active Brush", "Current active brush");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop,
- "rna_GPencilBrushes_index_get",
- "rna_GPencilBrushes_index_set",
- "rna_GPencilBrushes_index_range");
- RNA_def_property_ui_text(prop, "Active Brush Index", "Index of active brush");
-}
-
static void rna_def_transform_orientation(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2409,14 +2133,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem uv_select_mode_items[] = {
- {UV_SELECT_VERTEX, "VERTEX", ICON_UV_VERTEXSEL, "Vertex", "Vertex selection mode"},
- {UV_SELECT_EDGE, "EDGE", ICON_UV_EDGESEL, "Edge", "Edge selection mode"},
- {UV_SELECT_FACE, "FACE", ICON_UV_FACESEL, "Face", "Face selection mode"},
- {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"},
- {0, NULL, 0, NULL, NULL}
- };
-
/* the construction of this enum is quite special - everything is stored as bitflags,
* with 1st position only for for on/off (and exposed as boolean), while others are mutually
* exclusive options but which will only have any effect when autokey is enabled
@@ -2437,6 +2153,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem mod_weighted_strength[] = {
+ {FACE_STRENGTH_WEAK, "Weak", 0, "Weak", ""},
+ {FACE_STRENGTH_MEDIUM, "Medium", 0, "Medium", ""},
+ {FACE_STRENGTH_STRONG, "Strong", 0, "Strong", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem draw_groupuser_items[] = {
{OB_DRAW_GROUPUSER_NONE, "NONE", 0, "None", ""},
{OB_DRAW_GROUPUSER_ACTIVE, "ACTIVE", 0, "Active", "Show vertices with no weights in the active group"},
@@ -2451,21 +2174,20 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem gpencil_source_3d_items[] = {
- {GP_TOOL_SOURCE_SCENE, "SCENE", 0, "Scene",
- "Grease Pencil data attached to the current scene is used, "
- "unless the active object already has Grease Pencil data (i.e. for old files)"},
- {GP_TOOL_SOURCE_OBJECT, "OBJECT", 0, "Object",
- "Grease Pencil data-blocks attached to the active object are used "
- "(required when using pre 2.73 add-ons, e.g. BSurfaces)"},
+ static const EnumPropertyItem gpencil_stroke_placement_items[] = {
+ {GP_PROJECT_VIEWSPACE, "ORIGIN", ICON_OBJECT_ORIGIN, "Origin", "Draw stroke at Object origin"},
+ {GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Draw stroke at 3D cursor location" },
+ // {0, "VIEW", ICON_VISIBLE_IPO_ON, "View", "Stick stroke to the view "}, /* weird, GP_PROJECT_VIEWALIGN is inverted */
+ {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_VIEW, "SURFACE", ICON_FACESEL, "Surface", "Stick stroke to surfaces"},
+ //{GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_STROKE, "STROKE", ICON_GREASEPENCIL, "Stroke", "Stick stroke to other strokes"},
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem gpencil_stroke_placement_items[] = {
- {GP_PROJECT_VIEWSPACE, "CURSOR", 0, "Cursor", "Draw stroke at the 3D cursor"},
- {0, "VIEW", 0, "View", "Stick stroke to the view "}, /* weird, GP_PROJECT_VIEWALIGN is inverted */
- {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_VIEW, "SURFACE", 0, "Surface", "Stick stroke to surfaces"},
- {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_STROKE, "STROKE", 0, "Stroke", "Stick stroke to other strokes"},
+ static const EnumPropertyItem annotation_stroke_placement_items[] = {
+ {GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Draw stroke at 3D cursor location" },
+ {0, "VIEW", ICON_VISIBLE_IPO_ON, "View", "Stick stroke to the view "}, /* weird, GP_PROJECT_VIEWALIGN is inverted */
+ {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_VIEW, "SURFACE", ICON_FACESEL, "Surface", "Stick stroke to surfaces"},
+ {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_STROKE, "STROKE", ICON_GREASEPENCIL, "Stroke", "Stick stroke to other strokes"},
{0, NULL, 0, NULL, NULL}
};
@@ -2509,7 +2231,8 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
prop = RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "vpaint"); RNA_def_property_ui_text(prop, "Vertex Paint", "");
+ RNA_def_property_pointer_sdna(prop, NULL, "vpaint");
+ RNA_def_property_ui_text(prop, "Vertex Paint", "");
prop = RNA_def_property(srna, "weight_paint", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "wpaint");
@@ -2523,6 +2246,10 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "uvsculpt");
RNA_def_property_ui_text(prop, "UV Sculpt", "");
+ prop = RNA_def_property(srna, "gpencil_paint", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "gp_paint");
+ RNA_def_property_ui_text(prop, "Grease Pencil Paint", "");
+
prop = RNA_def_property(srna, "particle_edit", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "particle");
RNA_def_property_ui_text(prop, "Particle Edit", "");
@@ -2699,13 +2426,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Gizmo Mode", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ToolSettings_gizmo_flag_update");
- /* Grease Pencil */
- prop = RNA_def_property(srna, "use_gpencil_continuous_drawing", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_PAINTSESSIONS_ON);
- RNA_def_property_ui_text(prop, "Use Continuous Drawing",
- "Allow drawing multiple strokes at a time with Grease Pencil");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* xxx: need toolbar to be redrawn... */
+ prop = RNA_def_property(srna, "use_gizmo_apron", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", SCE_MANIP_DISABLE_APRON);
+ RNA_def_property_ui_text(prop, "Apron", "Handle input not directly over the gizmo");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ /* Grease Pencil */
prop = RNA_def_property(srna, "use_gpencil_additive_drawing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_RETAIN_LAST);
RNA_def_property_ui_text(prop, "Use Additive Drawing",
@@ -2719,12 +2445,11 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"When draw new strokes, the new stroke is drawn below of all strokes in the layer");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
- prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_src");
- RNA_def_property_enum_items(prop, gpencil_source_3d_items);
- RNA_def_property_ui_text(prop, "Grease Pencil Source",
- "Data-block where active Grease Pencil data is found from");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ prop = RNA_def_property(srna, "use_gpencil_thumbnail_list", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_THUMBNAIL_LIST);
+ RNA_def_property_ui_text(prop, "Compact List",
+ "Show compact list of color instead of thumbnails");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "gpencil_sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gp_sculpt");
@@ -2738,13 +2463,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grease Pencil Interpolate",
"Settings for Grease Pencil Interpolation tools");
- /* Grease Pencil - Drawing brushes */
- prop = RNA_def_property(srna, "gpencil_brushes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "gp_brushes", NULL);
- RNA_def_property_struct_type(prop, "GPencilBrush");
- RNA_def_property_ui_text(prop, "Grease Pencil Brushes", "Grease Pencil drawing brushes");
- rna_def_gpencil_brushes(brna, prop);
-
/* Grease Pencil - 3D View Stroke Placement */
prop = RNA_def_property(srna, "gpencil_stroke_placement_view3d", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_v3d_align");
@@ -2757,27 +2475,41 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Grease Pencil - 2D Views Stroke Placement */
- prop = RNA_def_property(srna, "gpencil_stroke_placement_view2d", PROP_ENUM, PROP_NONE);
+ /* Annotations - 2D Views Stroke Placement */
+ prop = RNA_def_property(srna, "annotation_stroke_placement_view2d", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_v2d_align");
- RNA_def_property_enum_items(prop, gpencil_stroke_placement_items);
+ RNA_def_property_enum_items(prop, annotation_stroke_placement_items);
RNA_def_property_ui_text(prop, "Stroke Placement (2D View)", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Grease Pencil - Sequencer Preview Stroke Placement */
- prop = RNA_def_property(srna, "gpencil_stroke_placement_sequencer_preview", PROP_ENUM, PROP_NONE);
+ /* Annotations - Sequencer Preview Stroke Placement */
+ prop = RNA_def_property(srna, "annotation_stroke_placement_sequencer_preview", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_seq_align");
- RNA_def_property_enum_items(prop, gpencil_stroke_placement_items);
+ RNA_def_property_enum_items(prop, annotation_stroke_placement_items);
RNA_def_property_ui_text(prop, "Stroke Placement (Sequencer Preview)", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
- /* Grease Pencil - Image Editor Stroke Placement */
- prop = RNA_def_property(srna, "gpencil_stroke_placement_image_editor", PROP_ENUM, PROP_NONE);
+ /* Annotations - Image Editor Stroke Placement */
+ prop = RNA_def_property(srna, "annotation_stroke_placement_image_editor", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_ima_align");
- RNA_def_property_enum_items(prop, gpencil_stroke_placement_items);
+ RNA_def_property_enum_items(prop, annotation_stroke_placement_items);
RNA_def_property_ui_text(prop, "Stroke Placement (Image Editor)", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+ /* Annotations - 3D View Stroke Placement */
+ /* XXX: Do we need to decouple the stroke_endpoints setting too? */
+ prop = RNA_def_property(srna, "annotation_stroke_placement_view3d", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "annotate_v3d_align");
+ RNA_def_property_enum_items(prop, annotation_stroke_placement_items);
+ RNA_def_property_ui_text(prop, "Annotation Stroke Placement (3D View)", "How annotation strokes are orientated in 3D space");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
+ /* Annotations - Stroke Thickness */
+ prop = RNA_def_property(srna, "annotation_thickness", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "annotate_thickness");
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_text(prop, "Annotation Stroke Thickness", "Thickness of annotation strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Auto Keying */
prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE);
@@ -2811,7 +2543,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
/* UV */
prop = RNA_def_property(srna, "uv_select_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_selectmode");
- RNA_def_property_enum_items(prop, uv_select_mode_items);
+ RNA_def_property_enum_items(prop, rna_enum_mesh_select_mode_uv_items);
RNA_def_property_ui_text(prop, "UV Selection Mode", "UV selection and display mode");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
@@ -2849,6 +2581,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "edge_mode_live_unwrap", 1);
RNA_def_property_ui_text(prop, "Live Unwrap", "Changing edges seam re-calculates UV unwrap");
+ prop = RNA_def_property(srna, "normal_vector", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply");
+ RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3);
+
+ prop = RNA_def_property(srna, "face_strength", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, mod_weighted_strength);
+ RNA_def_property_ui_text(prop, "Face Strength", "Set strength of face to specified value");
+
/* Unified Paint Settings */
prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -4092,6 +3832,7 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna)
prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect");
+ RNA_def_property_float_default(prop, 128.0f);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
@@ -4110,21 +3851,10 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna)
prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh");
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0000001f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1);
- RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- /* NOTE: high quality is always supported */
- prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
static void rna_def_gpu_ssao_fx(BlenderRNA *brna)
@@ -4255,6 +3985,7 @@ static void rna_def_scene_render_view(BlenderRNA *brna)
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "viewflag", SCE_VIEW_DISABLE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render view");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
@@ -4793,10 +4524,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
};
static const EnumPropertyItem display_mode_items[] = {
- {R_OUTPUT_SCREEN, "SCREEN", 0, "Full Screen", "Images are rendered in full Screen"},
- {R_OUTPUT_AREA, "AREA", 0, "Image Editor", "Images are rendered in Image Editor"},
- {R_OUTPUT_WINDOW, "WINDOW", 0, "New Window", "Images are rendered in new Window"},
- {R_OUTPUT_NONE, "NONE", 0, "Keep UI", "Images are rendered without forcing UI changes"},
+ {R_OUTPUT_SCREEN, "SCREEN", 0, "Full Screen", "Images are rendered in a maximized Image Editor"},
+ {R_OUTPUT_AREA, "AREA", 0, "Image Editor", "Images are rendered in an Image Editor"},
+ {R_OUTPUT_WINDOW, "WINDOW", 0, "New Window", "Images are rendered in a new window"},
+ {R_OUTPUT_NONE, "NONE", 0, "Keep User Interface", "Images are rendered without changing the user interface"},
{0, NULL, 0, NULL, NULL}
};
@@ -4809,7 +4540,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
};
static const EnumPropertyItem pixel_size_items[] = {
- {0, "AUTO", 0, "Automatic", "Automatic pixel size, depends on the UI scale"},
+ {0, "AUTO", 0, "Automatic", "Automatic pixel size, depends on the user interface scale"},
{1, "1", 0, "1x", "Render at full resolution"},
{2, "2", 0, "2x", "Render at 50% resolution"},
{4, "4", 0, "4x", "Render at 25% resolution"},
@@ -5411,7 +5142,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_single_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_SINGLE_LAYER);
- RNA_def_property_ui_text(prop, "Render Single Layer", "Only render the active layer");
+ RNA_def_property_ui_text(prop, "Render Single Layer", "Only render the active layer. Only affects rendering from the interface, ignored for rendering from command line");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* views (stereoscopy et al) */
@@ -5487,6 +5219,37 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering");
RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+ /* Grease Pencil - Simplify Options */
+ prop = RNA_def_property(srna, "simplify_gpencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_ENABLE);
+ RNA_def_property_ui_text(prop, "Simplify", "Simplify Grease Pencil drawing");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_onplay", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_ON_PLAY);
+ RNA_def_property_ui_text(prop, "Simplify Playback", "Simplify Grease Pencil only during animation playback");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_view_fill", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_FILL);
+ RNA_def_property_ui_text(prop, "Disable Fill", "Disable fill strokes in the viewport");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_remove_lines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_REMOVE_FILL_LINE);
+ RNA_def_property_ui_text(prop, "Disable Lines", "Disable external lines of fill strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_view_modifier", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_MODIFIER);
+ RNA_def_property_ui_text(prop, "Disable Modifiers", "Do not apply modifiers in the viewport");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_shader_fx", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_FX);
+ RNA_def_property_ui_text(prop, "Simplify Shaders", "Do not apply shader fx");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* persistent data */
prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA);
@@ -5753,6 +5516,10 @@ static void rna_def_scene_display(BlenderRNA *brna)
RNA_def_property_int_default(prop, 16);
RNA_def_property_ui_text(prop, "Samples", "Number of samples");
RNA_def_property_range(prop, 1, 500);
+
+ /* OpenGL render engine settings. */
+ prop = RNA_def_property(srna, "shading", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Shading Settings", "Shading settings for OpenGL render engine");
}
static void rna_def_scene_eevee(BlenderRNA *brna)
@@ -6011,12 +5778,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- prop = RNA_def_property(srna, "use_volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_COLORED);
- RNA_def_property_boolean_default(prop, 1);
- RNA_def_property_ui_text(prop, "Colored Transmittance", "Enable wavelength dependent volumetric transmittance");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
-
/* Ambient Occlusion */
prop = RNA_def_property(srna, "use_gtao", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_ENABLED);
@@ -6565,8 +6326,9 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
- RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block");
+ RNA_def_property_ui_text(prop, "Annotations", "Grease Pencil data-block used for annotations in the 3D view");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
/* active MovieClip */
@@ -6621,7 +6383,6 @@ void RNA_def_scene(BlenderRNA *brna)
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
rna_def_tool_settings(brna);
- rna_def_gpencil_brush(brna);
rna_def_gpencil_interpolate(brna);
rna_def_unified_paint_settings(brna);
rna_def_curve_paint_settings(brna);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 5b2a3c9c4f4..faa879b54b1 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -35,6 +35,7 @@
#include "rna_internal.h"
#include "DNA_ID.h"
+#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
@@ -51,7 +52,7 @@
#include "bmesh.h"
-static const EnumPropertyItem particle_edit_hair_brush_items[] = {
+const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[] = {
{PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
{PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
{PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"},
@@ -64,26 +65,29 @@ static const EnumPropertyItem particle_edit_hair_brush_items[] = {
};
const EnumPropertyItem rna_enum_gpencil_sculpt_brush_items[] = {
- {GP_EDITBRUSH_TYPE_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth stroke points"},
- {GP_EDITBRUSH_TYPE_THICKNESS, "THICKNESS", 0, "Thickness", "Adjust thickness of strokes"},
- { GP_EDITBRUSH_TYPE_STRENGTH, "STRENGTH", 0, "Strength", "Adjust color strength of strokes" },
- { GP_EDITBRUSH_TYPE_GRAB, "GRAB", 0, "Grab", "Translate the set of points initially within the brush circle" },
- {GP_EDITBRUSH_TYPE_PUSH, "PUSH", 0, "Push", "Move points out of the way, as if combing them"},
- {GP_EDITBRUSH_TYPE_TWIST, "TWIST", 0, "Twist", "Rotate points around the midpoint of the brush"},
- {GP_EDITBRUSH_TYPE_PINCH, "PINCH", 0, "Pinch", "Pull points towards the midpoint of the brush"},
- {GP_EDITBRUSH_TYPE_RANDOMIZE, "RANDOMIZE", 0, "Randomize", "Introduce jitter/randomness into strokes"},
- //{GP_EDITBRUSH_TYPE_SUBDIVIDE, "SUBDIVIDE", 0, "Subdivide", "Increase point density for higher resolution strokes when zoomed in"},
- //{GP_EDITBRUSH_TYPE_SIMPLIFY, "SIMPLIFY", 0, "Simplify", "Reduce density of stroke points"},
- {GP_EDITBRUSH_TYPE_CLONE, "CLONE", 0, "Clone", "Paste copies of the strokes stored on the clipboard"},
+ {GP_EDITBRUSH_TYPE_SMOOTH, "SMOOTH", ICON_GPBRUSH_SMOOTH, "Smooth", "Smooth stroke points"},
+ {GP_EDITBRUSH_TYPE_THICKNESS, "THICKNESS", ICON_GPBRUSH_THICKNESS, "Thickness", "Adjust thickness of strokes"},
+ {GP_EDITBRUSH_TYPE_STRENGTH, "STRENGTH", ICON_GPBRUSH_STRENGTH, "Strength", "Adjust color strength of strokes" },
+ {GP_EDITBRUSH_TYPE_GRAB, "GRAB", ICON_GPBRUSH_GRAB, "Grab", "Translate the set of points initially within the brush circle" },
+ {GP_EDITBRUSH_TYPE_PUSH, "PUSH", ICON_GPBRUSH_PUSH, "Push", "Move points out of the way, as if combing them"},
+ {GP_EDITBRUSH_TYPE_TWIST, "TWIST", ICON_GPBRUSH_TWIST, "Twist", "Rotate points around the midpoint of the brush"},
+ {GP_EDITBRUSH_TYPE_PINCH, "PINCH", ICON_GPBRUSH_PINCH, "Pinch", "Pull points towards the midpoint of the brush"},
+ {GP_EDITBRUSH_TYPE_RANDOMIZE, "RANDOMIZE", ICON_GPBRUSH_RANDOMIZE, "Randomize", "Introduce jitter/randomness into strokes"},
+ {GP_EDITBRUSH_TYPE_CLONE, "CLONE", ICON_GPBRUSH_CLONE, "Clone", "Paste copies of the strokes stored on the clipboard"},
{ 0, NULL, 0, NULL, NULL }
};
#ifndef RNA_RUNTIME
+static EnumPropertyItem rna_enum_gpencil_weight_brush_items[] = {
+ { GP_EDITBRUSH_TYPE_WEIGHT, "WEIGHT", ICON_GPBRUSH_WEIGHT, "Weight", "Weight Paint for Vertex Groups" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
static const EnumPropertyItem rna_enum_gpencil_lockaxis_items[] = {
- { GP_LOCKAXIS_NONE, "GP_LOCKAXIS_NONE", 0, "None", "" },
- { GP_LOCKAXIS_X, "GP_LOCKAXIS_X", 0, "X", "Project strokes to plane locked to X" },
- { GP_LOCKAXIS_Y, "GP_LOCKAXIS_Y", 0, "Y", "Project strokes to plane locked to Y" },
- { GP_LOCKAXIS_Z, "GP_LOCKAXIS_Z", 0, "Z", "Project strokes to plane locked to Z" },
+ { GP_LOCKAXIS_NONE, "GP_LOCKAXIS_NONE", ICON_UNLOCKED, "None", "" },
+ { GP_LOCKAXIS_X, "GP_LOCKAXIS_X", ICON_NDOF_DOM, "X", "Project strokes to plane locked to X" },
+ { GP_LOCKAXIS_Y, "GP_LOCKAXIS_Y", ICON_NDOF_DOM, "Y", "Project strokes to plane locked to Y" },
+ { GP_LOCKAXIS_Z, "GP_LOCKAXIS_Z", ICON_NDOF_DOM, "Z", "Project strokes to plane locked to Z" },
{ 0, NULL, 0, NULL, NULL }
};
#endif
@@ -103,22 +107,40 @@ const EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
#ifdef RNA_RUNTIME
#include "MEM_guardedalloc.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
#include "BKE_object.h"
+#include "BKE_gpencil.h"
+
#include "DEG_depsgraph.h"
#include "ED_particle.h"
-static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_GPencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
+ /* mark all grease pencil datablocks of the scene */
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
+ {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
+ {
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
-static const EnumPropertyItem particle_edit_disconnected_hair_brush_items[] = {
+const EnumPropertyItem rna_enum_particle_edit_disconnected_hair_brush_items[] = {
{PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
{PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
{PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"},
@@ -195,8 +217,9 @@ static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
pset->brushtype = value;
}
-static const EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+static const EnumPropertyItem *rna_ParticleEdit_tool_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
@@ -213,10 +236,10 @@ static const EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerR
if (psys) {
if (psys->flag & PSYS_GLOBAL_HAIR) {
- return particle_edit_disconnected_hair_brush_items;
+ return rna_enum_particle_edit_disconnected_hair_brush_items;
}
else {
- return particle_edit_hair_brush_items;
+ return rna_enum_particle_edit_hair_brush_items;
}
}
@@ -265,6 +288,8 @@ static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
mode = OB_MODE_VERTEX_PAINT;
else if (ptr->data == ts->wpaint)
mode = OB_MODE_WEIGHT_PAINT;
+ else if (ptr->data == ts->gp_paint)
+ mode = OB_MODE_GPENCIL_PAINT;
return brush->ob_mode & mode;
}
@@ -346,6 +371,11 @@ static char *rna_UvSculpt_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings.uv_sculpt");
}
+static char *rna_GpPaint_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_strdup("tool_settings.gp_paint");
+}
+
static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.particle_edit.brush");
@@ -435,9 +465,14 @@ static PointerRNA rna_GPencilSculptSettings_brush_get(PointerRNA *ptr)
GP_BrushEdit_Settings *gset = (GP_BrushEdit_Settings *)ptr->data;
GP_EditBrush_Data *brush = NULL;
- if ((gset->brushtype >= 0) && (gset->brushtype < TOT_GP_EDITBRUSH_TYPES))
- brush = &gset->brush[gset->brushtype];
-
+ if ((gset) && (gset->flag & GP_BRUSHEDIT_FLAG_WEIGHT_MODE)) {
+ if ((gset->weighttype >= GP_EDITBRUSH_TYPE_WEIGHT) && (gset->weighttype < TOT_GP_EDITBRUSH_TYPES))
+ brush = &gset->brush[gset->weighttype];
+ }
+ else {
+ if ((gset->brushtype >= 0) && (gset->brushtype < GP_EDITBRUSH_TYPE_WEIGHT))
+ brush = &gset->brush[gset->brushtype];
+ }
return rna_pointer_inherit_refine(ptr, &RNA_GPencilSculptBrush, brush);
}
@@ -708,6 +743,14 @@ static void rna_def_uv_sculpt(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "UV Sculpting", "");
}
+static void rna_def_gp_paint(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "GpPaint", "Paint");
+ RNA_def_struct_path_func(srna, "rna_GpPaint_path");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Paint", "");
+}
/* use for weight paint too */
static void rna_def_vertex_paint(BlenderRNA *brna)
@@ -909,7 +952,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brushtype");
- RNA_def_property_enum_items(prop, particle_edit_hair_brush_items);
+ RNA_def_property_enum_items(prop, rna_enum_particle_edit_hair_brush_items);
RNA_def_property_enum_funcs(prop, NULL, "rna_ParticleEdit_tool_set", "rna_ParticleEdit_tool_itemf");
RNA_def_property_ui_text(prop, "Tool", "");
@@ -1059,8 +1102,8 @@ static void rna_def_particle_edit(BlenderRNA *brna)
static void rna_def_gpencil_sculpt(BlenderRNA *brna)
{
static const EnumPropertyItem prop_direction_items[] = {
- {0, "ADD", 0, "Add", "Add effect of brush"},
- {GP_EDITBRUSH_FLAG_INVERT, "SUBTRACT", 0, "Subtract", "Subtract effect of brush"},
+ {0, "ADD", ICON_ZOOMIN, "Add", "Add effect of brush"},
+ {GP_EDITBRUSH_FLAG_INVERT, "SUBTRACT", ICON_ZOOMOUT, "Subtract", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
StructRNA *srna;
@@ -1076,86 +1119,148 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "brushtype");
RNA_def_property_enum_items(prop, rna_enum_gpencil_sculpt_brush_items);
RNA_def_property_ui_text(prop, "Tool", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "weight_tool", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "weighttype");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_weight_brush_items);
+ RNA_def_property_ui_text(prop, "Tool", "Tool for weight painting");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_GPencil_update");
prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "GPencilSculptBrush");
RNA_def_property_pointer_funcs(prop, "rna_GPencilSculptSettings_brush_get", NULL, NULL, NULL);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop, "Brush", "");
prop = RNA_def_property(srna, "use_select_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_SELECT_MASK);
RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points");
RNA_def_property_ui_icon(prop, ICON_VERTEXSEL, 0); // FIXME: this needs a custom icon
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_POSITION);
RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "affect_strength", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_STRENGTH);
RNA_def_property_ui_text(prop, "Affect Strength", "The brush affects the color strength of the point");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "affect_thickness", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_THICKNESS);
RNA_def_property_ui_text(prop, "Affect Thickness", "The brush affects the thickness of the point");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ prop = RNA_def_property(srna, "affect_uv", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_UV);
+ RNA_def_property_ui_text(prop, "Affect UV", "The brush affects the UV rotation of the point");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
- prop = RNA_def_property(srna, "selection_alpha", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "alpha");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Alpha", "Alpha value for selected vertices");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "use_multiframe_falloff", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_FRAME_FALLOFF);
+ RNA_def_property_ui_text(prop, "Use Falloff", "Use falloff effect when edit in multiframe mode to compute brush effect by frame");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* custom falloff curve */
+ prop = RNA_def_property(srna, "multiframe_falloff_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "cur_falloff");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve",
+ "Custom curve to control falloff of brush effect by Grease Pencil frames");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* lock axis */
prop = RNA_def_property(srna, "lockaxis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "lock_axis");
RNA_def_property_enum_items(prop, rna_enum_gpencil_lockaxis_items);
RNA_def_property_ui_text(prop, "Lock", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* brush */
srna = RNA_def_struct(brna, "GPencilSculptBrush", NULL);
RNA_def_struct_sdna(srna, "GP_EditBrush_Data");
RNA_def_struct_path_func(srna, "rna_GPencilSculptBrush_path");
RNA_def_struct_ui_text(srna, "GPencil Sculpt Brush", "Stroke editing brush");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
- RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS);
- RNA_def_property_ui_range(prop, 1, 100, 10, 3); // XXX: too big
+ RNA_def_property_range(prop, 1, GP_MAX_BRUSH_PIXEL_RADIUS);
+ RNA_def_property_ui_range(prop, 1, 500, 10, 3);
RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.001, 1.0);
RNA_def_property_ui_text(prop, "Strength", "Brush strength");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_USE_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_ui_text(prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "use_falloff", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_USE_FALLOFF);
RNA_def_property_ui_text(prop, "Use Falloff", "Strength of brush decays with distance from cursor");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "affect_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE);
RNA_def_property_ui_text(prop, "Affect Pressure", "Affect pressure values as well when smoothing strokes");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_direction_items);
RNA_def_property_ui_text(prop, "Direction", "");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* Cursor Color */
+ static float default_1[3] = { 1.0f, 0.6f, 0.6f };
+ static float default_2[3] = { 0.6f, 0.6f, 1.0f };
+
+ prop = RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "curcolor_add");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, default_1);
+ RNA_def_property_ui_text(prop, "Cursor Add", "Color for the cursor for addition");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "cursor_color_sub", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "curcolor_sub");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_array_default(prop, default_2);
+ RNA_def_property_ui_text(prop, "Cursor Sub", "Color for the cursor for substration");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
+ prop = RNA_def_property(srna, "use_cursor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_ENABLE_CURSOR);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_ui_text(prop, "Enable Cursor", "Enable cursor on screen");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+
}
void RNA_def_sculpt_paint(BlenderRNA *brna)
@@ -1166,6 +1271,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);
+ rna_def_gp_paint(brna);
rna_def_vertex_paint(brna);
rna_def_image_paint(brna);
rna_def_particle_edit(brna);
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
new file mode 100644
index 00000000000..da4470ccff7
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -0,0 +1,537 @@
+/*
+ * ***** 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/makesrna/intern/rna_shader_fx.c
+ * \ingroup RNA
+ */
+
+
+#include <float.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "DNA_shader_fx_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_animsys.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+const EnumPropertyItem rna_enum_object_shaderfx_type_items[] = {
+ {eShaderFxType_Blur, "FX_BLUR", ICON_SOLO_ON, "Blur", "Apply Gaussian Blur to object" },
+ {eShaderFxType_Colorize, "FX_COLORIZE", ICON_SOLO_ON, "Colorize", "Apply different tint effects" },
+ {eShaderFxType_Flip, "FX_FLIP", ICON_SOLO_ON, "Flip", "Flip image" },
+ {eShaderFxType_Light, "FX_LIGHT", ICON_SOLO_ON, "Light", "Simulate ilumination" },
+ {eShaderFxType_Pixel, "FX_PIXEL", ICON_SOLO_ON, "Pixelate", "Pixelate image"},
+ {eShaderFxType_Rim, "FX_RIM", ICON_SOLO_ON, "Rim", "Add a rim to the image" },
+ {eShaderFxType_Swirl, "FX_SWIRL", ICON_SOLO_ON, "Swirl", "Create a rotation distortion"},
+ {eShaderFxType_Wave, "FX_WAVE", ICON_SOLO_ON, "Wave Distortion", "Apply sinusoidal deformation"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static const EnumPropertyItem rna_enum_shaderfx_rim_modes_items[] = {
+ {eShaderFxRimMode_Normal, "NORMAL", 0, "Normal", "" },
+ {eShaderFxRimMode_Overlay, "OVERLAY", 0, "Overlay", "" },
+ {eShaderFxRimMode_Add, "ADD", 0, "Add", "" },
+ {eShaderFxRimMode_Subtract, "SUBTRACT", 0, "Subtract", "" },
+ {eShaderFxRimMode_Multiply, "MULTIPLY", 0, "Multiply", "" },
+ {eShaderFxRimMode_Divide, "DIVIDE", 0, "Divide", "" },
+ {0, NULL, 0, NULL, NULL }
+};
+
+static const EnumPropertyItem rna_enum_shaderfx_colorize_modes_items[] = {
+ {eShaderFxColorizeMode_GrayScale, "GRAYSCALE", 0, "Gray Scale", "" },
+ {eShaderFxColorizeMode_Sepia, "SEPIA", 0, "Sepia", "" },
+ {eShaderFxColorizeMode_BiTone, "BITONE", 0, "Bi-Tone", "" },
+ {eShaderFxColorizeMode_Transparent, "TRANSPARENT", 0, "Transparent", "" },
+ {eShaderFxColorizeMode_Custom, "CUSTOM", 0, "Custom", "" },
+ {0, NULL, 0, NULL, NULL }
+};
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_shader_fx.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+static StructRNA *rna_ShaderFx_refine(struct PointerRNA *ptr)
+{
+ ShaderFxData *md = (ShaderFxData *)ptr->data;
+
+ switch ((ShaderFxType)md->type) {
+ case eShaderFxType_Blur:
+ return &RNA_ShaderFxBlur;
+ case eShaderFxType_Colorize:
+ return &RNA_ShaderFxColorize;
+ case eShaderFxType_Wave:
+ return &RNA_ShaderFxWave;
+ case eShaderFxType_Pixel:
+ return &RNA_ShaderFxPixel;
+ case eShaderFxType_Rim:
+ return &RNA_ShaderFxRim;
+ case eShaderFxType_Swirl:
+ return &RNA_ShaderFxSwirl;
+ case eShaderFxType_Flip:
+ return &RNA_ShaderFxFlip;
+ case eShaderFxType_Light:
+ return &RNA_ShaderFxLight;
+ /* Default */
+ case eShaderFxType_None:
+ case NUM_SHADER_FX_TYPES:
+ return &RNA_ShaderFx;
+ }
+
+ return &RNA_ShaderFx;
+}
+
+static void rna_ShaderFx_name_set(PointerRNA *ptr, const char *value)
+{
+ ShaderFxData *gmd = ptr->data;
+ char oldname[sizeof(gmd->name)];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, gmd->name, sizeof(gmd->name));
+
+ /* copy the new name into the name slot */
+ BLI_strncpy_utf8(gmd->name, value, sizeof(gmd->name));
+
+ /* make sure the name is truly unique */
+ if (ptr->id.data) {
+ Object *ob = ptr->id.data;
+ BKE_shaderfx_unique_name(&ob->shader_fx, gmd);
+ }
+
+ /* fix all the animation data which may link to this */
+ BKE_animdata_fix_paths_rename_all(NULL, "shader_effects", oldname, gmd->name);
+}
+
+static char *rna_ShaderFx_path(PointerRNA *ptr)
+{
+ ShaderFxData *gmd = ptr->data;
+ char name_esc[sizeof(gmd->name) * 2];
+
+ BLI_strescape(name_esc, gmd->name, sizeof(name_esc));
+ return BLI_sprintfN("shader_effects[\"%s\"]", name_esc);
+}
+
+static void rna_ShaderFx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NC_GPENCIL, ptr->id.data);
+}
+
+static void rna_ShaderFx_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_ShaderFx_update(bmain, scene, ptr);
+ DEG_relations_tag_update(bmain);
+}
+
+/* Objects */
+
+static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRNA value)
+{
+ Object *ob = value.data;
+
+ if (!self || ob != self) {
+ if (!ob || type == OB_EMPTY || ob->type == type) {
+ id_lib_extern((ID *)ob);
+ *ob_p = ob;
+ }
+ }
+}
+
+#define RNA_FX_OBJECT_SET(_type, _prop, _obtype) \
+static void rna_##_type##ShaderFx_##_prop##_set(PointerRNA *ptr, PointerRNA value) \
+{ \
+ _type##ShaderFxData *tmd = (_type##ShaderFxData *)ptr->data; \
+ shaderfx_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
+}
+
+RNA_FX_OBJECT_SET(Light, object, OB_EMPTY);
+RNA_FX_OBJECT_SET(Swirl, object, OB_EMPTY);
+
+#undef RNA_FX_OBJECT_SET
+
+#else
+
+static void rna_def_shader_fx_blur(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxBlur", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Gaussian Blur Effect", "Gaussian Blur effect");
+ RNA_def_struct_sdna(srna, "BlurShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "factor", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "radius");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "Factor", "Factor of Blur");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "samples");
+ RNA_def_property_range(prop, 0, 32);
+ RNA_def_property_ui_range(prop, 0, 32, 2, -1);
+ RNA_def_property_int_default(prop, 4);
+ RNA_def_property_ui_text(prop, "Samples", "Number of Blur Samples (zero, disable blur)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "coc", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "coc");
+ RNA_def_property_range(prop, 0.001f, 1.0f);
+ RNA_def_property_float_default(prop, 0.025f);
+ RNA_def_property_ui_text(prop, "Precision", "Define circle of confusion for depth of field");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "use_dof_mode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_BLUR_DOF_MODE);
+ RNA_def_property_ui_text(prop, "Lock Focal Plane", "Blur using focal plane distance as factor to simulate depth of field effect (only in camera view)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_colorize(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxColorize", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Colorize Effect", "Colorize effect");
+ RNA_def_struct_sdna(srna, "ColorizeShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0, 1.0);
+ RNA_def_property_ui_text(prop, "Factor", "Mix factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "low_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "low_color");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Low color", "First color used for effect");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "high_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "high_color");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Hight color", "Second color used for effect");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, rna_enum_shaderfx_colorize_modes_items);
+ RNA_def_property_ui_text(prop, "Mode", "Effect mode");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_wave(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_shaderfx_wave_type_items[] = {
+ { 0, "HORIZONTAL", 0, "Horizontal", "" },
+ { 1, "VERTICAL", 0, "Vertical", "" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ srna = RNA_def_struct(brna, "ShaderFxWave", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Wave Deformation Effect", "Wave Deformation effect");
+ RNA_def_struct_sdna(srna, "WaveShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "orientation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "orientation");
+ RNA_def_property_enum_items(prop, prop_shaderfx_wave_type_items);
+ RNA_def_property_ui_text(prop, "Orientation", "Direction of the wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Period", "Period of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "phase", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "phase");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Phase", "Phase Shift of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_pixel(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxPixel", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Pixelate Effect", "Pixelate effect");
+ RNA_def_struct_sdna(srna, "PixelShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "size");
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Size", "Pixel size");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgba");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Color", "Color used for lines");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "use_lines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_PIXEL_USE_LINES);
+ RNA_def_property_ui_text(prop, "Lines", "Display lines between pixels");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_rim(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxRim", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Rim Effect", "Rim effect");
+ RNA_def_struct_sdna(srna, "RimShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "offset", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "offset");
+ RNA_def_property_range(prop, -INT_MAX, INT_MAX);
+ RNA_def_property_ui_text(prop, "Offset", "Offset of the rim");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "rim_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rim_rgb");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Rim Color", "Color used for Rim");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "mask_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "mask_rgb");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Mask Color", "Color that must be keept");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, rna_enum_shaderfx_rim_modes_items);
+ RNA_def_property_ui_text(prop, "Mode", "Blend mode");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "blur", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "blur");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "Blur", "Number of pixels for bluring rim (set to 0 to disable)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "samples");
+ RNA_def_property_range(prop, 0, 32);
+ RNA_def_property_ui_range(prop, 0, 32, 2, -1);
+ RNA_def_property_int_default(prop, 4);
+ RNA_def_property_ui_text(prop, "Samples", "Number of Blur Samples (zero, disable blur)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_swirl(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxSwirl", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Swirl Effect", "Swirl effect");
+ RNA_def_struct_sdna(srna, "SwirlShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "radius", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "radius");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "Radius", "Radius to apply");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_range(prop, DEG2RAD(-5 * 360), DEG2RAD(5 * 360));
+ RNA_def_property_ui_range(prop, DEG2RAD(-5 * 360), DEG2RAD(5 * 360), 5, 2);
+ RNA_def_property_ui_text(prop, "Angle", "Angle of rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "transparent", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_SWIRL_MAKE_TRANSPARENT);
+ RNA_def_property_ui_text(prop, "Transparent", "Make image transparent outside of radius");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object to determine center location");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_SwirlShaderFx_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
+}
+
+static void rna_def_shader_fx_flip(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxFlip", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Flip Effect", "Flip effect");
+ RNA_def_struct_sdna(srna, "FlipShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "flip_horizontal", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_HORIZONTAL);
+ RNA_def_property_ui_text(prop, "Horizontal", "Flip image horizontally");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "flip_vertical", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_VERTICAL);
+ RNA_def_property_ui_text(prop, "Vertical", "Flip image vertically");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
+static void rna_def_shader_fx_light(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxLight", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Light Effect", "Light effect");
+ RNA_def_struct_sdna(srna, "LightShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SOLO_ON);
+
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "energy");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1, FLT_MAX, 1, 2);
+ RNA_def_property_ui_text(prop, "Energy", "Strength of light source");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "ambient", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "ambient");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 2);
+ RNA_def_property_ui_text(prop, "Ambient", "Strength of ambient light source");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object to determine light source location");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_LightShaderFx_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
+}
+
+void RNA_def_shader_fx(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* data */
+ srna = RNA_def_struct(brna, "ShaderFx", NULL);
+ RNA_def_struct_ui_text(srna, "ShaderFx", "Effect affecting the grease pencil object");
+ RNA_def_struct_refine_func(srna, "rna_ShaderFx_refine");
+ RNA_def_struct_path_func(srna, "rna_ShaderFx_path");
+ RNA_def_struct_sdna(srna, "ShaderFxData");
+
+ /* strings */
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ShaderFx_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Effect name");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER | NA_RENAME, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* enums */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rna_enum_object_shaderfx_type_items);
+ RNA_def_property_ui_text(prop, "Type", "");
+
+ /* flags */
+ prop = RNA_def_property(srna, "show_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eShaderFxMode_Realtime);
+ RNA_def_property_ui_text(prop, "Realtime", "Display effect in viewport");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0);
+
+ prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eShaderFxMode_Render);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_text(prop, "Render", "Use effect during render");
+ RNA_def_property_ui_icon(prop, ICON_SCENE, 0);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "show_in_editmode", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eShaderFxMode_Editmode);
+ RNA_def_property_ui_text(prop, "Edit Mode", "Display effect in Edit mode");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+ RNA_def_property_ui_icon(prop, ICON_EDITMODE_HLT, 0);
+
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", eShaderFxMode_Expanded);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_text(prop, "Expanded", "Set effect expanded in the user interface");
+ RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
+
+ /* types */
+ rna_def_shader_fx_blur(brna);
+ rna_def_shader_fx_colorize(brna);
+ rna_def_shader_fx_wave(brna);
+ rna_def_shader_fx_pixel(brna);
+ rna_def_shader_fx_rim(brna);
+ rna_def_shader_fx_swirl(brna);
+ rna_def_shader_fx_flip(brna);
+ rna_def_shader_fx_light(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 5c30cdb2b07..d7563f13dc2 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "DNA_action_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -243,7 +244,7 @@ const EnumPropertyItem rna_enum_shading_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-const EnumPropertyItem rna_enum_viewport_lighting_items[] = {
+static const EnumPropertyItem rna_enum_viewport_lighting_items[] = {
{V3D_LIGHTING_FLAT, "FLAT", 0, "Flat", "Display using flat lighting"},
{V3D_LIGHTING_STUDIO, "STUDIO", 0, "Studio", "Display using studio lighting"},
{V3D_LIGHTING_MATCAP, "MATCAP", 0, "MatCap", "Display using matcap material and lighting"},
@@ -288,6 +289,7 @@ static const EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"},
{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"},
{BCONTEXT_WORKSPACE, "WORKSPACE", ICON_SPLITSCREEN, "Workspace", "Workspace"},
+ {BCONTEXT_SHADERFX, "SHADERFX", ICON_SOLO_ON, "Effects", "Object visual effects" },
{0, NULL, 0, NULL, NULL}
};
@@ -308,6 +310,14 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static const EnumPropertyItem rna_enum_gpencil_grid_axis_items[] = {
+ {V3D_GP_GRID_AXIS_LOCK, "LOCK", 0, "Lock", "Use current drawing locked axis" },
+ {V3D_GP_GRID_AXIS_X, "X", 0, "X", ""},
+ {V3D_GP_GRID_AXIS_Y, "Y", 0, "Y", ""},
+ {V3D_GP_GRID_AXIS_Z, "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
@@ -475,6 +485,17 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain), Scene *UNUSED(scen
}
}
+static void rna_GPencil_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ /* need set all caches as dirty to recalculate onion skinning */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_GPENCIL) {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ }
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+}
+
/* Space 3D View */
static void rna_SpaceView3D_camera_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
@@ -581,14 +602,6 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DEG_on_visible_update(bmain, false);
}
-static void rna_3DViewShading_type_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
-{
- View3D *v3d = (View3D *)(ptr->data);
- ScrArea *sa = rna_area_from_space(ptr);
-
- ED_view3d_shade_update(bmain, v3d, sa);
-}
-
static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
@@ -685,37 +698,77 @@ static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *value
ED_view3d_from_m4(mat, rv3d->ofs, rv3d->viewquat, &rv3d->dist);
}
-static int rna_3DViewShading_type_get(PointerRNA *ptr)
+static void rna_3DViewShading_type_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
+ ID *id = ptr->id.data;
+ if (GS(id->name) == ID_SCE) {
+ return;
+ }
+
bScreen *screen = ptr->id.data;
- Scene *scene = WM_windows_scene_get_from_screen(G_MAIN->wm.first, screen);
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (&v3d->shading == ptr->data) {
+ ED_view3d_shade_update(bmain, v3d, sa);
+ return;
+ }
+ }
+ }
+ }
+}
+
+static Scene *rna_3DViewShading_scene(PointerRNA *ptr)
+{
+ /* Get scene, depends if using 3D view or OpenGL render settings. */
+ ID *id = ptr->id.data;
+ if (GS(id->name) == ID_SCE) {
+ return (Scene *)id;
+ }
+ else {
+ bScreen *screen = ptr->id.data;
+ return WM_windows_scene_get_from_screen(G_MAIN->wm.first, screen);
+ }
+}
+
+static int rna_3DViewShading_type_get(PointerRNA *ptr)
+{
+ /* Available shading types depend on render engine. */
+ Scene *scene = rna_3DViewShading_scene(ptr);
RenderEngineType *type = RE_engines_find(scene->r.engine);
- View3D *v3d = (View3D *)ptr->data;
+ View3DShading *shading = (View3DShading *)ptr->data;
- if (!BKE_scene_uses_blender_eevee(scene) && v3d->drawtype == OB_RENDER) {
- if (!(type && type->view_draw)) {
+ if (BKE_scene_uses_blender_eevee(scene)) {
+ return shading->type;
+ }
+ else if (BKE_scene_uses_blender_opengl(scene)) {
+ return (shading->type == OB_MATERIAL) ? OB_RENDER : shading->type;
+ }
+ else {
+ if (shading->type == OB_RENDER && !(type && type->view_draw)) {
return OB_MATERIAL;
}
+ else {
+ return shading->type;
+ }
}
-
- return v3d->drawtype;
}
static void rna_3DViewShading_type_set(PointerRNA *ptr, int value)
{
- View3D *v3d = (View3D *)ptr->data;
- if (value != v3d->drawtype && value == OB_RENDER) {
- v3d->prev_drawtype = v3d->drawtype;
+ View3DShading *shading = (View3DShading *)ptr->data;
+ if (value != shading->type && value == OB_RENDER) {
+ shading->prev_type = shading->type;
}
- v3d->drawtype = value;
+ shading->type = value;
}
static const EnumPropertyItem *rna_3DViewShading_type_itemf(
- bContext *C, PointerRNA *UNUSED(ptr),
+ bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *r_free)
{
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = WM_window_get_active_scene(win);
+ Scene *scene = rna_3DViewShading_scene(ptr);
RenderEngineType *type = RE_engines_find(scene->r.engine);
EnumPropertyItem *item = NULL;
@@ -727,6 +780,9 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf(
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_MATERIAL);
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_RENDER);
}
+ else if (BKE_scene_uses_blender_opengl(scene)) {
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_RENDER);
+ }
else {
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_MATERIAL);
if (type && type->view_draw) {
@@ -743,13 +799,13 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf(
/* Shading.selected_studio_light */
static PointerRNA rna_View3DShading_selected_studio_light_get(PointerRNA *ptr)
{
- View3D *v3d = (View3D *)ptr->data;
+ View3DShading *shading = (View3DShading *)ptr->data;
StudioLight *sl;
- if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) {
- sl = BKE_studiolight_find(v3d->shading.matcap, STUDIOLIGHT_FLAG_ALL);
+ if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
+ sl = BKE_studiolight_find(shading->matcap, STUDIOLIGHT_FLAG_ALL);
}
else {
- sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_FLAG_ALL);
+ sl = BKE_studiolight_find(shading->studio_light, STUDIOLIGHT_FLAG_ALL);
}
return rna_pointer_inherit_refine(ptr, &RNA_StudioLight, sl);
}
@@ -757,33 +813,33 @@ static PointerRNA rna_View3DShading_selected_studio_light_get(PointerRNA *ptr)
/* shading.light */
static int rna_View3DShading_light_get(PointerRNA *ptr)
{
- View3D *v3d = (View3D *)ptr->data;
- return v3d->shading.light;
+ View3DShading *shading = (View3DShading *)ptr->data;
+ return shading->light;
}
static void rna_View3DShading_light_set(PointerRNA *ptr, int value)
{
- View3D *v3d = (View3D *)ptr->data;
- if (value == V3D_LIGHTING_MATCAP && v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
- v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR;
+ View3DShading *shading = (View3DShading *)ptr->data;
+ if (value == V3D_LIGHTING_MATCAP && shading->color_type == V3D_SHADING_TEXTURE_COLOR) {
+ shading->color_type = V3D_SHADING_MATERIAL_COLOR;
}
- v3d->shading.light = value;
+ shading->light = value;
}
static const EnumPropertyItem *rna_View3DShading_color_type_itemf(
bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *r_free)
{
- View3D *v3d = (View3D *)ptr->data;
+ View3DShading *shading = (View3DShading *)ptr->data;
int totitem = 0;
EnumPropertyItem *item = NULL;
- if (v3d->drawtype == OB_SOLID) {
+ if (shading->type == OB_SOLID) {
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR);
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_MATERIAL_COLOR);
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_RANDOM_COLOR);
- if (v3d->shading.light != V3D_LIGHTING_MATCAP) {
+ if (shading->light != V3D_LIGHTING_MATCAP) {
RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_TEXTURE_COLOR);
}
}
@@ -796,15 +852,15 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(
/* Studio light */
static int rna_View3DShading_studio_light_get(PointerRNA *ptr)
{
- View3D *v3d = (View3D *)ptr->data;
- char *dna_storage = v3d->shading.studio_light;
+ View3DShading *shading = (View3DShading *)ptr->data;
+ char *dna_storage = shading->studio_light;
int flag = STUDIOLIGHT_ORIENTATIONS_SOLID;
- if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) {
+ if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
flag = STUDIOLIGHT_ORIENTATION_VIEWNORMAL;
- dna_storage = v3d->shading.matcap;
+ dna_storage = shading->matcap;
}
- else if (v3d->drawtype == OB_MATERIAL) {
+ else if (shading->type == OB_MATERIAL) {
flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE;
}
StudioLight *sl = BKE_studiolight_find(dna_storage, flag);
@@ -819,15 +875,15 @@ static int rna_View3DShading_studio_light_get(PointerRNA *ptr)
static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value)
{
- View3D *v3d = (View3D *)ptr->data;
- char *dna_storage = v3d->shading.studio_light;
+ View3DShading *shading = (View3DShading *)ptr->data;
+ char *dna_storage = shading->studio_light;
int flag = STUDIOLIGHT_ORIENTATIONS_SOLID;
- if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) {
+ if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
flag = STUDIOLIGHT_ORIENTATION_VIEWNORMAL;
- dna_storage = v3d->shading.matcap;
+ dna_storage = shading->matcap;
}
- else if (v3d->drawtype == OB_MATERIAL) {
+ else if (shading->type == OB_MATERIAL) {
flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE;
}
StudioLight *sl = BKE_studiolight_findindex(value, flag);
@@ -840,15 +896,15 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(
bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *r_free)
{
- View3D *v3d = (View3D *)ptr->data;
+ View3DShading *shading = (View3DShading *)ptr->data;
EnumPropertyItem *item = NULL;
int totitem = 0;
- if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) {
+ if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
const int flags = (STUDIOLIGHT_EXTERNAL_FILE | STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) {
- int icon_id = (v3d->shading.flag & V3D_SHADING_MATCAP_FLIP_X) ? sl->icon_id_matcap_flipped: sl->icon_id_matcap;
+ int icon_id = (shading->flag & V3D_SHADING_MATCAP_FLIP_X) ? sl->icon_id_matcap_flipped: sl->icon_id_matcap;
if ((sl->flag & flags) == flags) {
EnumPropertyItem tmp = {sl->index, sl->name, icon_id, sl->name, ""};
RNA_enum_item_add(&item, &totitem, &tmp);
@@ -862,12 +918,12 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(
if (sl->flag & STUDIOLIGHT_INTERNAL) {
/* always show internal lights for solid */
- if (v3d->drawtype == OB_SOLID) {
+ if (shading->type == OB_SOLID) {
show_studiolight = true;
}
}
else {
- switch (v3d->drawtype) {
+ switch (shading->type) {
case OB_SOLID:
case OB_TEXTURE:
show_studiolight = (
@@ -914,11 +970,6 @@ static int rna_SpaceView3D_icon_from_show_object_viewport_get(PointerRNA *ptr)
return ICON_VIS_SEL_11 + (view_value << 1) + select_value;
}
-static PointerRNA rna_SpaceView3D_shading_get(PointerRNA *ptr)
-{
- return rna_pointer_inherit_refine(ptr, &RNA_View3DShading, ptr->data);
-}
-
static char *rna_View3DShading_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("shading");
@@ -1308,6 +1359,10 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MODIFIER);
}
+ if (sbuts->pathflag & (1 << BCONTEXT_SHADERFX)) {
+ RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SHADERFX);
+ }
+
if (sbuts->pathflag & (1 << BCONTEXT_DATA)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_DATA);
(item + totitem - 1)->icon = sbuts->dataicon;
@@ -2397,14 +2452,22 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ static const EnumPropertyItem background_type_items[] = {
+ {V3D_SHADING_BACKGROUND_THEME, "THEME", 0, "Theme", "Use the theme for background color"},
+ {V3D_SHADING_BACKGROUND_WORLD, "WORLD", 0, "World", "Use the world for background color"},
+ {V3D_SHADING_BACKGROUND_VIEWPORT, "VIEWPORT", 0, "Viewport", "Use a custom color limited to this viewport only"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static const float default_background_color[] = {0.05f, 0.05f, 0.05f};
+
+
+ /* Note these settings are used for both 3D viewport and the OpenGL render
+ * engine in the scene, so can't assume to always be part of a screen. */
srna = RNA_def_struct(brna, "View3DShading", NULL);
- RNA_def_struct_sdna(srna, "View3D");
- RNA_def_struct_nested(brna, srna, "SpaceView3D");
RNA_def_struct_path_func(srna, "rna_View3DShading_path");
RNA_def_struct_ui_text(srna, "3D View Shading Settings", "Settings for shading in the 3D viewport");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "drawtype");
RNA_def_property_enum_items(prop, rna_enum_shading_type_items);
RNA_def_property_enum_funcs(prop, "rna_3DViewShading_type_get", "rna_3DViewShading_type_set",
"rna_3DViewShading_type_itemf");
@@ -2412,14 +2475,14 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_3DViewShading_type_update");
prop = RNA_def_property(srna, "light", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "shading.light");
+ RNA_def_property_enum_sdna(prop, NULL, "light");
RNA_def_property_enum_items(prop, rna_enum_viewport_lighting_items);
RNA_def_property_enum_funcs(prop, "rna_View3DShading_light_get", "rna_View3DShading_light_set", NULL);
RNA_def_property_ui_text(prop, "Lighting", "Lighting Method for Solid/Texture Viewport Shading");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_object_outline", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_OBJECT_OUTLINE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_OBJECT_OUTLINE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Outline", "Show Object Outline");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -2432,13 +2495,13 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_cavity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_CAVITY);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_CAVITY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Cavity", "Show Cavity");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "cavity_ridge_factor", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.cavity_ridge_factor");
+ RNA_def_property_float_sdna(prop, NULL, "cavity_ridge_factor");
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Ridge", "Factor for the ridges");
RNA_def_property_range(prop, 0.0f, 250.0f);
@@ -2447,7 +2510,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "cavity_valley_factor", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.cavity_valley_factor");
+ RNA_def_property_float_sdna(prop, NULL, "cavity_valley_factor");
RNA_def_property_float_default(prop, 1.0);
RNA_def_property_ui_text(prop, "Valley", "Factor for the valleys");
RNA_def_property_range(prop, 0.0f, 250.0f);
@@ -2464,7 +2527,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_define_verify_sdna(1);
prop = RNA_def_property(srna, "studiolight_rotate_z", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_sdna(prop, NULL, "shading.studiolight_rot_z");
+ RNA_def_property_float_sdna(prop, NULL, "studiolight_rot_z");
RNA_def_property_float_default(prop, 0.0);
RNA_def_property_ui_text(prop, "Studiolight Rotation", "Rotation of the studiolight around the Z-Axis");
RNA_def_property_range(prop, -M_PI, M_PI);
@@ -2472,33 +2535,45 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "color_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "shading.color_type");
+ RNA_def_property_enum_sdna(prop, NULL, "color_type");
RNA_def_property_enum_items(prop, rna_enum_shading_color_type_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_View3DShading_color_type_itemf");
RNA_def_property_ui_text(prop, "Color", "Color Type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "single_color", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.single_color");
+ RNA_def_property_float_sdna(prop, NULL, "single_color");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Color", "Color for single color mode");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "background_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, background_type_items);
+ RNA_def_property_ui_text(prop, "Background", "Way to draw the background");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "background_color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_float_array_default(prop, default_background_color);
+ RNA_def_property_ui_text(prop, "Background Color", "Color for custom background color");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "show_shadows", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SHADOW);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SHADOW);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Shadow", "Show Shadow");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_xray", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_XRAY);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_XRAY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "X-Ray", "Show whole scene transparent");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "xray_alpha", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.xray_alpha");
+ RNA_def_property_float_sdna(prop, NULL, "xray_alpha");
RNA_def_property_float_default(prop, 0.5);
RNA_def_property_ui_text(prop, "X-Ray Alpha", "Amount of alpha to use");
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -2506,32 +2581,32 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "use_scene_lights", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SCENE_LIGHTS);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_LIGHTS);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Scene Lights", "Render lights and light probes of the scene");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "use_scene_world", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SCENE_WORLD);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_WORLD);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Scene World", "Use scene world for lighting");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_specular_highlight", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SPECULAR_HIGHLIGHT);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SPECULAR_HIGHLIGHT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Specular Highlights", "Render specular highlights");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "object_outline_color", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.object_outline_color");
+ RNA_def_property_float_sdna(prop, NULL, "object_outline_color");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Outline Color", "Color for object outline");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "shadow_intensity", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.shadow_intensity");
+ RNA_def_property_float_sdna(prop, NULL, "shadow_intensity");
RNA_def_property_float_default(prop, 0.5);
RNA_def_property_ui_text(prop, "Shadow Intensity", "Darkness of shadows");
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -2540,7 +2615,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "studiolight_background_alpha", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "shading.studiolight_background");
+ RNA_def_property_float_sdna(prop, NULL, "studiolight_background");
RNA_def_property_float_default(prop, 0.0);
RNA_def_property_ui_text(prop, "Background", "Show the studiolight in the background");
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -2563,7 +2638,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_overlays", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag2", V3D_RENDER_OVERRIDE);
RNA_def_property_ui_text(prop, "Show Overlays", "Display overlays like gizmos and outlines");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
prop = RNA_def_property(srna, "show_floor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_FLOOR);
@@ -2781,6 +2856,86 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Weight Paint Opacity", "Opacity of the weight paint mode overlay");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* grease pencil paper settings */
+ prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_ANNOTATION);
+ RNA_def_property_ui_text(prop, "Show Annotation",
+ "Show annotations for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_gpencil_paper", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_PAPER);
+ RNA_def_property_ui_text(prop, "Use Paper",
+ "Cover all viewport with a full color layer to improve visibility while drawing over complex scenes");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_gpencil_grid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_GRID);
+ RNA_def_property_ui_text(prop, "Use Grid",
+ "Draw a grid over grease pencil paper");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "gpencil_grid_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_grid_scale");
+ RNA_def_property_range(prop, 0.01f, FLT_MAX);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Scale", "Grid scale");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "gpencil_grid_lines", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "overlay.gpencil_grid_lines");
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_int_default(prop, GP_DEFAULT_GRID_LINES);
+ RNA_def_property_ui_text(prop, "Subdivisions", "Number of subdivisions in each side of symmetry line");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "gpencil_grid_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "overlay.gpencil_grid_axis");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_grid_axis_items);
+ RNA_def_property_ui_text(prop, "Axis", "Axis to display grid");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "gpencil_grid_opacity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_grid_opacity");
+ RNA_def_property_range(prop, 0.1f, 1.0f);
+ RNA_def_property_float_default(prop, 0.9f);
+ RNA_def_property_ui_text(prop, "Opacity", "Grid opacity");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* Paper opacity factor */
+ prop = RNA_def_property(srna, "gpencil_paper_opacity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_paper_opacity");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_ui_text(prop, "Opacity", "Paper opacity");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* show edit lines */
+ prop = RNA_def_property(srna, "use_gpencil_edit_lines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_EDIT_LINES);
+ RNA_def_property_ui_text(prop, "Edit Lines", "Show edit lines when edit strokes");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_gpencil_multiedit_line_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_MULTIEDIT_LINES);
+ RNA_def_property_ui_text(prop, "Lines Only", "Show only edit lines for additional frames");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+
+ /* main grease pencil onion switch */
+ prop = RNA_def_property(srna, "use_gpencil_onion_skin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_ONION_SKIN);
+ RNA_def_property_ui_text(prop, "Onion Skins", "Show ghosts of the frames before and after the current frame");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+
+ /* vertex opacity */
+ prop = RNA_def_property(srna, "vertex_opacity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vertex_opacity");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Vertex Opacity", "Opacity for edit vertices");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_GPencil_update");
+
}
static void rna_def_space_view3d(BlenderRNA *brna)
@@ -2907,12 +3062,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Clip End", "3D View far clipping distance");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_GPENCIL);
- RNA_def_property_ui_text(prop, "Show Grease Pencil",
- "Show grease pencil for this view");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
prop = RNA_def_property(srna, "show_textured_solid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_TEX);
RNA_def_property_ui_text(prop, "Textured Solid", "Display face-assigned textures in solid view");
@@ -2928,11 +3077,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Lock Camera to View", "Enable view navigation within the camera view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD);
- RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
prop = RNA_def_property(srna, "use_occlude_geometry", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ZBUF_SELECT);
RNA_def_property_ui_text(prop, "Occlude Geometry", "Limit selection to visible (clipped with depth buffer)");
@@ -2940,22 +3084,22 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_gizmo", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "mpr_flag", V3D_GIZMO_HIDE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", V3D_GIZMO_HIDE);
RNA_def_property_ui_text(prop, "Show Gizmo", "Show gizmos of all types");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_gizmo_navigate", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "mpr_flag", V3D_GIZMO_HIDE_NAVIGATE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", V3D_GIZMO_HIDE_NAVIGATE);
RNA_def_property_ui_text(prop, "Navigate Gizmo", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_gizmo_context", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "mpr_flag", V3D_GIZMO_HIDE_CONTEXT);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", V3D_GIZMO_HIDE_CONTEXT);
RNA_def_property_ui_text(prop, "Context Gizmo", "Context sensitive gizmos for the active item");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_gizmo_tool", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "mpr_flag", V3D_GIZMO_HIDE_TOOL);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", V3D_GIZMO_HIDE_TOOL);
RNA_def_property_ui_text(prop, "Tool Gizmo", "Active tool gizmo");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -3098,10 +3242,12 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{"show_object_viewport_lattice", "show_object_select_lattice"}},
{"Empty", (1 << OB_EMPTY),
{"show_object_viewport_empty", "show_object_select_empty"}},
+ {"Grease Pencil", (1 << OB_GPENCIL),
+ {"show_object_viewport_grease_pencil", "show_object_select_grease_pencil"}},
{"Camera", (1 << OB_CAMERA),
{"show_object_viewport_camera", "show_object_select_camera"}},
- {"Lamp", (1 << OB_LAMP),
- {"show_object_viewport_lamp", "show_object_select_lamp"}},
+ {"Light", (1 << OB_LAMP),
+ {"show_object_viewport_light", "show_object_select_light"}},
{"Speaker", (1 << OB_SPEAKER),
{"show_object_viewport_speaker", "show_object_select_speaker"}},
{"Light Probe", (1 << OB_LIGHTPROBE),
@@ -3134,7 +3280,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "shading", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "View3DShading");
- RNA_def_property_pointer_funcs(prop, "rna_SpaceView3D_shading_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Shading Settings", "Settings for shading in the 3D viewport");
prop = RNA_def_property(srna, "overlay", PROP_POINTER, PROP_NONE);
@@ -3338,10 +3483,10 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Repeated", "Draw the image repeated outside of the main view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
- prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_SHOW_GPENCIL);
- RNA_def_property_ui_text(prop, "Show Grease Pencil",
- "Show grease pencil for this view");
+ RNA_def_property_ui_text(prop, "Show Annotation",
+ "Show annotations for this view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "draw_channels", PROP_ENUM, PROP_NONE);
@@ -3390,6 +3535,7 @@ static void rna_def_space_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
@@ -3543,10 +3689,10 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
- prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GPENCIL);
- RNA_def_property_ui_text(prop, "Show Grease Pencil",
- "Show grease pencil for this view");
+ RNA_def_property_ui_text(prop, "Show Annotation",
+ "Show annotations for this view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "display_channel", PROP_INT, PROP_NONE);
@@ -3585,8 +3731,9 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
- RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
+ RNA_def_property_ui_text(prop, "Grease Pencil", "Grease Pencil data for this Preview region");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "overlay_type", PROP_ENUM, PROP_NONE);
@@ -4690,10 +4837,10 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Backdrop", "Use active Viewer Node output as backdrop for compositing nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, "rna_SpaceNodeEditor_show_backdrop_update");
- prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_SHOW_GPENCIL);
- RNA_def_property_ui_text(prop, "Show Grease Pencil",
- "Show grease pencil for this view");
+ RNA_def_property_ui_text(prop, "Show Annotation",
+ "Show annotations for this view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
prop = RNA_def_property(srna, "use_auto_render", PROP_BOOLEAN, PROP_NONE);
@@ -4758,8 +4905,8 @@ static void rna_def_space_clip(BlenderRNA *brna)
};
static const EnumPropertyItem gpencil_source_items[] = {
- {SC_GPENCIL_SRC_CLIP, "CLIP", 0, "Clip", "Show grease pencil data-block which belongs to movie clip"},
- {SC_GPENCIL_SRC_TRACK, "TRACK", 0, "Track", "Show grease pencil data-block which belongs to active track"},
+ {SC_GPENCIL_SRC_CLIP, "CLIP", 0, "Clip", "Show annotation data-block which belongs to movie clip"},
+ {SC_GPENCIL_SRC_TRACK, "TRACK", 0, "Track", "Show annotation data-block which belongs to active track"},
{0, NULL, 0, NULL, NULL}
};
@@ -4909,11 +5056,11 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Manual Calibration", "Use manual calibration helpers");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
- /* show grease pencil */
- prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GPENCIL);
- RNA_def_property_ui_text(prop, "Show Grease Pencil",
- "Show grease pencil for this view");
+ /* show annotation */
+ prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_ANNOTATION);
+ RNA_def_property_ui_text(prop, "Show Annotation",
+ "Show annotations for this view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
/* show filters */
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 5da49ac5957..4c5af755b13 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -1480,6 +1480,7 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_struct_type(prop, "GreasePencil");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this track");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index c9ce9ae7961..a5deb0a32f1 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -759,6 +759,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_string(func, "unlink", NULL, 0, "", "Operator identifier to unlink the ID block");
RNA_def_enum(func, "filter", id_template_filter_items, UI_TEMPLATE_ID_FILTER_ALL,
"", "Optionally limit the items which can be selected");
+ RNA_def_boolean(func, "live_icon", false, "", "Show preview instead of fixed icon");
func = RNA_def_function(srna, "template_ID_preview", "uiTemplateIDPreview");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -831,6 +832,31 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "template_greasepencil_modifier", "uiTemplateGpencilModifier");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Generates the UI layout for grease pencil modifiers");
+ parm = RNA_def_pointer(func, "data", "GpencilModifier", "", "Modifier data");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "template_shaderfx", "uiTemplateShaderFx");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Generates the UI layout for shader effect");
+ parm = RNA_def_pointer(func, "data", "ShaderFx", "", "Shader data");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "template_greasepencil_color", "uiTemplateGpencilColorPreview");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
+ RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);
+ RNA_def_float(func, "scale", 1.0f, 0.1f, 1.5f, "Scale of the image thumbnails", "", 0.5f, 1.0f);
+ RNA_def_enum(func, "filter", id_template_filter_items, UI_TEMPLATE_ID_FILTER_ALL,
+ "", "Optionally limit the items which can be selected");
+
func = RNA_def_function(srna, "template_constraint", "uiTemplateConstraint");
RNA_def_function_ui_description(func, "Generates the UI layout for constraints");
parm = RNA_def_pointer(func, "data", "Constraint", "", "Constraint data");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 5557afdb33f..4c3074bba4f 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -410,15 +410,10 @@ static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
static void rna_userdef_text_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
BLF_cache_clear();
+ UI_reinit_font();
WM_main_add_notifier(NC_WINDOW, NULL);
}
-static void rna_userdef_text_antialiasing_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- BLF_antialias_set((U.text_render & USER_TEXT_DISABLE_AA) == 0);
- rna_userdef_text_update(bmain, scene, ptr);
-}
-
static PointerRNA rna_Theme_space_generic_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_ThemeSpaceGeneric, ptr->data);
@@ -683,7 +678,9 @@ static void rna_UserDef_studiolight_path_irr_cache_get(PointerRNA *ptr, char *va
if (sl->path_irr_cache) {
BLI_strncpy(value, sl->path_irr_cache, FILE_MAX);
}
- value[0] = 0x00;
+ else {
+ value[0] = '\0';
+ }
}
static int rna_UserDef_studiolight_path_irr_cache_length(PointerRNA *ptr)
@@ -702,7 +699,9 @@ static void rna_UserDef_studiolight_path_sh_cache_get(PointerRNA *ptr, char *val
if (sl->path_sh_cache) {
BLI_strncpy(value, sl->path_sh_cache, FILE_MAX);
}
- value[0] = 0x00;
+ else {
+ value[0] = '\0';
+ }
}
static int rna_UserDef_studiolight_path_sh_cache_length(PointerRNA *ptr)
@@ -3427,12 +3426,6 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Direction", "Direction that the OpenGL light is shining");
RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
- prop = RNA_def_property(srna, "diffuse_color", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "col");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Diffuse Color", "Diffuse color of the OpenGL light");
- RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
-
prop = RNA_def_property(srna, "specular_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "spec");
RNA_def_property_array(prop, 3);
@@ -4353,7 +4346,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_text_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
- RNA_def_property_update(prop, 0, "rna_userdef_text_antialiasing_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_text_update");
+
+ prop = RNA_def_property(srna, "use_text_hinting", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_HINTING);
+ RNA_def_property_ui_text(prop, "Text Hinting", "Draw user interface text with hinting");
+ RNA_def_property_update(prop, 0, "rna_userdef_text_update");
prop = RNA_def_property(srna, "select_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "gpu_select_method");
@@ -4373,6 +4371,14 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Enable OpenGL multi-sampling, only for systems that support it, requires restart");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+ /* grease pencil anti-aliasing */
+ prop = RNA_def_property(srna, "gpencil_multi_sample", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_multisamples");
+ RNA_def_property_enum_items(prop, multi_sample_levels);
+ RNA_def_property_ui_text(prop, "Gpencil MultiSample",
+ "Enable Grease Pencil OpenGL multi-sampling, only for systems that support it");
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
+
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
RNA_def_property_ui_text(prop, "Region Overlap",
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 3432adc6eb3..fd0759bfe42 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -382,6 +382,10 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "NDOF Button A", "NdofBA"},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "NDOF Button B", "NdofBB"},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "NDOF Button C", "NdofBC"},
+ /* Action Zones. */
+ {EVT_ACTIONZONE_AREA, "ACTIONZONE_AREA", 0, "ActionZone Area", "AZone Area"},
+ {EVT_ACTIONZONE_REGION, "ACTIONZONE_REGION", 0, "ActionZone Region", "AZone Region"},
+ {EVT_ACTIONZONE_FULLSCREEN, "ACTIONZONE_FULLSCREEN", 0, "ActionZone Fullscreen", "AZone FullScr"},
{0, NULL, 0, NULL, NULL}
};
@@ -432,6 +436,8 @@ static const EnumPropertyItem operator_flag_items[] = {
"is enabled"},
{OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"},
{OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", "Removes the operator from search results"},
+ {OPTYPE_USE_EVAL_DATA, "USE_EVAL_DATA", 0, "Use Evaluated Data",
+ "Uses evaluated data (i.e. needs a valid depsgraph for current context)"},
{0, NULL, 0, NULL, NULL}
};
#endif
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 7abcf0f0667..a1780b45aed 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -120,31 +120,31 @@ static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
static wmGizmoGroupType *wm_gizmogrouptype_find_for_add_remove(ReportList *reports, const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, true);
- if (wgt == NULL) {
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, true);
+ if (gzgt == NULL) {
BKE_reportf(reports, RPT_ERROR, "Gizmo group type '%s' not found!", idname);
return NULL;
}
- if (wgt->flag & WM_GIZMOGROUPTYPE_PERSISTENT) {
+ if (gzgt->flag & WM_GIZMOGROUPTYPE_PERSISTENT) {
BKE_reportf(reports, RPT_ERROR, "Gizmo group '%s' has 'PERSISTENT' option set!", idname);
return NULL;
}
- return wgt;
+ return gzgt;
}
static void rna_gizmo_group_type_add(ReportList *reports, const char *idname)
{
- wmGizmoGroupType *wgt = wm_gizmogrouptype_find_for_add_remove(reports, idname);
- if (wgt != NULL) {
- WM_gizmo_group_type_add_ptr(wgt);
+ wmGizmoGroupType *gzgt = wm_gizmogrouptype_find_for_add_remove(reports, idname);
+ if (gzgt != NULL) {
+ WM_gizmo_group_type_add_ptr(gzgt);
}
}
static void rna_gizmo_group_type_remove(Main *bmain, ReportList *reports, const char *idname)
{
- wmGizmoGroupType *wgt = wm_gizmogrouptype_find_for_add_remove(reports, idname);
- if (wgt != NULL) {
- WM_gizmo_group_type_remove_ptr(bmain, wgt);
+ wmGizmoGroupType *gzgt = wm_gizmogrouptype_find_for_add_remove(reports, idname);
+ if (gzgt != NULL) {
+ WM_gizmo_group_type_remove_ptr(bmain, gzgt);
}
}
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 754ef4575a4..1eee5e5522f 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -76,55 +76,55 @@
#ifdef WITH_PYTHON
static void rna_gizmo_draw_cb(
- const struct bContext *C, struct wmGizmo *mpr)
+ const struct bContext *C, struct wmGizmo *gz)
{
extern FunctionRNA rna_Gizmo_draw_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "draw"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "draw"); */
func = &rna_Gizmo_draw_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
}
static void rna_gizmo_draw_select_cb(
- const struct bContext *C, struct wmGizmo *mpr, int select_id)
+ const struct bContext *C, struct wmGizmo *gz, int select_id)
{
extern FunctionRNA rna_Gizmo_draw_select_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "draw_select"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "draw_select"); */
func = &rna_Gizmo_draw_select_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
RNA_parameter_set_lookup(&list, "select_id", &select_id);
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
}
static int rna_gizmo_test_select_cb(
- struct bContext *C, struct wmGizmo *mpr, const struct wmEvent *event)
+ struct bContext *C, struct wmGizmo *gz, const int location[2])
{
extern FunctionRNA rna_Gizmo_test_select_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "test_select"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "test_select"); */
func = &rna_Gizmo_test_select_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- RNA_parameter_set_lookup(&list, "event", &event);
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ RNA_parameter_set_lookup(&list, "location", location);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
void *ret;
RNA_parameter_get_lookup(&list, "intersect_id", &ret);
@@ -135,23 +135,23 @@ static int rna_gizmo_test_select_cb(
}
static int rna_gizmo_modal_cb(
- struct bContext *C, struct wmGizmo *mpr, const struct wmEvent *event,
+ struct bContext *C, struct wmGizmo *gz, const struct wmEvent *event,
eWM_GizmoFlagTweak tweak_flag)
{
extern FunctionRNA rna_Gizmo_modal_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
const int tweak_flag_int = tweak_flag;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "modal"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "modal"); */
func = &rna_Gizmo_modal_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
RNA_parameter_set_lookup(&list, "event", &event);
RNA_parameter_set_lookup(&list, "tweak", &tweak_flag_int);
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
void *ret;
RNA_parameter_get_lookup(&list, "result", &ret);
@@ -162,37 +162,37 @@ static int rna_gizmo_modal_cb(
}
static void rna_gizmo_setup_cb(
- struct wmGizmo *mpr)
+ struct wmGizmo *gz)
{
extern FunctionRNA rna_Gizmo_setup_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "setup"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "setup"); */
func = &rna_Gizmo_setup_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
- mgroup->type->ext.call((bContext *)NULL, &mpr_ptr, func, &list);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
+ gzgroup->type->ext.call((bContext *)NULL, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
}
static int rna_gizmo_invoke_cb(
- struct bContext *C, struct wmGizmo *mpr, const struct wmEvent *event)
+ struct bContext *C, struct wmGizmo *gz, const struct wmEvent *event)
{
extern FunctionRNA rna_Gizmo_invoke_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "invoke"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "invoke"); */
func = &rna_Gizmo_invoke_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
RNA_parameter_set_lookup(&list, "event", &event);
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
void *ret;
RNA_parameter_get_lookup(&list, "result", &ret);
@@ -203,39 +203,39 @@ static int rna_gizmo_invoke_cb(
}
static void rna_gizmo_exit_cb(
- struct bContext *C, struct wmGizmo *mpr, bool cancel)
+ struct bContext *C, struct wmGizmo *gz, bool cancel)
{
extern FunctionRNA rna_Gizmo_exit_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "exit"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "exit"); */
func = &rna_Gizmo_exit_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
{
int cancel_i = cancel;
RNA_parameter_set_lookup(&list, "cancel", &cancel_i);
}
- mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
}
static void rna_gizmo_select_refresh_cb(
- struct wmGizmo *mpr)
+ struct wmGizmo *gz)
{
extern FunctionRNA rna_Gizmo_select_refresh_func;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- PointerRNA mpr_ptr;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ PointerRNA gz_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
- /* RNA_struct_find_function(&mpr_ptr, "select_refresh"); */
+ RNA_pointer_create(NULL, gz->type->ext.srna, gz, &gz_ptr);
+ /* RNA_struct_find_function(&gz_ptr, "select_refresh"); */
func = &rna_Gizmo_select_refresh_func;
- RNA_parameter_list_create(&list, &mpr_ptr, func);
- mgroup->type->ext.call((bContext *)NULL, &mpr_ptr, func, &list);
+ RNA_parameter_list_create(&list, &gz_ptr, func);
+ gzgroup->type->ext.call((bContext *)NULL, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
}
@@ -266,14 +266,14 @@ static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr)
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->gizmo_map) {
- wmGizmoMap *mmap = ar->gizmo_map;
- for (wmGizmoGroup *mgroup = WM_gizmomap_group_list(mmap)->first;
- mgroup;
- mgroup = mgroup->next)
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ for (wmGizmoGroup *gzgroup = WM_gizmomap_group_list(gzmap)->first;
+ gzgroup;
+ gzgroup = gzgroup->next)
{
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if (mpr->properties == properties) {
- return mpr;
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if (gz->properties == properties) {
+ return gz;
}
}
}
@@ -286,10 +286,10 @@ static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr)
static StructRNA *rna_GizmoProperties_refine(PointerRNA *ptr)
{
- wmGizmo *mpr = rna_GizmoProperties_find_operator(ptr);
+ wmGizmo *gz = rna_GizmoProperties_find_operator(ptr);
- if (mpr)
- return mpr->type->srna;
+ if (gz)
+ return gz->type->srna;
else
return ptr->type;
}
@@ -306,77 +306,77 @@ static IDProperty *rna_GizmoProperties_idprops(PointerRNA *ptr, bool create)
static PointerRNA rna_Gizmo_properties_get(PointerRNA *ptr)
{
- wmGizmo *mpr = ptr->data;
- return rna_pointer_inherit_refine(ptr, mpr->type->srna, mpr->properties);
+ wmGizmo *gz = ptr->data;
+ return rna_pointer_inherit_refine(ptr, gz->type->srna, gz->properties);
}
/* wmGizmo.float */
#define RNA_GIZMO_GENERIC_FLOAT_RW_DEF(func_id, member_id) \
static float rna_Gizmo_##func_id##_get(PointerRNA *ptr) \
{ \
- wmGizmo *mpr = ptr->data; \
- return mpr->member_id; \
+ wmGizmo *gz = ptr->data; \
+ return gz->member_id; \
} \
static void rna_Gizmo_##func_id##_set(PointerRNA *ptr, float value) \
{ \
- wmGizmo *mpr = ptr->data; \
- mpr->member_id = value; \
+ wmGizmo *gz = ptr->data; \
+ gz->member_id = value; \
}
#define RNA_GIZMO_GENERIC_FLOAT_ARRAY_INDEX_RW_DEF(func_id, member_id, index) \
static float rna_Gizmo_##func_id##_get(PointerRNA *ptr) \
{ \
- wmGizmo *mpr = ptr->data; \
- return mpr->member_id[index]; \
+ wmGizmo *gz = ptr->data; \
+ return gz->member_id[index]; \
} \
static void rna_Gizmo_##func_id##_set(PointerRNA *ptr, float value) \
{ \
- wmGizmo *mpr = ptr->data; \
- mpr->member_id[index] = value; \
+ wmGizmo *gz = ptr->data; \
+ gz->member_id[index] = value; \
}
/* wmGizmo.float[len] */
#define RNA_GIZMO_GENERIC_FLOAT_ARRAY_RW_DEF(func_id, member_id, len) \
static void rna_Gizmo_##func_id##_get(PointerRNA *ptr, float value[len]) \
{ \
- wmGizmo *mpr = ptr->data; \
- memcpy(value, mpr->member_id, sizeof(float[len])); \
+ wmGizmo *gz = ptr->data; \
+ memcpy(value, gz->member_id, sizeof(float[len])); \
} \
static void rna_Gizmo_##func_id##_set(PointerRNA *ptr, const float value[len]) \
{ \
- wmGizmo *mpr = ptr->data; \
- memcpy(mpr->member_id, value, sizeof(float[len])); \
+ wmGizmo *gz = ptr->data; \
+ memcpy(gz->member_id, value, sizeof(float[len])); \
}
/* wmGizmo.flag */
#define RNA_GIZMO_GENERIC_FLAG_RW_DEF(func_id, member_id, flag_value) \
static bool rna_Gizmo_##func_id##_get(PointerRNA *ptr) \
{ \
- wmGizmo *mpr = ptr->data; \
- return (mpr->member_id & flag_value) != 0; \
+ wmGizmo *gz = ptr->data; \
+ return (gz->member_id & flag_value) != 0; \
} \
static void rna_Gizmo_##func_id##_set(PointerRNA *ptr, bool value) \
{ \
- wmGizmo *mpr = ptr->data; \
- SET_FLAG_FROM_TEST(mpr->member_id, value, flag_value); \
+ wmGizmo *gz = ptr->data; \
+ SET_FLAG_FROM_TEST(gz->member_id, value, flag_value); \
}
/* wmGizmo.flag (negative) */
#define RNA_GIZMO_GENERIC_FLAG_NEG_RW_DEF(func_id, member_id, flag_value) \
static bool rna_Gizmo_##func_id##_get(PointerRNA *ptr) \
{ \
- wmGizmo *mpr = ptr->data; \
- return (mpr->member_id & flag_value) == 0; \
+ wmGizmo *gz = ptr->data; \
+ return (gz->member_id & flag_value) == 0; \
} \
static void rna_Gizmo_##func_id##_set(PointerRNA *ptr, bool value) \
{ \
- wmGizmo *mpr = ptr->data; \
- SET_FLAG_FROM_TEST(mpr->member_id, !value, flag_value); \
+ wmGizmo *gz = ptr->data; \
+ SET_FLAG_FROM_TEST(gz->member_id, !value, flag_value); \
}
#define RNA_GIZMO_FLAG_RO_DEF(func_id, member_id, flag_value) \
static int rna_Gizmo_##func_id##_get(PointerRNA *ptr) \
{ \
- wmGizmo *mpr = ptr->data; \
- return (mpr->member_id & flag_value) != 0; \
+ wmGizmo *gz = ptr->data; \
+ return (gz->member_id & flag_value) != 0; \
}
RNA_GIZMO_GENERIC_FLOAT_ARRAY_RW_DEF(color, color, 3);
@@ -391,8 +391,8 @@ RNA_GIZMO_GENERIC_FLOAT_ARRAY_RW_DEF(matrix_offset, matrix_offset, 16);
static void rna_Gizmo_matrix_world_get(PointerRNA *ptr, float value[16])
{
- wmGizmo *mpr = ptr->data;
- WM_gizmo_calc_matrix_final(mpr, (float (*)[4])value);
+ wmGizmo *gz = ptr->data;
+ WM_gizmo_calc_matrix_final(gz, (float (*)[4])value);
}
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(scale_basis, scale_basis);
@@ -414,21 +414,21 @@ RNA_GIZMO_FLAG_RO_DEF(state_select, state, WM_GIZMO_STATE_SELECT);
static void rna_Gizmo_state_select_set(struct PointerRNA *ptr, bool value)
{
- wmGizmo *mpr = ptr->data;
- wmGizmoGroup *mgroup = mpr->parent_mgroup;
- WM_gizmo_select_set(mgroup->parent_mmap, mpr, value);
+ wmGizmo *gz = ptr->data;
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ WM_gizmo_select_set(gzgroup->parent_gzmap, gz, value);
}
static PointerRNA rna_Gizmo_group_get(PointerRNA *ptr)
{
- wmGizmo *mpr = ptr->data;
- return rna_pointer_inherit_refine(ptr, &RNA_GizmoGroup, mpr->parent_mgroup);
+ wmGizmo *gz = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_GizmoGroup, gz->parent_gzgroup);
}
#ifdef WITH_PYTHON
static void rna_Gizmo_unregister(struct Main *bmain, StructRNA *type);
-void BPY_RNA_gizmo_wrapper(wmGizmoType *wgt, void *userdata);
+void BPY_RNA_gizmo_wrapper(wmGizmoType *gzgt, void *userdata);
static StructRNA *rna_Gizmo_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
@@ -438,7 +438,7 @@ static StructRNA *rna_Gizmo_register(
char idname[MAX_NAME];
} temp_buffers;
- wmGizmoType dummywt = {NULL};
+ wmGizmoType dummygt = {NULL};
wmGizmo dummymnp = {NULL};
PointerRNA mnp_ptr;
@@ -446,8 +446,8 @@ static StructRNA *rna_Gizmo_register(
int have_function[8];
/* setup dummy gizmo & gizmo type to store static properties in */
- dummymnp.type = &dummywt;
- dummywt.idname = temp_buffers.idname;
+ dummymnp.type = &dummygt;
+ dummygt.idname = temp_buffers.idname;
RNA_pointer_create(NULL, &RNA_Gizmo, &dummymnp, &mnp_ptr);
/* Clear so we can detect if it's left unset. */
@@ -465,71 +465,72 @@ static StructRNA *rna_Gizmo_register(
/* check if we have registered this gizmo type before, and remove it */
{
- const wmGizmoType *wt = WM_gizmotype_find(dummywt.idname, true);
- if (wt && wt->ext.srna) {
- rna_Gizmo_unregister(bmain, wt->ext.srna);
+ const wmGizmoType *gzt = WM_gizmotype_find(dummygt.idname, true);
+ if (gzt && gzt->ext.srna) {
+ rna_Gizmo_unregister(bmain, gzt->ext.srna);
}
}
- if (!RNA_struct_available_or_report(reports, dummywt.idname)) {
+ if (!RNA_struct_available_or_report(reports, dummygt.idname)) {
return NULL;
}
{ /* allocate the idname */
/* For multiple strings see GizmoGroup. */
- dummywt.idname = BLI_strdup(temp_buffers.idname);
+ dummygt.idname = BLI_strdup(temp_buffers.idname);
}
/* create a new gizmo type */
- dummywt.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummywt.idname, &RNA_Gizmo);
+ dummygt.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummygt.idname, &RNA_Gizmo);
/* gizmo properties are registered separately */
- RNA_def_struct_flag(dummywt.ext.srna, STRUCT_NO_IDPROPERTIES);
- dummywt.ext.data = data;
- dummywt.ext.call = call;
- dummywt.ext.free = free;
+ RNA_def_struct_flag(dummygt.ext.srna, STRUCT_NO_IDPROPERTIES);
+ dummygt.ext.data = data;
+ dummygt.ext.call = call;
+ dummygt.ext.free = free;
{
int i = 0;
- dummywt.draw = (have_function[i++]) ? rna_gizmo_draw_cb : NULL;
- dummywt.draw_select = (have_function[i++]) ? rna_gizmo_draw_select_cb : NULL;
- dummywt.test_select = (have_function[i++]) ? rna_gizmo_test_select_cb : NULL;
- dummywt.modal = (have_function[i++]) ? rna_gizmo_modal_cb : NULL;
-// dummywt.property_update = (have_function[i++]) ? rna_gizmo_property_update : NULL;
-// dummywt.position_get = (have_function[i++]) ? rna_gizmo_position_get : NULL;
- dummywt.setup = (have_function[i++]) ? rna_gizmo_setup_cb : NULL;
- dummywt.invoke = (have_function[i++]) ? rna_gizmo_invoke_cb : NULL;
- dummywt.exit = (have_function[i++]) ? rna_gizmo_exit_cb : NULL;
- dummywt.select_refresh = (have_function[i++]) ? rna_gizmo_select_refresh_cb : NULL;
+ dummygt.draw = (have_function[i++]) ? rna_gizmo_draw_cb : NULL;
+ dummygt.draw_select = (have_function[i++]) ? rna_gizmo_draw_select_cb : NULL;
+ dummygt.test_select = (have_function[i++]) ? rna_gizmo_test_select_cb : NULL;
+ dummygt.modal = (have_function[i++]) ? rna_gizmo_modal_cb : NULL;
+// dummygt.property_update = (have_function[i++]) ? rna_gizmo_property_update : NULL;
+// dummygt.position_get = (have_function[i++]) ? rna_gizmo_position_get : NULL;
+ dummygt.setup = (have_function[i++]) ? rna_gizmo_setup_cb : NULL;
+ dummygt.invoke = (have_function[i++]) ? rna_gizmo_invoke_cb : NULL;
+ dummygt.exit = (have_function[i++]) ? rna_gizmo_exit_cb : NULL;
+ dummygt.select_refresh = (have_function[i++]) ? rna_gizmo_select_refresh_cb : NULL;
BLI_assert(i == ARRAY_SIZE(have_function));
}
- WM_gizmotype_append_ptr(BPY_RNA_gizmo_wrapper, (void *)&dummywt);
+ WM_gizmotype_append_ptr(BPY_RNA_gizmo_wrapper, (void *)&dummygt);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
- return dummywt.ext.srna;
+ return dummygt.ext.srna;
}
static void rna_Gizmo_unregister(struct Main *bmain, StructRNA *type)
{
- wmGizmoType *wt = RNA_struct_blender_type_get(type);
+ wmGizmoType *gzt = RNA_struct_blender_type_get(type);
- if (!wt)
+ if (!gzt) {
return;
+ }
- RNA_struct_free_extension(type, &wt->ext);
+ RNA_struct_free_extension(type, &gzt->ext);
RNA_struct_free(&BLENDER_RNA, type);
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
- WM_gizmotype_remove_ptr(NULL, bmain, wt);
+ WM_gizmotype_remove_ptr(NULL, bmain, gzt);
}
static void **rna_Gizmo_instance(PointerRNA *ptr)
{
- wmGizmo *mpr = ptr->data;
- return &mpr->py_instance;
+ wmGizmo *gz = ptr->data;
+ return &gz->py_instance;
}
#endif /* WITH_PYTHON */
@@ -537,8 +538,8 @@ static void **rna_Gizmo_instance(PointerRNA *ptr)
static StructRNA *rna_Gizmo_refine(PointerRNA *mnp_ptr)
{
- wmGizmo *mpr = mnp_ptr->data;
- return (mpr->type && mpr->type->ext.srna) ? mpr->type->ext.srna : &RNA_Gizmo;
+ wmGizmo *gz = mnp_ptr->data;
+ return (gz->type && gz->type->ext.srna) ? gz->type->ext.srna : &RNA_Gizmo;
}
/** \} */
@@ -547,41 +548,41 @@ static StructRNA *rna_Gizmo_refine(PointerRNA *mnp_ptr)
* \{ */
static wmGizmo *rna_GizmoGroup_gizmo_new(
- wmGizmoGroup *mgroup, ReportList *reports, const char *idname)
+ wmGizmoGroup *gzgroup, ReportList *reports, const char *idname)
{
- const wmGizmoType *wt = WM_gizmotype_find(idname, true);
- if (wt == NULL) {
+ const wmGizmoType *gzt = WM_gizmotype_find(idname, true);
+ if (gzt == NULL) {
BKE_reportf(reports, RPT_ERROR, "GizmoType '%s' not known", idname);
return NULL;
}
- wmGizmo *mpr = WM_gizmo_new_ptr(wt, mgroup, NULL);
- return mpr;
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt, gzgroup, NULL);
+ return gz;
}
static void rna_GizmoGroup_gizmo_remove(
- wmGizmoGroup *mgroup, bContext *C, wmGizmo *mpr)
+ wmGizmoGroup *gzgroup, bContext *C, wmGizmo *gz)
{
- WM_gizmo_unlink(&mgroup->gizmos, mgroup->parent_mmap, mpr, C);
+ WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, gz, C);
}
static void rna_GizmoGroup_gizmo_clear(
- wmGizmoGroup *mgroup, bContext *C)
+ wmGizmoGroup *gzgroup, bContext *C)
{
- while (mgroup->gizmos.first) {
- WM_gizmo_unlink(&mgroup->gizmos, mgroup->parent_mmap, mgroup->gizmos.first, C);
+ while (gzgroup->gizmos.first) {
+ WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, gzgroup->gizmos.first, C);
}
}
static void rna_GizmoGroup_name_get(PointerRNA *ptr, char *value)
{
- wmGizmoGroup *mgroup = ptr->data;
- strcpy(value, mgroup->type->name);
+ wmGizmoGroup *gzgroup = ptr->data;
+ strcpy(value, gzgroup->type->name);
}
static int rna_GizmoGroup_name_length(PointerRNA *ptr)
{
- wmGizmoGroup *mgroup = ptr->data;
- return strlen(mgroup->type->name);
+ wmGizmoGroup *gzgroup = ptr->data;
+ return strlen(gzgroup->type->name);
}
/* just to work around 'const char *' warning and to ensure this is a python op */
@@ -607,13 +608,13 @@ static void rna_GizmoGroup_bl_label_set(PointerRNA *ptr, const char *value)
static bool rna_GizmoGroup_has_reports_get(PointerRNA *ptr)
{
- wmGizmoGroup *mgroup = ptr->data;
- return (mgroup->reports && mgroup->reports->list.first);
+ wmGizmoGroup *gzgroup = ptr->data;
+ return (gzgroup->reports && gzgroup->reports->list.first);
}
#ifdef WITH_PYTHON
-static bool rna_gizmogroup_poll_cb(const bContext *C, wmGizmoGroupType *wgt)
+static bool rna_gizmogroup_poll_cb(const bContext *C, wmGizmoGroupType *gzgt)
{
extern FunctionRNA rna_GizmoGroup_poll_func;
@@ -624,12 +625,12 @@ static bool rna_gizmogroup_poll_cb(const bContext *C, wmGizmoGroupType *wgt)
void *ret;
int visible;
- RNA_pointer_create(NULL, wgt->ext.srna, NULL, &ptr); /* dummy */
+ RNA_pointer_create(NULL, gzgt->ext.srna, NULL, &ptr); /* dummy */
func = &rna_GizmoGroup_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- wgt->ext.call((bContext *)C, &ptr, func, &list);
+ gzgt->ext.call((bContext *)C, &ptr, func, &list);
RNA_parameter_get_lookup(&list, "visible", &ret);
visible = *(int *)ret;
@@ -639,25 +640,25 @@ static bool rna_gizmogroup_poll_cb(const bContext *C, wmGizmoGroupType *wgt)
return visible;
}
-static void rna_gizmogroup_setup_cb(const bContext *C, wmGizmoGroup *mgroup)
+static void rna_gizmogroup_setup_cb(const bContext *C, wmGizmoGroup *gzgroup)
{
extern FunctionRNA rna_GizmoGroup_setup_func;
- PointerRNA mgroup_ptr;
+ PointerRNA gzgroup_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ RNA_pointer_create(NULL, gzgroup->type->ext.srna, gzgroup, &gzgroup_ptr);
func = &rna_GizmoGroup_setup_func; /* RNA_struct_find_function(&wgroupr, "setup"); */
- RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_list_create(&list, &gzgroup_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gzgroup_ptr, func, &list);
RNA_parameter_list_free(&list);
}
-static wmKeyMap *rna_gizmogroup_setup_keymap_cb(const wmGizmoGroupType *wgt, wmKeyConfig *config)
+static wmKeyMap *rna_gizmogroup_setup_keymap_cb(const wmGizmoGroupType *gzgt, wmKeyConfig *config)
{
extern FunctionRNA rna_GizmoGroup_setup_keymap_func;
void *ret;
@@ -666,12 +667,12 @@ static wmKeyMap *rna_gizmogroup_setup_keymap_cb(const wmGizmoGroupType *wgt, wmK
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, wgt->ext.srna, NULL, &ptr); /* dummy */
+ RNA_pointer_create(NULL, gzgt->ext.srna, NULL, &ptr); /* dummy */
func = &rna_GizmoGroup_setup_keymap_func; /* RNA_struct_find_function(&wgroupr, "setup_keymap"); */
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "keyconfig", &config);
- wgt->ext.call(NULL, &ptr, func, &list);
+ gzgt->ext.call(NULL, &ptr, func, &list);
RNA_parameter_get_lookup(&list, "keymap", &ret);
wmKeyMap *keymap = *(wmKeyMap **)ret;
@@ -681,43 +682,43 @@ static wmKeyMap *rna_gizmogroup_setup_keymap_cb(const wmGizmoGroupType *wgt, wmK
return keymap;
}
-static void rna_gizmogroup_refresh_cb(const bContext *C, wmGizmoGroup *mgroup)
+static void rna_gizmogroup_refresh_cb(const bContext *C, wmGizmoGroup *gzgroup)
{
extern FunctionRNA rna_GizmoGroup_refresh_func;
- PointerRNA mgroup_ptr;
+ PointerRNA gzgroup_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ RNA_pointer_create(NULL, gzgroup->type->ext.srna, gzgroup, &gzgroup_ptr);
func = &rna_GizmoGroup_refresh_func; /* RNA_struct_find_function(&wgroupr, "refresh"); */
- RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_list_create(&list, &gzgroup_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gzgroup_ptr, func, &list);
RNA_parameter_list_free(&list);
}
-static void rna_gizmogroup_draw_prepare_cb(const bContext *C, wmGizmoGroup *mgroup)
+static void rna_gizmogroup_draw_prepare_cb(const bContext *C, wmGizmoGroup *gzgroup)
{
extern FunctionRNA rna_GizmoGroup_draw_prepare_func;
- PointerRNA mgroup_ptr;
+ PointerRNA gzgroup_ptr;
ParameterList list;
FunctionRNA *func;
- RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ RNA_pointer_create(NULL, gzgroup->type->ext.srna, gzgroup, &gzgroup_ptr);
func = &rna_GizmoGroup_draw_prepare_func; /* RNA_struct_find_function(&wgroupr, "draw_prepare"); */
- RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_list_create(&list, &gzgroup_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
- mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+ gzgroup->type->ext.call((bContext *)C, &gzgroup_ptr, func, &list);
RNA_parameter_list_free(&list);
}
-void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *wgt, void *userdata);
+void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata);
static void rna_GizmoGroup_unregister(struct Main *bmain, StructRNA *type);
static StructRNA *rna_GizmoGroup_register(
@@ -758,21 +759,21 @@ static StructRNA *rna_GizmoGroup_register(
/* check if the area supports widgets */
const struct wmGizmoMapType_Params wmap_params = {
- .spaceid = dummywgt.mmap_params.spaceid,
- .regionid = dummywgt.mmap_params.regionid,
+ .spaceid = dummywgt.gzmap_params.spaceid,
+ .regionid = dummywgt.gzmap_params.regionid,
};
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wmap_params);
- if (mmap_type == NULL) {
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&wmap_params);
+ if (gzmap_type == NULL) {
BKE_reportf(reports, RPT_ERROR, "Area type does not support gizmos");
return NULL;
}
/* check if we have registered this gizmogroup type before, and remove it */
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(dummywgt.idname, true);
- if (wgt && wgt->ext.srna) {
- rna_GizmoGroup_unregister(bmain, wgt->ext.srna);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(dummywgt.idname, true);
+ if (gzgt && gzgt->ext.srna) {
+ rna_GizmoGroup_unregister(bmain, gzgt->ext.srna);
}
}
if (!RNA_struct_available_or_report(reports, dummywgt.idname)) {
@@ -807,18 +808,18 @@ static StructRNA *rna_GizmoGroup_register(
dummywgt.refresh = (have_function[3]) ? rna_gizmogroup_refresh_cb : NULL;
dummywgt.draw_prepare = (have_function[4]) ? rna_gizmogroup_draw_prepare_cb : NULL;
- wmGizmoGroupType *wgt = WM_gizmogrouptype_append_ptr(
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_append_ptr(
BPY_RNA_gizmogroup_wrapper, (void *)&dummywgt);
{
const char *owner_id = RNA_struct_state_owner_get();
if (owner_id) {
- BLI_strncpy(wgt->owner_id, owner_id, sizeof(wgt->owner_id));
+ BLI_strncpy(gzgt->owner_id, owner_id, sizeof(gzgt->owner_id));
}
}
- if (wgt->flag & WM_GIZMOGROUPTYPE_PERSISTENT) {
- WM_gizmo_group_type_add_ptr_ex(wgt, mmap_type);
+ if (gzgt->flag & WM_GIZMOGROUPTYPE_PERSISTENT) {
+ WM_gizmo_group_type_add_ptr_ex(gzgt, gzmap_type);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
@@ -829,37 +830,37 @@ static StructRNA *rna_GizmoGroup_register(
static void rna_GizmoGroup_unregister(struct Main *bmain, StructRNA *type)
{
- wmGizmoGroupType *wgt = RNA_struct_blender_type_get(type);
+ wmGizmoGroupType *gzgt = RNA_struct_blender_type_get(type);
- if (!wgt)
+ if (!gzgt)
return;
- RNA_struct_free_extension(type, &wgt->ext);
+ RNA_struct_free_extension(type, &gzgt->ext);
RNA_struct_free(&BLENDER_RNA, type);
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
- WM_gizmo_group_type_remove_ptr(bmain, wgt);
+ WM_gizmo_group_type_remove_ptr(bmain, gzgt);
}
static void **rna_GizmoGroup_instance(PointerRNA *ptr)
{
- wmGizmoGroup *mgroup = ptr->data;
- return &mgroup->py_instance;
+ wmGizmoGroup *gzgroup = ptr->data;
+ return &gzgroup->py_instance;
}
#endif /* WITH_PYTHON */
-static StructRNA *rna_GizmoGroup_refine(PointerRNA *mgroup_ptr)
+static StructRNA *rna_GizmoGroup_refine(PointerRNA *gzgroup_ptr)
{
- wmGizmoGroup *mgroup = mgroup_ptr->data;
- return (mgroup->type && mgroup->type->ext.srna) ? mgroup->type->ext.srna : &RNA_GizmoGroup;
+ wmGizmoGroup *gzgroup = gzgroup_ptr->data;
+ return (gzgroup->type && gzgroup->type->ext.srna) ? gzgroup->type->ext.srna : &RNA_GizmoGroup;
}
-static void rna_GizmoGroup_gizmos_begin(CollectionPropertyIterator *iter, PointerRNA *mgroup_ptr)
+static void rna_GizmoGroup_gizmos_begin(CollectionPropertyIterator *iter, PointerRNA *gzgroup_ptr)
{
- wmGizmoGroup *mgroup = mgroup_ptr->data;
- rna_iterator_listbase_begin(iter, &mgroup->gizmos, NULL);
+ wmGizmoGroup *gzgroup = gzgroup_ptr->data;
+ rna_iterator_listbase_begin(iter, &gzgroup->gizmos, NULL);
}
/** \} */
@@ -965,7 +966,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "event", "Event", "", "");
+ parm = RNA_def_int_array(func, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Region coordinates", INT_MIN, INT_MAX);
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_int(func, "intersect_id", 0, 0, INT_MAX, "", "", 0, INT_MAX);
RNA_def_function_return(func, parm);
@@ -1210,13 +1211,13 @@ static void rna_def_gizmogroup(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER);
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type->mmap_params.spaceid");
+ RNA_def_property_enum_sdna(prop, NULL, "type->gzmap_params.spaceid");
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type->mmap_params.regionid");
+ RNA_def_property_enum_sdna(prop, NULL, "type->gzmap_params.regionid");
RNA_def_property_enum_items(prop, rna_enum_region_type_items);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo_api.c b/source/blender/makesrna/intern/rna_wm_gizmo_api.c
index 04c02889fa3..e8a9e585165 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo_api.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo_api.c
@@ -47,28 +47,28 @@
#include "ED_gizmo_library.h"
static void rna_gizmo_draw_preset_box(
- wmGizmo *mpr, float matrix[16], int select_id)
+ wmGizmo *gz, float matrix[16], int select_id)
{
- ED_gizmo_draw_preset_box(mpr, (float (*)[4])matrix, select_id);
+ ED_gizmo_draw_preset_box(gz, (float (*)[4])matrix, select_id);
}
static void rna_gizmo_draw_preset_arrow(
- wmGizmo *mpr, float matrix[16], int axis, int select_id)
+ wmGizmo *gz, float matrix[16], int axis, int select_id)
{
- ED_gizmo_draw_preset_arrow(mpr, (float (*)[4])matrix, axis, select_id);
+ ED_gizmo_draw_preset_arrow(gz, (float (*)[4])matrix, axis, select_id);
}
static void rna_gizmo_draw_preset_circle(
- wmGizmo *mpr, float matrix[16], int axis, int select_id)
+ wmGizmo *gz, float matrix[16], int axis, int select_id)
{
- ED_gizmo_draw_preset_circle(mpr, (float (*)[4])matrix, axis, select_id);
+ ED_gizmo_draw_preset_circle(gz, (float (*)[4])matrix, axis, select_id);
}
static void rna_gizmo_draw_preset_facemap(
- wmGizmo *mpr, struct bContext *C, struct Object *ob, int facemap, int select_id)
+ wmGizmo *gz, struct bContext *C, struct Object *ob, int facemap, int select_id)
{
struct Scene *scene = CTX_data_scene(C);
- ED_gizmo_draw_preset_facemap(C, mpr, scene, ob, facemap, select_id);
+ ED_gizmo_draw_preset_facemap(C, gz, scene, ob, facemap, select_id);
}
/* -------------------------------------------------------------------- */
@@ -76,14 +76,14 @@ static void rna_gizmo_draw_preset_facemap(
* \{ */
static void rna_gizmo_target_set_prop(
- wmGizmo *mpr, ReportList *reports, const char *target_propname,
+ wmGizmo *gz, ReportList *reports, const char *target_propname,
PointerRNA *ptr, const char *propname, int index)
{
- const wmGizmoPropertyType *mpr_prop_type =
- WM_gizmotype_target_property_find(mpr->type, target_propname);
- if (mpr_prop_type == NULL) {
+ const wmGizmoPropertyType *gz_prop_type =
+ WM_gizmotype_target_property_find(gz->type, target_propname);
+ if (gz_prop_type == NULL) {
BKE_reportf(reports, RPT_ERROR, "Gizmo target property '%s.%s' not found",
- mpr->type->idname, target_propname);
+ gz->type->idname, target_propname);
return;
}
@@ -94,13 +94,13 @@ static void rna_gizmo_target_set_prop(
return;
}
- if (mpr_prop_type->data_type != RNA_property_type(prop)) {
- const int gizmo_type_index = RNA_enum_from_value(rna_enum_property_type_items, mpr_prop_type->data_type);
+ if (gz_prop_type->data_type != RNA_property_type(prop)) {
+ const int gizmo_type_index = RNA_enum_from_value(rna_enum_property_type_items, gz_prop_type->data_type);
const int prop_type_index = RNA_enum_from_value(rna_enum_property_type_items, RNA_property_type(prop));
BLI_assert((gizmo_type_index != -1) && (prop_type_index == -1));
BKE_reportf(reports, RPT_ERROR, "Gizmo target '%s.%s' expects '%s', '%s.%s' is '%s'",
- mpr->type->idname, target_propname,
+ gz->type->idname, target_propname,
rna_enum_property_type_items[gizmo_type_index].identifier,
RNA_struct_identifier(ptr->type), propname,
rna_enum_property_type_items[prop_type_index].identifier);
@@ -110,37 +110,37 @@ static void rna_gizmo_target_set_prop(
if (RNA_property_array_check(prop)) {
if (index == -1) {
const int prop_array_length = RNA_property_array_length(ptr, prop);
- if (mpr_prop_type->array_length != prop_array_length) {
+ if (gz_prop_type->array_length != prop_array_length) {
BKE_reportf(reports, RPT_ERROR,
"Gizmo target property '%s.%s' expects an array of length %d, found %d",
- mpr->type->idname, target_propname,
- mpr_prop_type->array_length,
+ gz->type->idname, target_propname,
+ gz_prop_type->array_length,
prop_array_length);
return;
}
}
}
else {
- if (mpr_prop_type->array_length != 1) {
+ if (gz_prop_type->array_length != 1) {
BKE_reportf(reports, RPT_ERROR,
"Gizmo target property '%s.%s' expects an array of length %d",
- mpr->type->idname, target_propname,
- mpr_prop_type->array_length);
+ gz->type->idname, target_propname,
+ gz_prop_type->array_length);
return;
}
}
- if (index >= mpr_prop_type->array_length) {
+ if (index >= gz_prop_type->array_length) {
BKE_reportf(reports, RPT_ERROR, "Gizmo target property '%s.%s', index %d must be below %d",
- mpr->type->idname, target_propname, index, mpr_prop_type->array_length);
+ gz->type->idname, target_propname, index, gz_prop_type->array_length);
return;
}
- WM_gizmo_target_property_def_rna_ptr(mpr, mpr_prop_type, ptr, prop, index);
+ WM_gizmo_target_property_def_rna_ptr(gz, gz_prop_type, ptr, prop, index);
}
static PointerRNA rna_gizmo_target_set_operator(
- wmGizmo *mpr, ReportList *reports, const char *opname, int part_index)
+ wmGizmo *gz, ReportList *reports, const char *opname, int part_index)
{
wmOperatorType *ot;
@@ -157,7 +157,7 @@ static PointerRNA rna_gizmo_target_set_operator(
properties = IDP_New(IDP_GROUP, &val, "wmGizmoProperties");
}
- return *WM_gizmo_operator_set(mpr, part_index, ot, properties);
+ return *WM_gizmo_operator_set(gz, part_index, ot, properties);
}
/** \} */
@@ -167,16 +167,16 @@ static PointerRNA rna_gizmo_target_set_operator(
* \{ */
static bool rna_gizmo_target_is_valid(
- wmGizmo *mpr, ReportList *reports, const char *target_propname)
+ wmGizmo *gz, ReportList *reports, const char *target_propname)
{
- wmGizmoProperty *mpr_prop =
- WM_gizmo_target_property_find(mpr, target_propname);
- if (mpr_prop == NULL) {
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, target_propname);
+ if (gz_prop == NULL) {
BKE_reportf(reports, RPT_ERROR, "Gizmo target property '%s.%s' not found",
- mpr->type->idname, target_propname);
+ gz->type->idname, target_propname);
return false;
}
- return WM_gizmo_target_property_is_valid(mpr_prop);
+ return WM_gizmo_target_property_is_valid(gz_prop);
}
/** \} */
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 166d71689d1..88b79e8ee32 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -224,6 +224,12 @@ static void rna_def_workspace_tool(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "");
RNA_def_property_int_funcs(prop, "rna_WorkspaceTool_index_get", NULL, NULL);
+ prop = RNA_def_property(srna, "space_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "space_type");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_items(prop, rna_enum_space_type_items);
+ RNA_def_property_ui_text(prop, "Space Type", "");
+
RNA_api_workspace_tool(srna);
}
diff --git a/source/blender/makesrna/intern/rna_workspace_api.c b/source/blender/makesrna/intern/rna_workspace_api.c
index 98e84f60b33..aac38d05cd8 100644
--- a/source/blender/makesrna/intern/rna_workspace_api.c
+++ b/source/blender/makesrna/intern/rna_workspace_api.c
@@ -41,6 +41,8 @@
#ifdef RNA_RUNTIME
+#include "BKE_paint.h"
+
#include "ED_screen.h"
static void rna_WorkspaceTool_setup(
@@ -68,6 +70,51 @@ static void rna_WorkspaceTool_setup(
WM_toolsystem_ref_set_from_runtime(C, (WorkSpace *)id, tref, &tref_rt, name);
}
+static void rna_WorkspaceTool_refresh_from_context(
+ ID *id,
+ bToolRef *tref,
+ Main *bmain)
+{
+ bToolRef_Runtime *tref_rt = tref->runtime;
+ if ((tref_rt == NULL) || (tref_rt->data_block[0] == '\0')) {
+ return;
+ }
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ if (&workspace->id == id) {
+ Scene *scene = WM_window_get_active_scene(win);
+ ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *ob = OBACT(view_layer);
+ if (ob == NULL) {
+ /* pass */
+ }
+ else if (ob->mode & OB_MODE_PARTICLE_EDIT) {
+ const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items;
+ const int i = RNA_enum_from_value(items, ts->particle.brushtype);
+ const EnumPropertyItem *item = &items[i];
+ if (!STREQ(tref_rt->data_block, item->identifier)) {
+ STRNCPY(tref_rt->data_block, item->identifier);
+ STRNCPY(tref->idname, item->name);
+ }
+ }
+ else {
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
+ if (paint) {
+ const ID *brush = (ID *)paint->brush;
+ if (brush) {
+ if (!STREQ(tref_rt->data_block, brush->name + 2)) {
+ STRNCPY(tref_rt->data_block, brush->name + 2);
+ STRNCPY(tref->idname, brush->name + 2);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
static PointerRNA rna_WorkspaceTool_operator_properties(
bToolRef *tref,
const char *idname)
@@ -124,6 +171,8 @@ void RNA_api_workspace_tool(StructRNA *srna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "refresh_from_context", "rna_WorkspaceTool_refresh_from_context");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index ead67814f01..fe561cdef1c 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -199,6 +199,8 @@ void RNA_def_world(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ static float default_world_color[] = {0.05f, 0.05f, 0.05f};
+
srna = RNA_def_struct(brna, "World", "ID");
RNA_def_struct_ui_text(srna, "World",
"World data-block describing the environment and ambient lighting of a scene");
@@ -207,10 +209,11 @@ void RNA_def_world(BlenderRNA *brna)
rna_def_animdata_common(srna);
/* colors */
- prop = RNA_def_property(srna, "horizon_color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "horr");
RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Horizon Color", "Color at the horizon");
+ RNA_def_property_float_array_default(prop, default_world_color);
+ RNA_def_property_ui_text(prop, "Color", "Color of the background");
/* RNA_def_property_update(prop, 0, "rna_World_update"); */
/* render-only uses this */
RNA_def_property_update(prop, 0, "rna_World_draw_update");
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 45a4070d29f..43dc8507ffb 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -101,6 +101,7 @@ set(SRC
intern/MOD_uvproject.c
intern/MOD_warp.c
intern/MOD_wave.c
+ intern/MOD_weighted_normal.c
intern/MOD_weightvg_util.c
intern/MOD_weightvgedit.c
intern/MOD_weightvgmix.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index cf3794dfaa5..d6e4e1868b2 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -86,6 +86,7 @@ extern ModifierTypeInfo modifierType_NormalEdit;
extern ModifierTypeInfo modifierType_CorrectiveSmooth;
extern ModifierTypeInfo modifierType_MeshSequenceCache;
extern ModifierTypeInfo modifierType_SurfaceDeform;
+extern ModifierTypeInfo modifierType_WeightedNormal;
extern ModifierTypeInfo modifierType_Hair;
/* MOD_util.c */
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 5ae0013aab0..085f21fe138 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -456,9 +456,10 @@ static Mesh *arrayModifier_doArray(
if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
Curve *cu = amd->curve_ob->data;
if (cu) {
- if (amd->curve_ob->curve_cache && amd->curve_ob->curve_cache->path) {
+ CurveCache *curve_cache = amd->curve_ob->runtime.curve_cache;
+ if (curve_cache != NULL && curve_cache->path != NULL) {
float scale_fac = mat4_to_scale(amd->curve_ob->obmat);
- length = scale_fac * amd->curve_ob->curve_cache->path->totdist;
+ length = scale_fac * curve_cache->path->totdist;
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 64d1a6c310b..ba07a3a56cc 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -32,11 +32,15 @@
* \ingroup modifiers
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_string.h"
@@ -49,6 +53,8 @@
#include "bmesh.h"
#include "bmesh_tools.h"
+#include "DEG_depsgraph_query.h"
+
static void initData(ModifierData *md)
{
BevelModifierData *bmd = (BevelModifierData *) md;
@@ -59,10 +65,14 @@ static void initData(ModifierData *md)
bmd->val_flags = MOD_BEVEL_AMT_OFFSET;
bmd->lim_flags = 0;
bmd->e_flags = 0;
+ bmd->edge_flags = 0;
bmd->mat = -1;
bmd->profile = 0.5f;
bmd->bevel_angle = DEG2RADF(30.0f);
bmd->defgrp_name[0] = '\0';
+ bmd->hnmode = MOD_BEVEL_HN_NONE;
+ bmd->hn_strength = 0.5f;
+ bmd->clnordata.faceHash = NULL;
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
@@ -76,6 +86,254 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
+static void bevel_set_weighted_normal_face_strength(BMesh *bm, Scene *scene)
+{
+ BMFace *f;
+ BMIter fiter;
+ const char *wn_layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
+
+ if (cd_prop_int_idx == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, wn_layer_id);
+ cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
+ }
+ cd_prop_int_idx -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_idx);
+
+ const int face_strength = scene->toolsettings->face_strength;
+
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength = face_strength;
+ }
+ }
+}
+
+static void bevel_mod_harden_normals(
+ BevelModifierData *bmd, BMesh *bm, const float hn_strength,
+ const int hnmode, MDeformVert *dvert, int vgroup)
+{
+ if (bmd->res > 20 || bmd->value == 0)
+ return;
+
+ BM_mesh_normals_update(bm);
+ BM_lnorspace_update(bm);
+ BM_normals_loops_edges_tag(bm, true);
+
+ const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ const bool do_normal_to_recon = (hn_strength == 1.0f);
+
+ BMFace *f;
+ BMLoop *l, *l_cur, *l_first;
+ BMIter fiter;
+ GHash *faceHash = bmd->clnordata.faceHash;
+
+ /* Iterate throught all loops of a face */
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+
+ l_cur = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if ((!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG)) ||
+ (!BM_elem_flag_test(l_cur, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_cur)))
+ {
+
+ /* previous and next edge is sharp, accumulate face normals into loop */
+ if (!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_cur->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_cur);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_cur, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_cur->v;
+ BMEdge *e_next;
+ const BMEdge *e_org = l_cur->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+ UNUSED_VARS_NDEBUG(v_pivot);
+
+ lfan_pivot = l_cur;
+ e_next = lfan_pivot->e;
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float cn_wght[3] = { 0.0f, 0.0f, 0.0f };
+ int recon_face_count = 0; /* Counts number of reconstructed faces current vert is connected to */
+ BMFace *recon_face = NULL; /* Reconstructed face */
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
+
+ if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
+ int weight = BM_elem_float_data_get(&bm->edata, lfan_pivot->f, CD_BWEIGHT);
+ if (weight) {
+ if (hnmode == MOD_BEVEL_HN_FACE) {
+ float cur[3]; //Add area weighted face normals
+ mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
+ add_v3_v3(cn_wght, cur);
+ }
+ else
+ add_v3_v3(cn_wght, lfan_pivot->f->no); //Else simply add face normals
+ }
+ else
+ add_v3_v3(cn_wght, lfan_pivot->f->no);
+
+ }
+ else if (bmd->lim_flags & MOD_BEVEL_VGROUP) {
+ const bool has_vgroup = dvert != NULL;
+ const bool vert_of_group = (
+ has_vgroup &&
+ (defvert_find_index(&dvert[BM_elem_index_get(l->v)], vgroup) != NULL));
+
+ if (vert_of_group && hnmode == MOD_BEVEL_HN_FACE) {
+ float cur[3];
+ mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
+ add_v3_v3(cn_wght, cur);
+ }
+ else
+ add_v3_v3(cn_wght, lfan_pivot->f->no);
+ }
+ else {
+ float cur[3];
+ mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
+ add_v3_v3(cn_wght, cur);
+ }
+ if (!BLI_ghash_haskey(faceHash, lfan_pivot->f)) {
+ recon_face = f;
+ recon_face_count++;
+ }
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+
+ normalize_v3(cn_wght);
+ mul_v3_fl(cn_wght, hn_strength);
+ float n_final[3];
+
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+
+ /* If vertex is edge vert with 1 reconnected face */
+ if (recon_face_count == 1 || do_normal_to_recon) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], recon_face->no, clnors);
+ }
+ else if (vertex_only == false || recon_face_count == 0) {
+ copy_v3_v3(n_final, l->f->no);
+ mul_v3_fl(n_final, 1.0f - hn_strength);
+ add_v3_v3(n_final, cn_wght);
+ normalize_v3(n_final);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
+ }
+ else if (BLI_ghash_haskey(faceHash, l->f)) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], l->v->no, clnors);
+ }
+ }
+ }
+ }
+ } while ((l_cur = l_cur->next) != l_first);
+ }
+}
+
+static void bevel_fix_normal_shading_continuity(BevelModifierData *bmd, BMesh *bm)
+{
+ const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
+ if (bmd->value == 0 || (bmd->clnordata.faceHash == NULL && vertex_only))
+ return;
+
+ BM_mesh_normals_update(bm);
+ BM_lnorspace_update(bm);
+
+ GHash *faceHash = bmd->clnordata.faceHash;
+ BMEdge *e;
+ BMLoop *l;
+ BMIter liter, eiter;
+
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ const float hn_strength = bmd->hn_strength;
+ float ref = 10.0f;
+
+ BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
+ BMFace *f_a, *f_b;
+ BM_edge_face_pair(e, &f_a, &f_b);
+
+ bool has_f_a = false, has_f_b = false;
+ if (f_a)
+ has_f_a = BLI_ghash_haskey(faceHash, f_a);
+ if (f_b)
+ has_f_b = BLI_ghash_haskey(faceHash, f_b);
+ if (has_f_a ^ has_f_b) {
+ /* If one of both faces is present in faceHash then we are at a border
+ * between new vmesh created and reconstructed face */
+
+ for (int i = 0; i < 2; i++) {
+ BMVert *v = (i == 0) ? e->v1 : e->v2;
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+
+ if (l->f == f_a || l->f == f_b) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ float n_final[3], pow_a[3], pow_b[3];
+
+ zero_v3(n_final);
+ copy_v3_v3(pow_a, f_a->no);
+ copy_v3_v3(pow_b, f_b->no);
+ if (has_f_a) {
+ mul_v3_fl(pow_a, bmd->res / ref);
+ mul_v3_fl(pow_b, ref / bmd->res);
+ }
+ else {
+ mul_v3_fl(pow_b, bmd->res / ref);
+ mul_v3_fl(pow_a, ref / bmd->res);
+ }
+ add_v3_v3(n_final, pow_a);
+ add_v3_v3(n_final, pow_b);
+ normalize_v3(n_final);
+
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
+ }
+ }
+ }
+ }
+ else if (has_f_a == true && has_f_b == true) {
+ /* Else if both faces are present we assign clnor corresponding
+ * to vert normal and face normal */
+ for (int i = 0; i < 2; i++) {
+ BMVert *v = (i == 0) ? e->v1 : e->v2;
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+
+ if (l->f == f_a || l->f == f_b) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ float n_final[3], cn_wght[3];
+
+ copy_v3_v3(n_final, v->no);
+ mul_v3_fl(n_final, hn_strength);
+
+ copy_v3_v3(cn_wght, l->f->no);
+ mul_v3_fl(cn_wght, 1.0f - hn_strength);
+
+ add_v3_v3(n_final, cn_wght);
+ normalize_v3(n_final);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], n_final, clnors);
+ }
+ }
+ }
+ }
+ }
+}
+
/*
* This calls the new bevel code (added since 2.64)
*/
@@ -96,6 +354,11 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
const int offset_type = bmd->val_flags;
const int mat = CLAMPIS(bmd->mat, -1, ctx->object->totcol - 1);
const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0;
+ const bool mark_seam = (bmd->edge_flags & MOD_BEVEL_MARK_SEAM);
+ const bool mark_sharp = (bmd->edge_flags & MOD_BEVEL_MARK_SHARP);
+ const bool set_wn_strength = (bmd->flags & MOD_BEVEL_SET_WN_STR);
+
+ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
bm = BKE_mesh_to_bmesh_ex(
mesh,
@@ -166,7 +429,15 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile,
vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp,
- dvert, vgroup, mat, loop_slide);
+ dvert, vgroup, mat, loop_slide, mark_seam, mark_sharp, bmd->hnmode, &bmd->clnordata);
+
+ if (bmd->hnmode != BEVEL_HN_FIX_SHA && bmd->hnmode != MOD_BEVEL_HN_NONE) {
+ bevel_mod_harden_normals(bmd, bm, bmd->hn_strength, bmd->hnmode, dvert, vgroup);
+ }
+ if (bmd->hnmode == BEVEL_HN_FIX_SHA)
+ bevel_fix_normal_shading_continuity(bmd, bm);
+ if (set_wn_strength)
+ bevel_set_weighted_normal_face_strength(bm, scene);
result = BKE_bmesh_to_mesh_nomain(bm, &(struct BMeshToMeshParams){0});
@@ -175,6 +446,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
bm->ftoolflagpool == NULL); /* make sure we never alloc'd these */
BM_mesh_free(bm);
+ if (bmd->clnordata.faceHash)
+ BLI_ghash_free(bmd->clnordata.faceHash, NULL, NULL);
+
result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
return result;
@@ -192,7 +466,8 @@ ModifierTypeInfo modifierType_Bevel = {
/* type */ eModifierTypeType_Constructive,
/* flags */ eModifierTypeFlag_AcceptsMesh |
eModifierTypeFlag_SupportsEditmode |
- eModifierTypeFlag_EnableInEditmode,
+ eModifierTypeFlag_EnableInEditmode |
+ eModifierTypeFlag_AcceptsCVs,
/* copyData */ modifier_copyData_generic,
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 3a1fe1513af..1fac637a9ef 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -774,7 +774,7 @@ static Mesh *applyModifier(
/* add faces & edges */
origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX);
- BLI_assert(origindex_edge != NULL);
+ BLI_assert((numEdges == 0) || (origindex_edge != NULL));
ed = &medge[(numEdges * stride) + newEdges]; /* start after copied edges */
orig_ed = &origindex_edge[(numEdges * stride) + newEdges];
for (i = 0; i < rimVerts; i++, ed++, orig_ed++) {
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index f532c168b04..1b25b4f62dc 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -35,8 +35,9 @@
#include <stddef.h>
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
#ifdef WITH_OPENSUBDIV
# include "DNA_userdef_types.h"
@@ -44,9 +45,9 @@
#include "BLI_utildefines.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_scene.h"
+#include "BKE_subdiv.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -56,6 +57,8 @@
#include "intern/CCGSubSurf.h"
+// #define USE_OPENSUBDIV
+
static void initData(ModifierData *md)
{
SubsurfModifierData *smd = (SubsurfModifierData *) md;
@@ -181,9 +184,70 @@ static DerivedMesh *applyModifierEM(
#endif
result = subsurf_make_derived_from_derived(derivedData, smd, scene, NULL, ss_flags);
+ return result;
+}
+
+#ifdef USE_OPENSUBDIV
+static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd,
+ const ModifierEvalContext *ctx)
+{
+ Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
+ const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
+ const int requested_levels = (use_render_params) ? smd->renderLevels
+ : smd->levels;
+ return get_render_subsurf_level(&scene->r,
+ requested_levels,
+ use_render_params);
+}
+
+static void subdiv_settings_init(SubdivSettings *settings,
+ const SubsurfModifierData *smd,
+ const ModifierEvalContext *ctx)
+{
+ settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
+ settings->is_adaptive = !settings->is_simple;
+ settings->level = subdiv_levels_for_modifier_get(smd, ctx);
+ settings->fvar_linear_interpolation =
+ (smd->flags & eSubsurfModifierFlag_SubsurfUv)
+ ? SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY
+ : SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL;
+}
+
+static void subdiv_mesh_settings_init(SubdivToMeshSettings *settings,
+ const SubdivSettings *subdiv_settings)
+{
+ settings->resolution = (1 << subdiv_settings->level) + 1;
+}
+static Mesh *applyModifier_subdiv(ModifierData *md,
+ const ModifierEvalContext *ctx,
+ Mesh *mesh)
+{
+ Mesh *result = mesh;
+ SubsurfModifierData *smd = (SubsurfModifierData *) md;
+ SubdivSettings subdiv_settings;
+ subdiv_settings_init(&subdiv_settings, smd, ctx);
+ if (subdiv_settings.level == 0) {
+ /* NOTE: Shouldn't really happen, is supposed to be catched by
+ * isDisabled() callback.
+ */
+ return result;
+ }
+ /* TODO(sergey): Try to re-use subdiv when possible. */
+ Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, mesh);
+ if (subdiv == NULL) {
+ /* Happens on bad topology, ut also on empty input mesh. */
+ return result;
+ }
+ SubdivToMeshSettings mesh_settings;
+ subdiv_mesh_settings_init(&mesh_settings, &subdiv_settings);
+ result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
+ /* TODO(sergey): Cache subdiv somehow. */
+ // BKE_subdiv_stats_print(&subdiv->stats);
+ BKE_subdiv_free(subdiv);
return result;
}
+#endif
static bool dependsOnNormals(ModifierData *md)
{
@@ -222,7 +286,11 @@ ModifierTypeInfo modifierType_Subsurf = {
/* deformMatrices */ NULL,
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
+#ifdef USE_OPENSUBDIV
+ /* applyModifier */ applyModifier_subdiv,
+#else
/* applyModifier */ NULL,
+#endif
/* applyModifierEM */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 42fd37c19f2..b240dd18119 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -290,6 +290,7 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(CorrectiveSmooth);
INIT_TYPE(MeshSequenceCache);
INIT_TYPE(SurfaceDeform);
+ INIT_TYPE(WeightedNormal);
INIT_TYPE(Hair);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
new file mode 100644
index 00000000000..69c71d34dbc
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -0,0 +1,671 @@
+/*
+ * ***** 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/modifiers/intern/MOD_weighted_normal.c
+ * \ingroup modifiers
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_deform.h"
+#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_mesh.h"
+
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_util.h"
+
+#define CLNORS_VALID_VEC_LEN (1e-6f)
+
+typedef struct ModePair {
+ float val; /* Contains mode based value (face area / corner angle). */
+ int index; /* Index value per poly or per loop. */
+} ModePair;
+
+/* Sorting function used in modifier, sorts in decreasing order. */
+static int modepair_cmp_by_val_inverse(const void *p1, const void *p2)
+{
+ ModePair *r1 = (ModePair *)p1;
+ ModePair *r2 = (ModePair *)p2;
+
+ return (r1->val < r2->val) ? 1 : ((r1->val > r2->val) ? -1 : 0);
+}
+
+/* There will be one of those per vertex (simple case, computing one normal per vertex), or per smooth fan. */
+typedef struct WeightedNormalDataAggregateItem {
+ float normal[3];
+
+ int num_loops; /* Count number of loops using this item so far. */
+ float curr_val; /* Current max val for this item. */
+ int curr_strength; /* Current max strength encountered for this item. */
+} WeightedNormalDataAggregateItem;
+
+#define NUM_CACHED_INVERSE_POWERS_OF_WEIGHT 128
+
+typedef struct WeightedNormalData {
+ const int numVerts;
+ const int numEdges;
+ const int numLoops;
+ const int numPolys;
+
+ MVert *mvert;
+ MEdge *medge;
+
+ MLoop *mloop;
+ short (*clnors)[2];
+ const bool has_clnors; /* True if clnors already existed, false if we had to create them. */
+ const float split_angle;
+
+ MPoly *mpoly;
+ float (*polynors)[3];
+ int *poly_strength;
+
+ MDeformVert *dvert;
+ const int defgrp_index;
+ const bool use_invert_vgroup;
+
+ const float weight;
+ const short mode;
+
+ /* Lower-level, internal processing data. */
+ float cached_inverse_powers_of_weight[NUM_CACHED_INVERSE_POWERS_OF_WEIGHT];
+
+ WeightedNormalDataAggregateItem *items_data;
+
+ ModePair *mode_pair;
+
+ int *loop_to_poly;
+} WeightedNormalData;
+
+/* Check strength of given poly compared to those found so far for that given item (vertex or smooth fan),
+ * and reset matching item_data in case we get a stronger new strength. */
+static bool check_item_poly_strength(
+ WeightedNormalData *wn_data, WeightedNormalDataAggregateItem *item_data, const int mp_index)
+{
+ BLI_assert (wn_data->poly_strength != NULL);
+
+ const int mp_strength = wn_data->poly_strength[mp_index];
+
+ if (mp_strength > item_data->curr_strength) {
+ item_data->curr_strength = mp_strength;
+ item_data->curr_val = 0.0f;
+ item_data->num_loops = 0;
+ zero_v3(item_data->normal);
+ }
+
+ return mp_strength == item_data->curr_strength;
+}
+
+static void aggregate_item_normal(
+ WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data,
+ WeightedNormalDataAggregateItem *item_data,
+ const int mv_index, const int mp_index,
+ const float curr_val, const bool use_face_influence)
+{
+ float (*polynors)[3] = wn_data->polynors;
+
+ MDeformVert *dvert = wn_data->dvert;
+ const int defgrp_index = wn_data->defgrp_index;
+ const bool use_invert_vgroup = wn_data->use_invert_vgroup;
+
+ const float weight = wn_data->weight;
+
+ float *cached_inverse_powers_of_weight = wn_data->cached_inverse_powers_of_weight;
+
+ const bool has_vgroup = dvert != NULL;
+ const bool vert_of_group = has_vgroup && defvert_find_index(&dvert[mv_index], defgrp_index) != NULL;
+
+ if (has_vgroup && ((vert_of_group && use_invert_vgroup) || (!vert_of_group && !use_invert_vgroup))) {
+ return;
+ }
+
+ if (use_face_influence && !check_item_poly_strength(wn_data, item_data, mp_index)) {
+ return;
+ }
+
+ /* If item's curr_val is 0 init it to present value. */
+ if (item_data->curr_val == 0.0f) {
+ item_data->curr_val = curr_val;
+ }
+ if (!compare_ff(item_data->curr_val, curr_val, wnmd->thresh)) {
+ /* item's curr_val and present value differ more than threshold, update. */
+ item_data->num_loops++;
+ item_data->curr_val = curr_val;
+ }
+
+ /* Exponentially divided weight for each normal (since a few values will be used by most cases, we cache those). */
+ const int num_loops = item_data->num_loops;
+ if (num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT && cached_inverse_powers_of_weight[num_loops] == 0.0f) {
+ cached_inverse_powers_of_weight[num_loops] = 1.0f / powf(weight, num_loops);
+ }
+ const float inverted_n_weight = num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ?
+ cached_inverse_powers_of_weight[num_loops] : 1.0f / powf(weight, num_loops);
+
+ madd_v3_v3fl(item_data->normal, polynors[mp_index], curr_val * inverted_n_weight);
+}
+
+static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
+{
+ const int numVerts = wn_data->numVerts;
+ const int numEdges = wn_data->numEdges;
+ const int numLoops = wn_data->numLoops;
+ const int numPolys = wn_data->numPolys;
+
+ MVert *mvert = wn_data->mvert;
+ MEdge *medge = wn_data->medge;
+
+ MLoop *mloop = wn_data->mloop;
+ short (*clnors)[2] = wn_data->clnors;
+ int *loop_to_poly = wn_data->loop_to_poly;
+
+ MPoly *mpoly = wn_data->mpoly;
+ float (*polynors)[3] = wn_data->polynors;
+ int *poly_strength = wn_data->poly_strength;
+
+ MDeformVert *dvert = wn_data->dvert;
+
+ const short mode = wn_data->mode;
+ ModePair *mode_pair = wn_data->mode_pair;
+
+ const bool has_clnors = wn_data->has_clnors;
+ const float split_angle = wn_data->split_angle;
+ MLoopNorSpaceArray lnors_spacearr = {NULL};
+
+ const bool keep_sharp = (wnmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0;
+ const bool use_face_influence = (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) != 0 && poly_strength != NULL;
+ const bool has_vgroup = dvert != NULL;
+
+ float (*loop_normals)[3] = NULL;
+
+ WeightedNormalDataAggregateItem *items_data = NULL;
+ int num_items = 0;
+ if (keep_sharp) {
+ BLI_bitmap *done_loops = BLI_BITMAP_NEW(numLoops, __func__);
+
+ /* This will give us loop normal spaces, we do not actually care about computed loop_normals for now... */
+ loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__);
+ BKE_mesh_normals_loop_split(mvert, numVerts, medge, numEdges,
+ mloop, loop_normals, numLoops, mpoly, polynors, numPolys,
+ true, split_angle, &lnors_spacearr, has_clnors ? clnors : NULL, loop_to_poly);
+
+ num_items = lnors_spacearr.num_spaces;
+ items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__);
+
+ /* In this first loop, we assign each WeightedNormalDataAggregateItem
+ * to its smooth fan of loops (aka lnor space). */
+ MPoly *mp;
+ int mp_index;
+ int item_index;
+ for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ int ml_index = mp->loopstart;
+ const int ml_end_index = ml_index + mp->totloop;
+
+ for (; ml_index < ml_end_index; ml_index++) {
+ if (BLI_BITMAP_TEST(done_loops, ml_index)) {
+ /* Smooth fan of this loop has already been processed, skip it. */
+ continue;
+ }
+ BLI_assert(item_index < num_items);
+
+ WeightedNormalDataAggregateItem *itdt = &items_data[item_index];
+ itdt->curr_strength = FACE_STRENGTH_WEAK;
+
+ MLoopNorSpace *lnor_space = lnors_spacearr.lspacearr[ml_index];
+ lnor_space->user_data = itdt;
+
+ if (!(lnor_space->flags & MLNOR_SPACE_IS_SINGLE)) {
+ for (LinkNode *lnode = lnor_space->loops; lnode; lnode = lnode->next) {
+ const int ml_fan_index = GET_INT_FROM_POINTER(lnode->link);
+ BLI_BITMAP_ENABLE(done_loops, ml_fan_index);
+ }
+ }
+ else {
+ BLI_BITMAP_ENABLE(done_loops, ml_index);
+ }
+
+ item_index++;
+ }
+ }
+
+ MEM_freeN(done_loops);
+ }
+ else {
+ num_items = numVerts;
+ items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__);
+ if (use_face_influence) {
+ for (int item_index = 0; item_index < num_items; item_index++) {
+ items_data[item_index].curr_strength = FACE_STRENGTH_WEAK;
+ }
+ }
+ }
+ wn_data->items_data = items_data;
+
+ switch (mode) {
+ case MOD_WEIGHTEDNORMAL_MODE_FACE:
+ for (int i = 0; i < numPolys; i++) {
+ const int mp_index = mode_pair[i].index;
+ const float mp_val = mode_pair[i].val;
+
+ int ml_index = mpoly[mp_index].loopstart;
+ const int ml_index_end = ml_index + mpoly[mp_index].totloop;
+ for (; ml_index < ml_index_end; ml_index++) {
+ const int mv_index = mloop[ml_index].v;
+ WeightedNormalDataAggregateItem *item_data = keep_sharp ?
+ lnors_spacearr.lspacearr[ml_index]->user_data:
+ &items_data[mv_index];
+
+ aggregate_item_normal(wnmd, wn_data, item_data, mv_index, mp_index, mp_val, use_face_influence);
+ }
+ }
+ break;
+ case MOD_WEIGHTEDNORMAL_MODE_ANGLE:
+ case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE:
+ BLI_assert(loop_to_poly != NULL);
+
+ for (int i = 0; i < numLoops; i++) {
+ const int ml_index = mode_pair[i].index;
+ const float ml_val = mode_pair[i].val;
+
+ const int mp_index = loop_to_poly[ml_index];
+ const int mv_index = mloop[ml_index].v;
+ WeightedNormalDataAggregateItem *item_data = keep_sharp ?
+ lnors_spacearr.lspacearr[ml_index]->user_data:
+ &items_data[mv_index];
+
+ aggregate_item_normal(wnmd, wn_data, item_data, mv_index, mp_index, ml_val, use_face_influence);
+ }
+ break;
+ default:
+ BLI_assert(0);
+ }
+
+ /* Validate computed weighted normals. */
+ for (int item_index = 0; item_index < num_items; item_index++) {
+ if (normalize_v3(items_data[item_index].normal) < CLNORS_VALID_VEC_LEN) {
+ zero_v3(items_data[item_index].normal);
+ }
+ }
+
+ if (keep_sharp) {
+ /* Set loop normals for normal computed for each lnor space (smooth fan).
+ * Note that loop_normals is already populated with clnors (before this modifier is applied, at start of
+ * this function), so no need to recompute them here. */
+ for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ WeightedNormalDataAggregateItem *item_data = lnors_spacearr.lspacearr[ml_index]->user_data;
+ if (!is_zero_v3(item_data->normal)) {
+ copy_v3_v3(loop_normals[ml_index], item_data->normal);
+ }
+ }
+
+ BKE_mesh_normals_loop_custom_set(mvert, numVerts, medge, numEdges,
+ mloop, loop_normals, numLoops, mpoly, polynors, numPolys, clnors);
+ }
+ else {
+ /* TODO: Ideally, we could add an option to BKE_mesh_normals_loop_custom_[from_vertices_]set() to keep current
+ * clnors instead of resetting them to default autocomputed ones, when given new custom normal is zero-vec.
+ * But this is not exactly trivial change, better to keep this optimization for later...
+ */
+ if (!has_vgroup) {
+ /* Note: in theory, we could avoid this extra allocation & copying... But think we can live with it for now,
+ * and it makes code simpler & cleaner. */
+ float (*vert_normals)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*loop_normals), __func__);
+
+ for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ const int mv_index = mloop[ml_index].v;
+ copy_v3_v3(vert_normals[mv_index], items_data[mv_index].normal);
+ }
+
+ BKE_mesh_normals_loop_custom_from_vertices_set(mvert, vert_normals, numVerts, medge, numEdges,
+ mloop, numLoops, mpoly, polynors, numPolys, clnors);
+
+ MEM_freeN(vert_normals);
+ }
+ else {
+ loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__);
+
+ BKE_mesh_normals_loop_split(mvert, numVerts, medge, numEdges,
+ mloop, loop_normals, numLoops, mpoly, polynors, numPolys,
+ true, split_angle, NULL, has_clnors ? clnors : NULL, loop_to_poly);
+
+ for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ const int item_index = mloop[ml_index].v;
+ if (!is_zero_v3(items_data[item_index].normal)) {
+ copy_v3_v3(loop_normals[ml_index], items_data[item_index].normal);
+ }
+ }
+
+ BKE_mesh_normals_loop_custom_set(mvert, numVerts, medge, numEdges,
+ mloop, loop_normals, numLoops, mpoly, polynors, numPolys, clnors);
+ }
+ }
+
+ if (keep_sharp) {
+ BKE_lnor_spacearr_free(&lnors_spacearr);
+ }
+ MEM_SAFE_FREE(loop_normals);
+}
+
+static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
+{
+ const int numPolys = wn_data->numPolys;
+
+ MVert *mvert = wn_data->mvert;
+ MLoop *mloop = wn_data->mloop;
+ MPoly *mpoly = wn_data->mpoly;
+
+ MPoly *mp;
+ int mp_index;
+
+ ModePair *face_area = MEM_malloc_arrayN((size_t)numPolys, sizeof(*face_area), __func__);
+
+ ModePair *f_area = face_area;
+ for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++, f_area++) {
+ f_area->val = BKE_mesh_calc_poly_area(mp, &mloop[mp->loopstart], mvert);
+ f_area->index = mp_index;
+ }
+
+ qsort(face_area, numPolys, sizeof(*face_area), modepair_cmp_by_val_inverse);
+
+ wn_data->mode_pair = face_area;
+ apply_weights_vertex_normal(wnmd, wn_data);
+}
+
+static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
+{
+ const int numLoops = wn_data->numLoops;
+ const int numPolys = wn_data->numPolys;
+
+ MVert *mvert = wn_data->mvert;
+ MLoop *mloop = wn_data->mloop;
+ MPoly *mpoly = wn_data->mpoly;
+
+ MPoly *mp;
+ int mp_index;
+
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+
+ ModePair *corner_angle = MEM_malloc_arrayN((size_t)numLoops, sizeof(*corner_angle), __func__);
+
+ for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) {
+ MLoop *ml_start = &mloop[mp->loopstart];
+
+ float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__);
+ BKE_mesh_calc_poly_angles(mp, ml_start, mvert, index_angle);
+
+ ModePair *c_angl = &corner_angle[mp->loopstart];
+ float *angl = index_angle;
+ for (int ml_index = mp->loopstart; ml_index < mp->loopstart + mp->totloop; ml_index++, c_angl++, angl++) {
+ c_angl->val = (float)M_PI - *angl;
+ c_angl->index = ml_index;
+
+ loop_to_poly[ml_index] = mp_index;
+ }
+ MEM_freeN(index_angle);
+ }
+
+ qsort(corner_angle, numLoops, sizeof(*corner_angle), modepair_cmp_by_val_inverse);
+
+ wn_data->loop_to_poly = loop_to_poly;
+ wn_data->mode_pair = corner_angle;
+ apply_weights_vertex_normal(wnmd, wn_data);
+}
+
+static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
+{
+ const int numLoops = wn_data->numLoops;
+ const int numPolys = wn_data->numPolys;
+
+ MVert *mvert = wn_data->mvert;
+ MLoop *mloop = wn_data->mloop;
+ MPoly *mpoly = wn_data->mpoly;
+
+ MPoly *mp;
+ int mp_index;
+
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+
+ ModePair *combined = MEM_malloc_arrayN((size_t)numLoops, sizeof(*combined), __func__);
+
+ for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) {
+ MLoop *ml_start = &mloop[mp->loopstart];
+
+ float face_area = BKE_mesh_calc_poly_area(mp, ml_start, mvert);
+ float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__);
+ BKE_mesh_calc_poly_angles(mp, ml_start, mvert, index_angle);
+
+ ModePair *cmbnd = &combined[mp->loopstart];
+ float *angl = index_angle;
+ for (int ml_index = mp->loopstart; ml_index < mp->loopstart + mp->totloop; ml_index++, cmbnd++, angl++) {
+ /* In this case val is product of corner angle and face area. */
+ cmbnd->val = ((float)M_PI - *angl) * face_area;
+ cmbnd->index = ml_index;
+
+ loop_to_poly[ml_index] = mp_index;
+ }
+ MEM_freeN(index_angle);
+ }
+
+ qsort(combined, numLoops, sizeof(*combined), modepair_cmp_by_val_inverse);
+
+ wn_data->loop_to_poly = loop_to_poly;
+ wn_data->mode_pair = combined;
+ apply_weights_vertex_normal(wnmd, wn_data);
+}
+
+static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
+{
+ WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md;
+ Object *ob = ctx->object;
+
+ /* XXX TODO ARG GRRR XYQWNMPRXTYY
+ * Once we fully switch to Mesh evaluation of modifiers, we can expect to get that flag from the COW copy.
+ * But for now, it is lost in the DM intermediate step, so we need to directly check orig object's data. */
+#if 0
+ if (!(mesh->flag & ME_AUTOSMOOTH)) {
+#else
+ if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) {
+#endif
+ modifier_setError((ModifierData *)wnmd, "Enable 'Auto Smooth' option in mesh settings");
+ return mesh;
+ }
+
+ Mesh *result;
+ BKE_id_copy_ex(
+ NULL, &mesh->id, (ID **)&result,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+
+ const int numVerts = result->totvert;
+ const int numEdges = result->totedge;
+ const int numLoops = result->totloop;
+ const int numPolys = result->totpoly;
+
+ MEdge *medge = result->medge;
+ MPoly *mpoly = result->mpoly;
+ MVert *mvert = result->mvert;
+ MLoop *mloop = result->mloop;
+
+ /* Right now:
+ * If weight = 50 then all faces are given equal weight.
+ * If weight > 50 then more weight given to faces with larger vals (face area / corner angle).
+ * If weight < 50 then more weight given to faces with lesser vals. However current calculation
+ * does not converge to min/max.
+ */
+ float weight = ((float)wnmd->weight) / 50.0f;
+ if (wnmd->weight == 100) {
+ weight = (float)SHRT_MAX;
+ }
+ else if (wnmd->weight == 1) {
+ weight = 1 / (float)SHRT_MAX;
+ }
+ else if ((weight - 1) * 25 > 1) {
+ weight = (weight - 1) * 25;
+ }
+
+ CustomData *pdata = &result->pdata;
+ float (*polynors)[3] = CustomData_get_layer(pdata, CD_NORMAL);
+ if (!polynors) {
+ polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
+ }
+ BKE_mesh_calc_normals_poly(mvert, NULL, numVerts, mloop, mpoly, numLoops, numPolys, polynors, false);
+
+
+ const float split_angle = mesh->smoothresh;
+ short (*clnors)[2];
+ CustomData *ldata = &result->ldata;
+ clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
+
+ /* Keep info whether we had clnors, it helps when generating clnor spaces and default normals. */
+ const bool has_clnors = clnors != NULL;
+ if (!clnors) {
+ clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numLoops);
+ clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
+ }
+
+ MDeformVert *dvert;
+ int defgrp_index;
+ MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index);
+
+ WeightedNormalData wn_data = {
+ .numVerts = numVerts,
+ .numEdges = numEdges,
+ .numLoops = numLoops,
+ .numPolys = numPolys,
+
+ .mvert = mvert,
+ .medge = medge,
+
+ .mloop = mloop,
+ .clnors = clnors,
+ .has_clnors = has_clnors,
+ .split_angle = split_angle,
+
+ .mpoly = mpoly,
+ .polynors = polynors,
+ .poly_strength = CustomData_get_layer_named(
+ &result->pdata, CD_PROP_INT,
+ MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID),
+
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .use_invert_vgroup = (wnmd->flag & MOD_WEIGHTEDNORMAL_INVERT_VGROUP) != 0,
+
+ .weight = weight,
+ .mode = wnmd->mode,
+ };
+
+ switch (wnmd->mode) {
+ case MOD_WEIGHTEDNORMAL_MODE_FACE:
+ wn_face_area(wnmd, &wn_data);
+ break;
+ case MOD_WEIGHTEDNORMAL_MODE_ANGLE:
+ wn_corner_angle(wnmd, &wn_data);
+ break;
+ case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE:
+ wn_face_with_angle(wnmd, &wn_data);
+ break;
+ }
+
+ MEM_SAFE_FREE(wn_data.loop_to_poly);
+ MEM_SAFE_FREE(wn_data.mode_pair);
+ MEM_SAFE_FREE(wn_data.items_data);
+
+ return result;
+}
+
+static void initData(ModifierData *md)
+{
+ WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md;
+ wnmd->mode = MOD_WEIGHTEDNORMAL_MODE_FACE;
+ wnmd->weight = 50;
+ wnmd->thresh = 1e-2f;
+ wnmd->flag = 0;
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md;
+ CustomDataMask dataMask = CD_CUSTOMLOOPNORMAL;
+
+ if (wnmd->defgrp_name[0]) {
+ dataMask |= CD_MASK_MDEFORMVERT;
+ }
+
+ if (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) {
+ dataMask |= CD_MASK_PROP_INT;
+ }
+
+ return dataMask;
+}
+
+static bool dependsOnNormals(ModifierData *UNUSED(md))
+{
+ return true;
+}
+
+ModifierTypeInfo modifierType_WeightedNormal = {
+ /* name */ "Weighted Normal",
+ /* structName */ "WeightedNormalModifierData",
+ /* structSize */ sizeof(WeightedNormalModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ modifier_copyData_generic,
+
+ /* deformVerts_DM */ NULL,
+ /* deformMatrices_DM */ NULL,
+ /* deformVertsEM_DM */ NULL,
+ /* deformMatricesEM_DM*/NULL,
+ /* applyModifier_DM */ NULL,
+ /* applyModifierEM_DM */NULL,
+
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index a34ed1baaff..47379dec99a 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -203,20 +203,18 @@ static Mesh *applyModifier(
}
}
- Mesh *result = mesh;
-
if (has_mdef) {
- dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, numVerts);
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
}
else {
/* Add a valid data layer! */
- dvert = CustomData_add_layer(&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
+ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
}
/* Ultimate security check. */
if (!dvert) {
- BKE_id_free(NULL, result);
return mesh;
}
+ mesh->dvert = dvert;
/* Get org weights, assuming 0.0 for vertices not in given vgroup. */
org_w = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGEdit Modifier, org_w");
@@ -249,7 +247,7 @@ static Mesh *applyModifier(
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
- weightvg_do_mask(ctx, numVerts, NULL, org_w, new_w, ctx->object, result, wmd->mask_constant,
+ weightvg_do_mask(ctx, numVerts, NULL, org_w, new_w, ctx->object, mesh, wmd->mask_constant,
wmd->mask_defgrp_name, scene, wmd->mask_texture,
wmd->mask_tex_use_channel, wmd->mask_tex_mapping,
wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
@@ -270,7 +268,7 @@ static Mesh *applyModifier(
MEM_freeN(dw);
/* Return the vgroup-modified mesh. */
- return result;
+ return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index b6a7228b171..ea401d01f66 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -243,20 +243,18 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
}
}
- Mesh *result = mesh;
-
if (has_mdef) {
- dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, numVerts);
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
}
else {
/* Add a valid data layer! */
- dvert = CustomData_add_layer(&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
+ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
}
/* Ultimate security check. */
if (!dvert) {
- BKE_id_free(NULL, result);
return mesh;
}
+ mesh->dvert = dvert;
/* Find out which vertices to work on. */
tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGMix Modifier, tidx");
@@ -324,7 +322,6 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
MEM_freeN(tdw1);
MEM_freeN(tdw2);
MEM_freeN(tidx);
- BKE_id_free(NULL, result);
return mesh;
}
if (numIdx != -1) {
@@ -360,7 +357,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
- weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ctx->object, result, wmd->mask_constant,
+ weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ctx->object, mesh, wmd->mask_constant,
wmd->mask_defgrp_name, scene, wmd->mask_texture,
wmd->mask_tex_use_channel, wmd->mask_tex_mapping,
wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
@@ -384,7 +381,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
MEM_SAFE_FREE(indices);
/* Return the vgroup-modified mesh. */
- return result;
+ return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 05b1ec19253..4a5a54642ef 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -422,20 +422,12 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return mesh;
}
- Mesh *result = mesh;
-
- if (has_mdef) {
- dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, numVerts);
- }
- else {
- /* Add a valid data layer! */
- dvert = CustomData_add_layer(&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
- }
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
/* Ultimate security check. */
if (!dvert) {
- BKE_id_free(NULL, result);
return mesh;
}
+ mesh->dvert = dvert;
/* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */
tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGProximity Modifier, tidx");
@@ -454,7 +446,6 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
MEM_freeN(tidx);
MEM_freeN(tw);
MEM_freeN(tdw);
- BKE_id_free(NULL, result);
return mesh;
}
if (numIdx != numVerts) {
@@ -476,7 +467,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
/* Get our vertex coordinates. */
if (numIdx != numVerts) {
- float (*tv_cos)[3] = BKE_mesh_vertexCos_get(result, NULL);
+ float (*tv_cos)[3] = BKE_mesh_vertexCos_get(mesh, NULL);
v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
for (i = 0; i < numIdx; i++) {
copy_v3_v3(v_cos[i], tv_cos[indices[i]]);
@@ -484,7 +475,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
MEM_freeN(tv_cos);
}
else {
- v_cos = BKE_mesh_vertexCos_get(result, NULL);
+ v_cos = BKE_mesh_vertexCos_get(mesh, NULL);
}
/* Compute wanted distances. */
@@ -544,7 +535,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
- weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ob, result, wmd->mask_constant,
+ weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ob, mesh, wmd->mask_constant,
wmd->mask_defgrp_name, scene, wmd->mask_texture,
wmd->mask_tex_use_channel, wmd->mask_tex_mapping,
wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
@@ -570,7 +561,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
#endif
/* Return the vgroup-modified mesh. */
- return result;
+ return mesh;
}
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 67c86180188..8df114afa24 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SRC
composite/nodes/node_composite_composite.c
composite/nodes/node_composite_cornerpin.c
composite/nodes/node_composite_crop.c
+ composite/nodes/node_composite_cryptomatte.c
composite/nodes/node_composite_curves.c
composite/nodes/node_composite_despeckle.c
composite/nodes/node_composite_doubleEdgeMask.c
@@ -168,6 +169,7 @@ set(SRC
shader/nodes/node_shader_bsdf_transparent.c
shader/nodes/node_shader_bsdf_velvet.c
shader/nodes/node_shader_bsdf_hair.c
+ shader/nodes/node_shader_bsdf_hair_principled.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_emission.c
shader/nodes/node_shader_fresnel.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index dfcb83b873a..a728d1e228d 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -109,6 +109,7 @@ void register_node_type_cmp_luma_matte(void);
void register_node_type_cmp_doubleedgemask(void);
void register_node_type_cmp_keyingscreen(void);
void register_node_type_cmp_keying(void);
+void register_node_type_cmp_cryptomatte(void);
void register_node_type_cmp_translate(void);
void register_node_type_cmp_rotate(void);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 83a5f5c5bf1..2f466b0296c 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -111,6 +111,7 @@ void register_node_type_sh_volume_absorption(void);
void register_node_type_sh_volume_scatter(void);
void register_node_type_sh_volume_principled(void);
void register_node_type_sh_bsdf_hair(void);
+void register_node_type_sh_bsdf_hair_principled(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
void register_node_type_sh_add_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index cf974132961..22c2afcc466 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -85,6 +85,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BS
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TOON, def_toon, "BSDF_TOON", BsdfToon, "Toon BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BSDF_HAIR", BsdfHair, "Hair BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_HAIR_PRINCIPLED, def_hair_principled, "BSDF_HAIR_PRINCIPLED", BsdfHairPrincipled, "Principled Hair BSDF", "")
DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" )
DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" )
@@ -215,6 +216,7 @@ DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXEL
DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" )
DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" )
+DefNode( CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTOMATTE", Cryptomatte, "Cryptomatte", "" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c
new file mode 100644
index 00000000000..af988c0df39
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c
@@ -0,0 +1,302 @@
+/*
+ * ***** 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) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Stockner, Stefan Werner
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_cryptomatte.c
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+#include "BLI_assert.h"
+#include "BLI_dynstr.h"
+#include "BLI_hash_mm3.h"
+#include "BLI_utildefines.h"
+
+/* this is taken from the cryptomatte specification 1.0 */
+
+BLI_INLINE float hash_to_float(uint32_t hash)
+{
+ uint32_t mantissa = hash & ((1 << 23) - 1);
+ uint32_t exponent = (hash >> 23) & ((1 << 8) - 1);
+ exponent = MAX2(exponent, (uint32_t)1);
+ exponent = MIN2(exponent, (uint32_t)254);
+ exponent = exponent << 23;
+ uint32_t sign = (hash >> 31);
+ sign = sign << 31;
+ uint32_t float_bits = sign | exponent | mantissa;
+ float f;
+ /* Bit casting relies on equal size for both types. */
+ BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size")
+ memcpy(&f, &float_bits, sizeof(float));
+ return f;
+}
+
+static void cryptomatte_add(NodeCryptomatte *n, float f)
+{
+ /* Turn the number into a string. */
+ char number[32];
+ BLI_snprintf(number, sizeof(number), "<%.9g>", f);
+
+ /* Search if we already have the number. */
+ if (n->matte_id && strlen(n->matte_id) != 0) {
+ size_t start = 0;
+ const size_t end = strlen(n->matte_id);
+ size_t token_len = 0;
+ while (start < end) {
+ /* Ignore leading whitespace. */
+ while (start < end && n->matte_id[start] == ' ') {
+ ++start;
+ }
+
+ /* Find the next seprator. */
+ char *token_end = strchr(n->matte_id + start, ',');
+ if (token_end == NULL || token_end == n->matte_id + start) {
+ token_end = n->matte_id + end;
+ }
+ /* Be aware that token_len still contains any trailing white space. */
+ token_len = token_end - (n->matte_id + start);
+
+ /* If this has a leading bracket, assume a raw floating point number and look for the closing bracket. */
+ if (n->matte_id[start] == '<') {
+ if (strncmp(n->matte_id + start, number, strlen(number)) == 0) {
+ /* This number is already there, so continue. */
+ return;
+ }
+ }
+ else {
+ /* Remove trailing white space */
+ size_t name_len = token_len;
+ while (n->matte_id[start + name_len] == ' ' && name_len > 0) {
+ name_len--;
+ }
+ /* Calculate the hash of the token and compare. */
+ uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0);
+ if (f == hash_to_float(hash)) {
+ return;
+ }
+ }
+ start += token_len + 1;
+ }
+ }
+
+ DynStr *new_matte = BLI_dynstr_new();
+ if (!new_matte) {
+ return;
+ }
+
+ if (n->matte_id) {
+ BLI_dynstr_append(new_matte, n->matte_id);
+ MEM_freeN(n->matte_id);
+ }
+
+ if (BLI_dynstr_get_len(new_matte) > 0) {
+ BLI_dynstr_append(new_matte, ",");
+ }
+ BLI_dynstr_append(new_matte, number);
+ n->matte_id = BLI_dynstr_get_cstring(new_matte);
+ BLI_dynstr_free(new_matte);
+}
+
+static void cryptomatte_remove(NodeCryptomatte *n, float f)
+{
+ if (n->matte_id == NULL || strlen(n->matte_id) == 0) {
+ /* Empty string, nothing to remove. */
+ return;
+ }
+
+ /* This will be the new string without the removed key. */
+ DynStr *new_matte = BLI_dynstr_new();
+ if (!new_matte) {
+ return;
+ }
+
+ /* Turn the number into a string. */
+ static char number[32];
+ BLI_snprintf(number, sizeof(number), "<%.9g>", f);
+
+ /* Search if we already have the number. */
+ size_t start = 0;
+ const size_t end = strlen(n->matte_id);
+ size_t token_len = 0;
+ bool is_first = true;
+ while (start < end) {
+ bool skip = false;
+ /* Ignore leading whitespace or commas. */
+ while (start < end && ((n->matte_id[start] == ' ') || (n->matte_id[start] == ','))) {
+ ++start;
+ }
+
+ /* Find the next seprator. */
+ char *token_end = strchr(n->matte_id + start + 1, ',');
+ if (token_end == NULL || token_end == n->matte_id + start) {
+ token_end = n->matte_id + end;
+ }
+ /* Be aware that token_len still contains any trailing white space. */
+ token_len = token_end - (n->matte_id + start);
+
+ if (token_len == 1) {
+ skip = true;
+ }
+ /* If this has a leading bracket, assume a raw floating point number and look for the closing bracket. */
+ else if (n->matte_id[start] == '<') {
+ if (strncmp(n->matte_id + start, number, strlen(number)) == 0) {
+ /* This number is already there, so skip it. */
+ skip = true;
+ }
+ }
+ else {
+ /* Remove trailing white space */
+ size_t name_len = token_len;
+ while (n->matte_id[start + name_len] == ' ' && name_len > 0) {
+ name_len--;
+ }
+ /* Calculate the hash of the token and compare. */
+ uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0);
+ if (f == hash_to_float(hash)) {
+ skip = true;
+ }
+ }
+ if (!skip) {
+ if (is_first) {
+ is_first = false;
+ }
+ else {
+ BLI_dynstr_append(new_matte, ", ");
+ }
+ BLI_dynstr_nappend(new_matte, n->matte_id + start, token_len);
+ }
+ start += token_len + 1;
+ }
+
+ if (n->matte_id) {
+ MEM_freeN(n->matte_id);
+ n->matte_id = NULL;
+ }
+ if (BLI_dynstr_get_len(new_matte) > 0) {
+ n->matte_id = BLI_dynstr_get_cstring(new_matte);
+ }
+ BLI_dynstr_free(new_matte);
+}
+
+static bNodeSocketTemplate outputs[] = {
+ { SOCK_RGBA, 0, N_("Image")},
+ { SOCK_FLOAT, 0, N_("Matte")},
+ { SOCK_RGBA, 0, N_("Pick")},
+ { -1, 0, "" }
+};
+
+void ntreeCompositCryptomatteSyncFromAdd(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeCryptomatte *n = node->storage;
+ if (n->add[0] != 0.0f) {
+ cryptomatte_add(n, n->add[0]);
+ n->add[0] = 0.0f;
+ n->add[1] = 0.0f;
+ n->add[2] = 0.0f;
+ }
+}
+
+void ntreeCompositCryptomatteSyncFromRemove(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeCryptomatte *n = node->storage;
+ if (n->remove[0] != 0.0f) {
+ cryptomatte_remove(n, n->remove[0]);
+ n->remove[0] = 0.0f;
+ n->remove[1] = 0.0f;
+ n->remove[2] = 0.0f;
+ }
+}
+
+bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node)
+{
+ NodeCryptomatte *n = node->storage;
+ char sockname[32];
+ n->num_inputs++;
+ BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs - 1);
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, sockname);
+ return sock;
+}
+
+int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
+{
+ NodeCryptomatte *n = node->storage;
+ if (n->num_inputs < 2) {
+ return 0;
+ }
+ bNodeSocket *sock = node->inputs.last;
+ nodeRemoveSocket(ntree, node, sock);
+ n->num_inputs--;
+ return 1;
+}
+
+static void init(bNodeTree *ntree, bNode *node)
+{
+ NodeCryptomatte *user = MEM_callocN(sizeof(NodeCryptomatte), "cryptomatte user");
+ node->storage = user;
+
+
+ nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "image", "Image");
+
+ /* Add three inputs by default, as recommended by the Cryptomatte specification. */
+ ntreeCompositCryptomatteAddSocket(ntree, node);
+ ntreeCompositCryptomatteAddSocket(ntree, node);
+ ntreeCompositCryptomatteAddSocket(ntree, node);
+}
+
+static void node_free_cryptomatte(bNode *node)
+{
+ NodeCryptomatte *nc = node->storage;
+
+ if (nc) {
+ if (nc->matte_id) {
+ MEM_freeN(nc->matte_id);
+ }
+
+ MEM_freeN(nc);
+ }
+}
+
+static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
+{
+ NodeCryptomatte *src_nc = src_node->storage;
+ NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc);
+
+ if (src_nc->matte_id)
+ dest_nc->matte_id = MEM_dupallocN(src_nc->matte_id);
+
+ dest_node->storage = dest_nc;
+}
+
+void register_node_type_cmp_cryptomatte(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_CRYPTOMATTE, "Cryptomatte", NODE_CLASS_CONVERTOR, 0);
+ node_type_socket_templates(&ntype, NULL, outputs);
+ node_type_init(&ntype, init);
+ node_type_storage(&ntype, "NodeCryptomatte", node_free_cryptomatte, node_copy_cryptomatte);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 919af171756..6f2c7835a3c 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -583,10 +583,9 @@ static void ntree_shader_tag_sss_node(bNodeTree *ntree, bNode *output_node)
nodeChainIter(ntree, output_node, ntree_tag_sss_bsdf_cb, &sss_id, true);
}
-void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, bool *has_surface_output, bool *has_volume_output)
+/* This one needs to work on a local tree. */
+void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat, bool *has_surface_output, bool *has_volume_output)
{
- /* localize tree to create links for reroute and mute */
- bNodeTree *localtree = ntreeLocalize(ntree);
bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
bNodeTreeExec *exec;
@@ -618,9 +617,6 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, bool *has_surface
*has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0);
}
}
-
- ntreeFreeTree(localtree);
- MEM_freeN(localtree);
}
bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 9190f0d53cd..63c1cac566d 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -253,13 +253,18 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in
float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0;
if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) {
- GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
- GPUNodeLink *tmin = GPU_uniform(texmap->min);
- GPUNodeLink *tmax = GPU_uniform(texmap->max);
- GPUNodeLink *tdomin = GPU_uniform(&domin);
- GPUNodeLink *tdomax = GPU_uniform(&domax);
-
- GPU_link(mat, "mapping", in[0].link, tmat, tmin, tmax, tdomin, tdomax, &in[0].link);
+ static float max[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
+ static float min[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+ GPUNodeLink *tmin, *tmax, *tmat0, *tmat1, *tmat2, *tmat3;
+
+ tmin = GPU_uniform_buffer((domin) ? texmap->min : min, GPU_VEC3);
+ tmax = GPU_uniform_buffer((domax) ? texmap->max : max, GPU_VEC3);
+ tmat0 = GPU_uniform_buffer((float *)texmap->mat[0], GPU_VEC4);
+ tmat1 = GPU_uniform_buffer((float *)texmap->mat[1], GPU_VEC4);
+ tmat2 = GPU_uniform_buffer((float *)texmap->mat[2], GPU_VEC4);
+ tmat3 = GPU_uniform_buffer((float *)texmap->mat[3], GPU_VEC4);
+
+ GPU_link(mat, "mapping", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link);
if (texmap->type == TEXMAP_TYPE_NORMAL)
GPU_link(mat, "texco_norm", in[0].link, &in[0].link);
diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
index 76291df41bc..e57f5e0d6cf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c
+++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.c
@@ -40,12 +40,15 @@ static bNodeSocketTemplate sh_node_blackbody_out[] = {
static int node_shader_gpu_blackbody(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- const int size = 256;
+ const int size = CM_TABLE + 1;
float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f);
- return GPU_stack_link(mat, node, "node_blackbody", in, out, GPU_texture(size, data));
+ float layer;
+ GPUNodeLink *ramp_texture = GPU_texture_ramp(mat, size, data, &layer);
+
+ return GPU_stack_link(mat, node, "node_blackbody", in, out, ramp_texture, GPU_uniform(&layer));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
index c1423867d96..6551b20a375 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -54,6 +54,8 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *node, bNode
if (!in[4].link)
GPU_link(mat, "world_normals_get", &in[4].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY);
+
return GPU_stack_link(mat, node, "node_bsdf_anisotropic", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
index 58a37b0e81d..c1b8c748657 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
@@ -46,6 +46,8 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *node, bNodeExec
if (!in[2].link)
GPU_link(mat, "world_normals_get", &in[2].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE);
+
return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 7b060bc68aa..ada6e21356f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -52,6 +52,8 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *node, bNodeExecDa
if (!in[3].link)
GPU_link(mat, "world_normals_get", &in[3].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT);
+
return GPU_stack_link(mat, node, "node_bsdf_glass", in, out, GPU_uniform(&node->ssr_id));
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
index c3fb43c0ce8..f56837de261 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
@@ -51,6 +51,8 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *node, bNodeExecD
if (!in[2].link)
GPU_link(mat, "world_normals_get", &in[2].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY);
+
return GPU_stack_link(mat, node, "node_bsdf_glossy", in, out, GPU_uniform(&node->ssr_id));
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
new file mode 100644
index 00000000000..83e4bf1731b
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
@@ -0,0 +1,132 @@
+/*
+ * ***** 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) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Stockner, L. E. Segovia
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+/* Color, melanin and absorption coefficient default to approximately same brownish hair. */
+static bNodeSocketTemplate sh_node_bsdf_hair_principled_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.017513f, 0.005763f, 0.002059f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Melanin"), 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Melanin Redness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 1, N_("Absorption Coefficient"), 0.245531f, 0.52f, 1.365f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Radial Roughness"), 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("IOR"), 1.55f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 1, N_("Offset"), 2.0f * ((float)M_PI) / 180.f, 0.0f, 0.0f, 0.0f, -M_PI_2, M_PI_2, PROP_ANGLE},
+ { SOCK_FLOAT, 1, N_("Random Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Random Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" },
+};
+
+static bNodeSocketTemplate sh_node_bsdf_hair_principled_out[] = {
+ { SOCK_SHADER, 0, N_("BSDF")},
+ { -1, 0, "" }
+};
+
+/* Initialize the custom Parametrization property to Color. */
+static void node_shader_init_hair_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = SHD_PRINCIPLED_HAIR_REFLECTANCE;
+}
+
+/* Triggers (in)visibility of some sockets when changing Parametrization. */
+static void node_shader_update_hair_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ int parametrization = node->custom1;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Color")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ else if (STREQ(sock->name, "Melanin")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ else if (STREQ(sock->name, "Melanin Redness")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ else if (STREQ(sock->name, "Tint")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ else if (STREQ(sock->name, "Absorption Coefficient")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ else if (STREQ(sock->name, "Random Color")) {
+ if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ }
+}
+
+/* node type definition */
+void register_node_type_sh_bsdf_hair_principled(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_BSDF_HAIR_PRINCIPLED, "Principled Hair BSDF", NODE_CLASS_SHADER, 0);
+ node_type_socket_templates(&ntype, sh_node_bsdf_hair_principled_in, sh_node_bsdf_hair_principled_out);
+ node_type_size_preset(&ntype, NODE_SIZE_LARGE);
+ node_type_init(&ntype, node_shader_init_hair_principled);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_update(&ntype, node_shader_update_hair_principled, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index 7f02295d45f..370dcdcc2ea 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -64,22 +64,12 @@ static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
node->custom2 = SHD_SUBSURFACE_BURLEY;
}
+#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f))
+#define socket_not_one(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) < 1.0f - 1e-5f))
+
static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *sss_scale;
-#if 0 /* Old 2.7 glsl viewport */
- // normal
- if (!in[17].link)
- in[17].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link);
-
- // clearcoat normal
- if (!in[18].link)
- in[18].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link);
-#endif
/* Normals */
if (!in[17].link) {
@@ -117,7 +107,48 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *node, bNodeE
GPU_link(mat, "set_rgb", GPU_uniform((float *)one), &sss_scale);
}
- return GPU_stack_link(mat, node, "node_bsdf_principled_clearcoat", in, out, GPU_builtin(GPU_VIEW_POSITION),
+ bool use_diffuse = socket_not_one(4) && socket_not_one(15);
+ bool use_subsurf = socket_not_zero(1) && use_diffuse;
+ bool use_refract = socket_not_one(4) && socket_not_zero(15);
+ bool use_clear = socket_not_zero(12);
+
+ /* Due to the manual effort done per config, we only optimize the most common permutations. */
+ char *node_name;
+ uint flag = 0;
+ if (!use_subsurf && use_diffuse && !use_refract && !use_clear) {
+ static char name[] = "node_bsdf_principled_dielectric";
+ node_name = name;
+ flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY;
+ }
+ else if (!use_subsurf && !use_diffuse && !use_refract && !use_clear) {
+ static char name[] = "node_bsdf_principled_metallic";
+ node_name = name;
+ flag = GPU_MATFLAG_GLOSSY;
+ }
+ else if (!use_subsurf && !use_diffuse && !use_refract && use_clear) {
+ static char name[] = "node_bsdf_principled_clearcoat";
+ node_name = name;
+ flag = GPU_MATFLAG_GLOSSY;
+ }
+ else if (use_subsurf && use_diffuse && !use_refract && !use_clear) {
+ static char name[] = "node_bsdf_principled_subsurface";
+ node_name = name;
+ flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS | GPU_MATFLAG_GLOSSY;
+ }
+ else if (!use_subsurf && !use_diffuse && use_refract && !use_clear && !socket_not_zero(4)) {
+ static char name[] = "node_bsdf_principled_glass";
+ node_name = name;
+ flag = GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT;
+ }
+ else {
+ static char name[] = "node_bsdf_principled";
+ node_name = name;
+ flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY | GPU_MATFLAG_SSS | GPU_MATFLAG_REFRACT;
+ }
+
+ GPU_material_flag_set(mat, flag);
+
+ return GPU_stack_link(mat, node, node_name, in, out, GPU_builtin(GPU_VIEW_POSITION),
GPU_uniform(&node->ssr_id), GPU_uniform(&node->sss_id), sss_scale);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
index 41dd3f8af3c..b59f1c80342 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
@@ -52,6 +52,8 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *node, bNodeE
if (!in[3].link)
GPU_link(mat, "world_normals_get", &in[3].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_REFRACT);
+
return GPU_stack_link(mat, node, "node_bsdf_refraction", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
index 2c0949f275c..349db30af14 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
@@ -45,6 +45,8 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *node, bNode
if (!in[1].link)
GPU_link(mat, "world_normals_get", &in[1].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE);
+
return GPU_stack_link(mat, node, "node_bsdf_translucent", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
index ce331f03d4e..59b831c0dab 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
@@ -46,6 +46,8 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *node, bNodeExecD
if (!in[2].link)
GPU_link(mat, "world_normals_get", &in[2].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE);
+
return GPU_stack_link(mat, node, "node_bsdf_velvet", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c
index d5932ff233a..21bdc3cd0d8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_curves.c
+++ b/source/blender/nodes/shader/nodes/node_shader_curves.c
@@ -62,11 +62,13 @@ static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- float *array;
+ float *array, layer;
int size;
curvemapping_table_RGBA(node->storage, &array, &size);
- return GPU_stack_link(mat, node, "curves_vec", in, out, GPU_texture(size, array));
+ GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer);
+
+ return GPU_stack_link(mat, node, "curves_vec", in, out, tex, GPU_uniform(&layer));
}
void register_node_type_sh_curve_vec(void)
@@ -119,12 +121,14 @@ static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- float *array;
+ float *array, layer;
int size;
curvemapping_initialize(node->storage);
curvemapping_table_RGBA(node->storage, &array, &size);
- return GPU_stack_link(mat, node, "curves_rgb", in, out, GPU_texture(size, array));
+ GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer);
+
+ return GPU_stack_link(mat, node, "curves_rgb", in, out, tex, GPU_uniform(&layer));
}
void register_node_type_sh_curve_rgb(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c
index e05b0be1e62..6583dd0cec3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c
+++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c
@@ -67,6 +67,8 @@ static int node_shader_gpu_eevee_specular(GPUMaterial *mat, bNode *node, bNodeEx
GPU_link(mat, "set_value", GPU_uniform(&one), &in[9].link);
}
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY);
+
return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_uniform(&node->ssr_id));
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index a84e88e9551..98dcd58b983 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -88,13 +88,18 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
TexMapping *texmap = node->storage;
float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0;
float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0;
- GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
- GPUNodeLink *tmin = GPU_uniform(texmap->min);
- GPUNodeLink *tmax = GPU_uniform(texmap->max);
- GPUNodeLink *tdomin = GPU_uniform(&domin);
- GPUNodeLink *tdomax = GPU_uniform(&domax);
-
- GPU_stack_link(mat, node, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
+ static float max[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
+ static float min[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+ GPUNodeLink *tmin, *tmax, *tmat0, *tmat1, *tmat2, *tmat3;
+
+ tmin = GPU_uniform_buffer((domin) ? texmap->min : min, GPU_VEC3);
+ tmax = GPU_uniform_buffer((domax) ? texmap->max : max, GPU_VEC3);
+ tmat0 = GPU_uniform_buffer((float *)texmap->mat[0], GPU_VEC4);
+ tmat1 = GPU_uniform_buffer((float *)texmap->mat[1], GPU_VEC4);
+ tmat2 = GPU_uniform_buffer((float *)texmap->mat[2], GPU_VEC4);
+ tmat3 = GPU_uniform_buffer((float *)texmap->mat[3], GPU_VEC4);
+
+ GPU_stack_link(mat, node, "mapping", in, out, tmat0, tmat1, tmat2, tmat3, tmin, tmax);
if (texmap->type == TEXMAP_TYPE_NORMAL)
GPU_link(mat, "texco_norm", out[0].link, &out[0].link);
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 3c0fb145987..e4b5aaef72d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -63,11 +63,21 @@ static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *U
if (in[0].link)
strength = in[0].link;
+ else if (node->original) {
+ bNodeSocket *socket = BLI_findlink(&node->original->inputs, 0);
+ bNodeSocketValueFloat *socket_data = socket->default_value;
+ strength = GPU_uniform_buffer(&socket_data->value, GPU_FLOAT);
+ }
else
strength = GPU_uniform(in[0].vec);
if (in[1].link)
realnorm = in[1].link;
+ else if (node->original) {
+ bNodeSocket *socket = BLI_findlink(&node->original->inputs, 1);
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ realnorm = GPU_uniform_buffer(socket_data->value, GPU_VEC3);
+ }
else
realnorm = GPU_uniform(in[1].vec);
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
index 57fb9026595..f8af125eb9e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -54,6 +54,8 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *node,
if (!in[5].link)
GPU_link(mat, "world_normals_get", &in[5].link);
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS);
+
if (node->sss_id == 1) {
bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2);
bNodeSocketValueRGBA *socket_data = socket->default_value;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 2bbe3617bee..9782df2638f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -55,11 +55,28 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
+ static const char *names[] = {
+ "node_tex_image_linear",
+ "node_tex_image_nearest",
+ "node_tex_image_cubic",
+ "node_tex_image_smart"
+ };
+ static const char *names_box[] = {
+ "tex_box_sample_linear",
+ "tex_box_sample_nearest",
+ "tex_box_sample_cubic",
+ "tex_box_sample_smart"
+ };
+
Image *ima = (Image *)node->id;
ImageUser *iuser = NULL;
NodeTexImage *tex = node->storage;
+ const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX)
+ ? names_box[tex->interpolation]
+ : names[tex->interpolation];
+ bool do_color_correction = false;
- GPUNodeLink *norm;
+ GPUNodeLink *norm, *col1, *col2, *col3;
int isdata = tex->color_space == SHD_COLORSPACE_NONE;
float blend = tex->projection_blend;
@@ -67,6 +84,15 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
if (!ima)
return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ if ((tex->color_space == SHD_COLORSPACE_COLOR) &&
+ ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
+ GPU_material_do_color_management(mat))
+ {
+ do_color_correction = true;
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
if (!in[0].link)
in[0].link = GPU_attribute(CD_MTFACE, "");
@@ -74,7 +100,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
switch (tex->projection) {
case SHD_PROJ_FLAT:
- GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
break;
case SHD_PROJ_BOX:
GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
@@ -83,8 +109,20 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
GPU_link(mat, "direction_transform_m4v3", norm,
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
&norm);
+ GPU_link(mat, gpu_node_name, in[0].link,
+ norm,
+ GPU_image(ima, iuser, isdata),
+ &col1,
+ &col2,
+ &col3);
+ if (do_color_correction) {
+ GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
+ GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
+ GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
+ }
GPU_link(mat, "node_tex_image_box", in[0].link,
norm,
+ col1, col2, col3,
GPU_image(ima, iuser, isdata),
GPU_uniform(&blend),
&out[0].link,
@@ -93,23 +131,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
case SHD_PROJ_SPHERE:
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
- GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
break;
case SHD_PROJ_TUBE:
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
- GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
break;
}
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if ((tex->color_space == SHD_COLORSPACE_COLOR) &&
- ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
- GPU_material_do_color_management(mat))
- {
+ if (do_color_correction && (tex->projection != SHD_PROJ_BOX)) {
GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
}
- BKE_image_release_ibuf(ima, ibuf, NULL);
return true;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index b6581cb18cb..5f583e1e29b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -65,11 +65,19 @@ static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node)
static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- float *array;
+ struct ColorBand *coba = node->storage;
+ float *array, layer;
int size;
- BKE_colorband_evaluate_table_rgba(node->storage, &array, &size);
- return GPU_stack_link(mat, node, "valtorgb", in, out, GPU_texture(size, array));
+ BKE_colorband_evaluate_table_rgba(coba, &array, &size);
+ GPUNodeLink *tex = GPU_texture_ramp(mat, size, array, &layer);
+
+ if (coba->ipotype == COLBAND_INTERP_CONSTANT) {
+ return GPU_stack_link(mat, node, "valtorgb_nearest", in, out, tex, GPU_uniform(&layer));
+ }
+ else {
+ return GPU_stack_link(mat, node, "valtorgb", in, out, tex, GPU_uniform(&layer));
+ }
}
void register_node_type_sh_valtorgb(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
index a88a7ebb21a..c946c42f9af 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
@@ -132,19 +132,19 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, bNode *node, bNod
}
/* Create blackbody spectrum. */
- GPUNodeLink *spectrummap;
+ const int size = CM_TABLE + 1;
+ float *data, layer;
if (use_blackbody) {
- const int size = 256;
- float *data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
+ data = MEM_mallocN(sizeof(float) * size * 4, "blackbody texture");
blackbody_temperature_to_rgb_table(data, size, 965.0f, 12000.0f);
- spectrummap = GPU_texture(size, data);
}
else {
- float *data = MEM_callocN(sizeof(float) * 4, "blackbody black");
- spectrummap = GPU_texture(1, data);
+ data = MEM_callocN(sizeof(float) * size * 4, "blackbody black");
}
+ GPUNodeLink *spectrummap = GPU_texture_ramp(mat, size, data, &layer);
- return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap);
+ return GPU_stack_link(mat, node, "node_volume_principled", in, out, density, color, temperature, spectrummap,
+ GPU_uniform(&layer));
}
/* node type definition */
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index 8d26fee0abd..030576fefd1 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -17,7 +17,7 @@
# ***** END GPL LICENSE BLOCK *****
add_subdirectory(intern)
-add_subdirectory(gawain)
add_subdirectory(generic)
+add_subdirectory(gpu)
add_subdirectory(mathutils)
add_subdirectory(bmesh)
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 4e55495a0cd..62981798b1a 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -192,7 +192,7 @@ static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void
}
PyDoc_STRVAR(bpy_bmvertskin_flag__use_root_doc,
-"Use as root vertex.\n\n:type: boolean"
+"Use as root vertex. Setting this flag does not clear other roots in the same mesh island.\n\n:type: boolean"
);
PyDoc_STRVAR(bpy_bmvertskin_flag__use_loose_doc,
"Use loose vertex.\n\n:type: boolean"
@@ -221,17 +221,16 @@ static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *
}
}
-/* XXX Todo: Make root settable, currently the code to disable all other verts as roots sits within the modifier */
static PyGetSetDef bpy_bmvertskin_getseters[] = {
/* attributes match rna_mesh_gen */
{(char *)"radius", (getter)bpy_bmvertskin_radius_get, (setter)bpy_bmvertskin_radius_set, (char *)bpy_bmvertskin_radius_doc, NULL},
- {(char *)"use_root", (getter)bpy_bmvertskin_flag_get, (setter)NULL, (char *)bpy_bmvertskin_flag__use_root_doc, (void *)MVERT_SKIN_ROOT},
+ {(char *)"use_root", (getter)bpy_bmvertskin_flag_get, (setter)bpy_bmvertskin_flag_set, (char *)bpy_bmvertskin_flag__use_root_doc, (void *)MVERT_SKIN_ROOT},
{(char *)"use_loose", (getter)bpy_bmvertskin_flag_get, (setter)bpy_bmvertskin_flag_set, (char *)bpy_bmvertskin_flag__use_loose_doc, (void *)MVERT_SKIN_LOOSE},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
-static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.uv.active */
+static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.skin.active */
static void bm_init_types_bmvertskin(void)
{
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index d0f708b7e3c..71812466477 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -500,6 +500,7 @@ PyObject *BPyInit_blf(void)
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
+ PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
return submodule;
}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 4b56d4412e6..4d4d5232800 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -596,15 +596,15 @@ static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob)
return prop;
}
-static IDProperty *idp_from_DatablockPointer(const char *name, PyObject *ob, IDPropertyTemplate *val)
+static IDProperty *idp_from_DatablockPointer(const char *name, PyObject *ob)
{
- pyrna_id_FromPyObject(ob, &val->id);
- return IDP_New(IDP_ID, val, name);
+ IDPropertyTemplate val = {0};
+ pyrna_id_FromPyObject(ob, &val.id);
+ return IDP_New(IDP_ID, &val, name);
}
static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob)
{
- IDPropertyTemplate val = {0};
const char *name = idp_try_read_name(name_obj);
if (name == NULL) {
return NULL;
@@ -626,7 +626,7 @@ static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob)
return idp_from_PySequence(name, ob);
}
else if (ob == Py_None || pyrna_id_CheckPyObject(ob)) {
- return idp_from_DatablockPointer(name, ob, &val);
+ return idp_from_DatablockPointer(name, ob);
}
else if (PyMapping_Check(ob)) {
return idp_from_PyMapping(name, ob);
diff --git a/source/blender/python/generic/imbuf_py_api.h b/source/blender/python/generic/imbuf_py_api.h
index 92c1732a9c9..35adc541bfc 100644
--- a/source/blender/python/generic/imbuf_py_api.h
+++ b/source/blender/python/generic/imbuf_py_api.h
@@ -27,4 +27,6 @@
PyObject *BPyInit_imbuf(void);
+extern PyTypeObject Py_ImBuf_Type;
+
#endif /* __IMBUF_PY_API_H__ */
diff --git a/source/blender/python/gawain/CMakeLists.txt b/source/blender/python/gpu/CMakeLists.txt
index 9eab323a0fe..141a36bbcc2 100644
--- a/source/blender/python/gawain/CMakeLists.txt
+++ b/source/blender/python/gpu/CMakeLists.txt
@@ -24,7 +24,6 @@ set(INC
../../blenlib
../../gpu
../../makesdna
- ../../../../intern/gawain
../../../../intern/guardedalloc
../../../../intern/glew-mx
)
@@ -35,13 +34,13 @@ set(INC_SYS
)
set(SRC
- gwn_py_api.c
- gwn_py_types.c
+ gpu_py_api.c
+ gpu_py_types.c
- gwn_py_api.h
- gwn_py_types.h
+ gpu_py_api.h
+ gpu_py_types.h
)
add_definitions(${GL_DEFINITIONS})
-blender_add_lib(bf_python_gawain "${SRC}" "${INC}" "${INC_SYS}")
+blender_add_lib(bf_python_gpu "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/gawain/gwn_py_api.c b/source/blender/python/gpu/gpu_py_api.c
index d79ef070649..53285b372d8 100644
--- a/source/blender/python/gawain/gwn_py_api.c
+++ b/source/blender/python/gpu/gpu_py_api.c
@@ -18,44 +18,44 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/python/gawain/gwn_py_api.c
- * \ingroup pygawain
+/** \file blender/python/gpu/gpu_py_api.c
+ * \ingroup pygpu
*
- * Experimental Python API, not considered public yet (called '_gawain'),
+ * Experimental Python API, not considered public yet (called '_gpu'),
* we may re-expose as public later.
*/
#include <Python.h>
-#include "gawain/gwn_batch.h"
-#include "gawain/gwn_vertex_format.h"
+#include "GPU_batch.h"
+#include "GPU_vertex_format.h"
-#include "gwn_py_api.h"
-#include "gwn_py_types.h"
+#include "gpu_py_api.h"
+#include "gpu_py_types.h"
#include "BLI_utildefines.h"
#include "../generic/python_utildefines.h"
-PyDoc_STRVAR(GWN_doc,
-"This module provides access to gawain drawing functions."
+PyDoc_STRVAR(GPU_doc,
+"This module provides access to gpu drawing functions."
);
-static struct PyModuleDef GWN_module_def = {
+static struct PyModuleDef GPU_module_def = {
PyModuleDef_HEAD_INIT,
- .m_name = "_gawain", /* m_name */
- .m_doc = GWN_doc, /* m_doc */
+ .m_name = "_gpu", /* m_name */
+ .m_doc = GPU_doc, /* m_doc */
};
-PyObject *BPyInit_gawain(void)
+PyObject *BPyInit_gpu(void)
{
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
PyObject *submodule;
PyObject *mod;
- mod = PyModule_Create(&GWN_module_def);
+ mod = PyModule_Create(&GPU_module_def);
- /* _gawain.types */
- PyModule_AddObject(mod, "types", (submodule = BPyInit_gawain_types()));
+ /* _gpu.types */
+ PyModule_AddObject(mod, "types", (submodule = BPyInit_gpu_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
diff --git a/source/blender/python/gawain/gwn_py_api.h b/source/blender/python/gpu/gpu_py_api.h
index 3ef85e8ae0f..387bfcab950 100644
--- a/source/blender/python/gawain/gwn_py_api.h
+++ b/source/blender/python/gpu/gpu_py_api.h
@@ -18,13 +18,13 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __GWN_PY_API_H__
-#define __GWN_PY_API_H__
+#ifndef __GPU_PY_API_H__
+#define __GPU_PY_API_H__
-/** \file blender/python/gawain/gwn_py_api.h
- * \ingroup pygawain
+/** \file blender/python/gpu/gpu_py_api.h
+ * \ingroup pygpu
*/
-PyObject *BPyInit_gawain(void);
+PyObject *BPyInit_gpu(void);
-#endif /* __GWN_PY_API_H__ */
+#endif /* __GPU_PY_API_H__ */
diff --git a/source/blender/python/gawain/gwn_py_types.c b/source/blender/python/gpu/gpu_py_types.c
index bdf0be9f7e1..4e564fdf849 100644
--- a/source/blender/python/gawain/gwn_py_types.c
+++ b/source/blender/python/gpu/gpu_py_types.c
@@ -18,28 +18,26 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/python/gawain/gwn_py_types.c
- * \ingroup pygawain
+/** \file blender/python/gpu/gpu_py_types.c
+ * \ingroup pygpu
*
- * - Use ``bpygwn_`` for local API.
- * - Use ``BPyGwn_`` for public API.
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
*/
#include <Python.h>
-#include "gawain/gwn_batch.h"
-#include "gawain/gwn_vertex_format.h"
+#include "GPU_batch.h"
+#include "GPU_vertex_format.h"
#include "BLI_math.h"
-#include "GPU_batch.h"
-
#include "MEM_guardedalloc.h"
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
-#include "gwn_py_types.h" /* own include */
+#include "gpu_py_types.h" /* own include */
#ifdef __BIG_ENDIAN__
/* big endian */
@@ -60,7 +58,7 @@
* Use with PyArg_ParseTuple's "O&" formatting.
* \{ */
-static int bpygwn_ParseVertCompType(PyObject *o, void *p)
+static int bpygpu_ParseVertCompType(PyObject *o, void *p)
{
Py_ssize_t comp_type_id_len;
const char *comp_type_id = _PyUnicode_AsStringAndSize(o, &comp_type_id_len);
@@ -71,21 +69,21 @@ static int bpygwn_ParseVertCompType(PyObject *o, void *p)
return 0;
}
- Gwn_VertCompType comp_type;
+ GPUVertCompType comp_type;
if (comp_type_id_len == 2) {
switch (*((ushort *)comp_type_id)) {
- case MAKE_ID2('I', '8'): { comp_type = GWN_COMP_I8; goto success; }
- case MAKE_ID2('U', '8'): { comp_type = GWN_COMP_U8; goto success; }
+ case MAKE_ID2('I', '8'): { comp_type = GPU_COMP_I8; goto success; }
+ case MAKE_ID2('U', '8'): { comp_type = GPU_COMP_U8; goto success; }
}
}
else if (comp_type_id_len == 3) {
switch (*((uint *)comp_type_id)) {
- case MAKE_ID3('I', '1', '6'): { comp_type = GWN_COMP_I16; goto success; }
- case MAKE_ID3('U', '1', '6'): { comp_type = GWN_COMP_U16; goto success; }
- case MAKE_ID3('I', '3', '2'): { comp_type = GWN_COMP_I32; goto success; }
- case MAKE_ID3('U', '3', '2'): { comp_type = GWN_COMP_U32; goto success; }
- case MAKE_ID3('F', '3', '2'): { comp_type = GWN_COMP_F32; goto success; }
- case MAKE_ID3('I', '1', '0'): { comp_type = GWN_COMP_I10; goto success; }
+ case MAKE_ID3('I', '1', '6'): { comp_type = GPU_COMP_I16; goto success; }
+ case MAKE_ID3('U', '1', '6'): { comp_type = GPU_COMP_U16; goto success; }
+ case MAKE_ID3('I', '3', '2'): { comp_type = GPU_COMP_I32; goto success; }
+ case MAKE_ID3('U', '3', '2'): { comp_type = GPU_COMP_U32; goto success; }
+ case MAKE_ID3('F', '3', '2'): { comp_type = GPU_COMP_F32; goto success; }
+ case MAKE_ID3('I', '1', '0'): { comp_type = GPU_COMP_I10; goto success; }
}
}
@@ -95,11 +93,11 @@ static int bpygwn_ParseVertCompType(PyObject *o, void *p)
return 0;
success:
- *((Gwn_VertCompType *)p) = comp_type;
+ *((GPUVertCompType *)p) = comp_type;
return 1;
}
-static int bpygwn_ParseVertFetchMode(PyObject *o, void *p)
+static int bpygpu_ParseVertFetchMode(PyObject *o, void *p)
{
Py_ssize_t mode_id_len;
const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
@@ -112,12 +110,12 @@ static int bpygwn_ParseVertFetchMode(PyObject *o, void *p)
#define MATCH_ID(id) \
if (mode_id_len == strlen(STRINGIFY(id))) { \
if (STREQ(mode_id, STRINGIFY(id))) { \
- mode = GWN_FETCH_##id; \
+ mode = GPU_FETCH_##id; \
goto success; \
} \
} ((void)0)
- Gwn_VertFetchMode mode;
+ GPUVertFetchMode mode;
MATCH_ID(FLOAT);
MATCH_ID(INT);
MATCH_ID(INT_TO_FLOAT_UNIT);
@@ -129,11 +127,11 @@ static int bpygwn_ParseVertFetchMode(PyObject *o, void *p)
return 0;
success:
- (*(Gwn_VertFetchMode *)p) = mode;
+ (*(GPUVertFetchMode *)p) = mode;
return 1;
}
-static int bpygwn_ParsePrimType(PyObject *o, void *p)
+static int bpygpu_ParsePrimType(PyObject *o, void *p)
{
Py_ssize_t mode_id_len;
const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
@@ -146,12 +144,12 @@ static int bpygwn_ParsePrimType(PyObject *o, void *p)
#define MATCH_ID(id) \
if (mode_id_len == strlen(STRINGIFY(id))) { \
if (STREQ(mode_id, STRINGIFY(id))) { \
- mode = GWN_PRIM_##id; \
+ mode = GPU_PRIM_##id; \
goto success; \
} \
} ((void)0)
- Gwn_PrimType mode;
+ GPUPrimType mode;
MATCH_ID(POINTS);
MATCH_ID(LINES);
MATCH_ID(TRIS);
@@ -168,7 +166,7 @@ static int bpygwn_ParsePrimType(PyObject *o, void *p)
return 0;
success:
- (*(Gwn_PrimType *)p) = mode;
+ (*(GPUPrimType *)p) = mode;
return 1;
}
@@ -182,19 +180,19 @@ success:
#define PY_AS_NATIVE_SWITCH(attr) \
switch (attr->comp_type) { \
- case GWN_COMP_I8: { PY_AS_NATIVE(int8_t, PyC_Long_AsI8); break; } \
- case GWN_COMP_U8: { PY_AS_NATIVE(uint8_t, PyC_Long_AsU8); break; } \
- case GWN_COMP_I16: { PY_AS_NATIVE(int16_t, PyC_Long_AsI16); break; } \
- case GWN_COMP_U16: { PY_AS_NATIVE(uint16_t, PyC_Long_AsU16); break; } \
- case GWN_COMP_I32: { PY_AS_NATIVE(int32_t, PyC_Long_AsI32); break; } \
- case GWN_COMP_U32: { PY_AS_NATIVE(uint32_t, PyC_Long_AsU32); break; } \
- case GWN_COMP_F32: { PY_AS_NATIVE(float, PyFloat_AsDouble); break; } \
+ case GPU_COMP_I8: { PY_AS_NATIVE(int8_t, PyC_Long_AsI8); break; } \
+ case GPU_COMP_U8: { PY_AS_NATIVE(uint8_t, PyC_Long_AsU8); break; } \
+ case GPU_COMP_I16: { PY_AS_NATIVE(int16_t, PyC_Long_AsI16); break; } \
+ case GPU_COMP_U16: { PY_AS_NATIVE(uint16_t, PyC_Long_AsU16); break; } \
+ case GPU_COMP_I32: { PY_AS_NATIVE(int32_t, PyC_Long_AsI32); break; } \
+ case GPU_COMP_U32: { PY_AS_NATIVE(uint32_t, PyC_Long_AsU32); break; } \
+ case GPU_COMP_F32: { PY_AS_NATIVE(float, PyFloat_AsDouble); break; } \
default: \
BLI_assert(0); \
} ((void)0)
/* No error checking, callers must run PyErr_Occurred */
-static void fill_format_elem(void *data_dst_void, PyObject *py_src, const Gwn_VertAttr *attr)
+static void fill_format_elem(void *data_dst_void, PyObject *py_src, const GPUVertAttr *attr)
{
#define PY_AS_NATIVE(ty_dst, py_as_native) \
{ \
@@ -208,7 +206,7 @@ static void fill_format_elem(void *data_dst_void, PyObject *py_src, const Gwn_Ve
}
/* No error checking, callers must run PyErr_Occurred */
-static void fill_format_tuple(void *data_dst_void, PyObject *py_src, const Gwn_VertAttr *attr)
+static void fill_format_tuple(void *data_dst_void, PyObject *py_src, const GPUVertAttr *attr)
{
const uint len = attr->comp_len;
@@ -230,15 +228,15 @@ static void fill_format_tuple(void *data_dst_void, PyObject *py_src, const Gwn_V
#undef WARN_TYPE_LIMIT_PUSH
#undef WARN_TYPE_LIMIT_POP
-static bool bpygwn_vertbuf_fill_impl(
- Gwn_VertBuf *vbo,
+static bool bpygpu_vertbuf_fill_impl(
+ GPUVertBuf *vbo,
uint data_id, PyObject *seq)
{
bool ok = true;
- const Gwn_VertAttr *attr = &vbo->format.attribs[data_id];
+ const GPUVertAttr *attr = &vbo->format.attribs[data_id];
- Gwn_VertBufRaw data_step;
- GWN_vertbuf_attr_get_raw_data(vbo, data_id, &data_step);
+ GPUVertBufRaw data_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, data_id, &data_step);
PyObject *seq_fast = PySequence_Fast(seq, "Vertex buffer fill");
if (seq_fast == NULL) {
@@ -257,14 +255,14 @@ static bool bpygwn_vertbuf_fill_impl(
if (attr->comp_len == 1) {
for (uint i = 0; i < seq_len; i++) {
- uchar *data = (uchar *)GWN_vertbuf_raw_step(&data_step);
+ uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *item = seq_items[i];
fill_format_elem(data, item, attr);
}
}
else {
for (uint i = 0; i < seq_len; i++) {
- uchar *data = (uchar *)GWN_vertbuf_raw_step(&data_step);
+ uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *item = seq_items[i];
if (!PyTuple_CheckExact(item)) {
PyErr_Format(PyExc_ValueError,
@@ -298,7 +296,7 @@ finally:
/* handy, but not used just now */
#if 0
-static int bpygwn_find_id(const Gwn_VertFormat *fmt, const char *id)
+static int bpygpu_find_id(const GPUVertFormat *fmt, const char *id)
{
for (int i = 0; i < fmt->attr_len; i++) {
for (uint j = 0; j < fmt->name_len; j++) {
@@ -319,7 +317,7 @@ static int bpygwn_find_id(const Gwn_VertFormat *fmt, const char *id)
/** \name VertFormat Type
* \{ */
-static PyObject *bpygwn_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) {
PyErr_SetString(PyExc_TypeError,
@@ -327,64 +325,64 @@ static PyObject *bpygwn_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *arg
return NULL;
}
- BPyGwn_VertFormat *ret = (BPyGwn_VertFormat *)BPyGwn_VertFormat_CreatePyObject(NULL);
+ BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
return (PyObject *)ret;
}
-PyDoc_STRVAR(bpygwn_VertFormat_attr_add_doc,
+PyDoc_STRVAR(bpygpu_VertFormat_attr_add_doc,
"TODO"
);
-static PyObject *bpygwn_VertFormat_attr_add(BPyGwn_VertFormat *self, PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"id", "comp_type", "len", "fetch_mode", NULL};
struct {
const char *id;
- Gwn_VertCompType comp_type;
+ GPUVertCompType comp_type;
uint len;
- Gwn_VertFetchMode fetch_mode;
+ GPUVertFetchMode fetch_mode;
} params;
- if (self->fmt.attr_len == GWN_VERT_ATTR_MAX_LEN) {
- PyErr_SetString(PyExc_ValueError, "Maxumum attr reached " STRINGIFY(GWN_VERT_ATTR_MAX_LEN));
+ if (self->fmt.attr_len == GPU_VERT_ATTR_MAX_LEN) {
+ PyErr_SetString(PyExc_ValueError, "Maxumum attr reached " STRINGIFY(GPU_VERT_ATTR_MAX_LEN));
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "$sO&IO&:attr_add", (char **)kwlist,
&params.id,
- bpygwn_ParseVertCompType, &params.comp_type,
+ bpygpu_ParseVertCompType, &params.comp_type,
&params.len,
- bpygwn_ParseVertFetchMode, &params.fetch_mode))
+ bpygpu_ParseVertFetchMode, &params.fetch_mode))
{
return NULL;
}
- uint attr_id = GWN_vertformat_attr_add(&self->fmt, params.id, params.comp_type, params.len, params.fetch_mode);
+ uint attr_id = GPU_vertformat_attr_add(&self->fmt, params.id, params.comp_type, params.len, params.fetch_mode);
return PyLong_FromLong(attr_id);
}
-static struct PyMethodDef bpygwn_VertFormat_methods[] = {
- {"attr_add", (PyCFunction)bpygwn_VertFormat_attr_add,
- METH_VARARGS | METH_KEYWORDS, bpygwn_VertFormat_attr_add_doc},
+static struct PyMethodDef bpygpu_VertFormat_methods[] = {
+ {"attr_add", (PyCFunction)bpygpu_VertFormat_attr_add,
+ METH_VARARGS | METH_KEYWORDS, bpygpu_VertFormat_attr_add_doc},
{NULL, NULL, 0, NULL}
};
-static void bpygwn_VertFormat_dealloc(BPyGwn_VertFormat *self)
+static void bpygpu_VertFormat_dealloc(BPyGPUVertFormat *self)
{
Py_TYPE(self)->tp_free(self);
}
-PyTypeObject BPyGwn_VertFormat_Type = {
+PyTypeObject BPyGPUVertFormat_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "Gwn_VertFormat",
- .tp_basicsize = sizeof(BPyGwn_VertFormat),
- .tp_dealloc = (destructor)bpygwn_VertFormat_dealloc,
+ .tp_name = "GPUVertFormat",
+ .tp_basicsize = sizeof(BPyGPUVertFormat),
+ .tp_dealloc = (destructor)bpygpu_VertFormat_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_methods = bpygwn_VertFormat_methods,
- .tp_new = bpygwn_VertFormat_new,
+ .tp_methods = bpygpu_VertFormat_methods,
+ .tp_new = bpygpu_VertFormat_new,
};
/** \} */
@@ -395,35 +393,35 @@ PyTypeObject BPyGwn_VertFormat_Type = {
/** \name VertBuf Type
* \{ */
-static PyObject *bpygwn_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
const char * const keywords[] = {"len", "format", NULL};
struct {
- BPyGwn_VertFormat *py_fmt;
+ BPyGPUVertFormat *py_fmt;
uint len;
} params;
if (!PyArg_ParseTupleAndKeywords(
args, kwds,
- "$IO!:Gwn_VertBuf.__new__", (char **)keywords,
+ "$IO!:GPUVertBuf.__new__", (char **)keywords,
&params.len,
- &BPyGwn_VertFormat_Type, &params.py_fmt))
+ &BPyGPUVertFormat_Type, &params.py_fmt))
{
return NULL;
}
- struct Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&params.py_fmt->fmt);
+ struct GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&params.py_fmt->fmt);
- GWN_vertbuf_data_alloc(vbo, params.len);
+ GPU_vertbuf_data_alloc(vbo, params.len);
- return BPyGwn_VertBuf_CreatePyObject(vbo);
+ return BPyGPUVertBuf_CreatePyObject(vbo);
}
-PyDoc_STRVAR(bpygwn_VertBuf_fill_doc,
+PyDoc_STRVAR(bpygpu_VertBuf_fill_doc,
"TODO"
);
-static PyObject *bpygwn_VertBuf_fill(BPyGwn_VertBuf *self, PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertBuf_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"id", "data", NULL};
@@ -453,32 +451,32 @@ static PyObject *bpygwn_VertBuf_fill(BPyGwn_VertBuf *self, PyObject *args, PyObj
return NULL;
}
- if (!bpygwn_vertbuf_fill_impl(self->buf, params.id, params.py_seq_data)) {
+ if (!bpygpu_vertbuf_fill_impl(self->buf, params.id, params.py_seq_data)) {
return NULL;
}
Py_RETURN_NONE;
}
-static struct PyMethodDef bpygwn_VertBuf_methods[] = {
- {"fill", (PyCFunction) bpygwn_VertBuf_fill,
- METH_VARARGS | METH_KEYWORDS, bpygwn_VertBuf_fill_doc},
+static struct PyMethodDef bpygpu_VertBuf_methods[] = {
+ {"fill", (PyCFunction) bpygpu_VertBuf_fill,
+ METH_VARARGS | METH_KEYWORDS, bpygpu_VertBuf_fill_doc},
{NULL, NULL, 0, NULL}
};
-static void bpygwn_VertBuf_dealloc(BPyGwn_VertBuf *self)
+static void bpygpu_VertBuf_dealloc(BPyGPUVertBuf *self)
{
- GWN_vertbuf_discard(self->buf);
+ GPU_vertbuf_discard(self->buf);
Py_TYPE(self)->tp_free(self);
}
-PyTypeObject BPyGwn_VertBuf_Type = {
+PyTypeObject BPyGPUVertBuf_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "Gwn_VertBuf",
- .tp_basicsize = sizeof(BPyGwn_VertBuf),
- .tp_dealloc = (destructor)bpygwn_VertBuf_dealloc,
+ .tp_name = "GPUVertBuf",
+ .tp_basicsize = sizeof(BPyGPUVertBuf),
+ .tp_dealloc = (destructor)bpygpu_VertBuf_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_methods = bpygwn_VertBuf_methods,
- .tp_new = bpygwn_VertBuf_new,
+ .tp_methods = bpygpu_VertBuf_methods,
+ .tp_new = bpygpu_VertBuf_new,
};
/** \} */
@@ -489,28 +487,28 @@ PyTypeObject BPyGwn_VertBuf_Type = {
/** \name VertBatch Type
* \{ */
-static PyObject *bpygwn_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
const char * const keywords[] = {"type", "buf", NULL};
struct {
- Gwn_PrimType type_id;
- BPyGwn_VertBuf *py_buf;
+ GPUPrimType type_id;
+ BPyGPUVertBuf *py_buf;
} params;
if (!PyArg_ParseTupleAndKeywords(
args, kwds,
- "$O&O!:Gwn_Batch.__new__", (char **)keywords,
- bpygwn_ParsePrimType, &params.type_id,
- &BPyGwn_VertBuf_Type, &params.py_buf))
+ "$O&O!:GPUBatch.__new__", (char **)keywords,
+ bpygpu_ParsePrimType, &params.type_id,
+ &BPyGPUVertBuf_Type, &params.py_buf))
{
return NULL;
}
- Gwn_Batch *batch = GWN_batch_create(params.type_id, params.py_buf->buf, NULL);
- BPyGwn_Batch *ret = (BPyGwn_Batch *)BPyGwn_Batch_CreatePyObject(batch);
+ GPUBatch *batch = GPU_batch_create(params.type_id, params.py_buf->buf, NULL);
+ BPyGPUBatch *ret = (BPyGPUBatch *)BPyGPUBatch_CreatePyObject(batch);
-#ifdef USE_GWN_PY_REFERENCES
+#ifdef USE_GPU_PY_REFERENCES
ret->references = PyList_New(1);
PyList_SET_ITEM(ret->references, 0, (PyObject *)params.py_buf);
Py_INCREF(params.py_buf);
@@ -520,14 +518,14 @@ static PyObject *bpygwn_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, Py
return (PyObject *)ret;
}
-PyDoc_STRVAR(bpygwn_VertBatch_vertbuf_add_doc,
+PyDoc_STRVAR(bpygpu_VertBatch_vertbuf_add_doc,
"TODO"
);
-static PyObject *bpygwn_VertBatch_vertbuf_add(BPyGwn_Batch *self, BPyGwn_VertBuf *py_buf)
+static PyObject *bpygpu_VertBatch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_buf)
{
- if (!BPyGwn_VertBuf_Check(py_buf)) {
+ if (!BPyGPUVertBuf_Check(py_buf)) {
PyErr_Format(PyExc_TypeError,
- "Expected a Gwn_VertBuf, got %s",
+ "Expected a GPUVertBuf, got %s",
Py_TYPE(py_buf)->tp_name);
return NULL;
}
@@ -539,20 +537,20 @@ static PyObject *bpygwn_VertBatch_vertbuf_add(BPyGwn_Batch *self, BPyGwn_VertBuf
return NULL;
}
-#ifdef USE_GWN_PY_REFERENCES
+#ifdef USE_GPU_PY_REFERENCES
/* Hold user */
PyList_Append(self->references, (PyObject *)py_buf);
#endif
- GWN_batch_vertbuf_add(self->batch, py_buf->buf);
+ GPU_batch_vertbuf_add(self->batch, py_buf->buf);
Py_RETURN_NONE;
}
/* Currently magic number from Py perspective. */
-PyDoc_STRVAR(bpygwn_VertBatch_program_set_builtin_doc,
+PyDoc_STRVAR(bpygpu_VertBatch_program_set_builtin_doc,
"TODO"
);
-static PyObject *bpygwn_VertBatch_program_set_builtin(BPyGwn_Batch *self, PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertBatch_program_set_builtin(BPyGPUBatch *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"id", NULL};
@@ -590,11 +588,11 @@ static PyObject *bpygwn_VertBatch_program_set_builtin(BPyGwn_Batch *self, PyObje
return NULL;
success:
- GWN_batch_program_set_builtin(self->batch, shader);
+ GPU_batch_program_set_builtin(self->batch, shader);
Py_RETURN_NONE;
}
-static PyObject *bpygwn_VertBatch_uniform_bool(BPyGwn_Batch *self, PyObject *args)
+static PyObject *bpygpu_VertBatch_uniform_bool(BPyGPUBatch *self, PyObject *args)
{
struct {
const char *id;
@@ -609,11 +607,11 @@ static PyObject *bpygwn_VertBatch_uniform_bool(BPyGwn_Batch *self, PyObject *arg
return NULL;
}
- GWN_batch_uniform_1b(self->batch, params.id, params.values[0]);
+ GPU_batch_uniform_1b(self->batch, params.id, params.values[0]);
Py_RETURN_NONE;
}
-static PyObject *bpygwn_VertBatch_uniform_i32(BPyGwn_Batch *self, PyObject *args)
+static PyObject *bpygpu_VertBatch_uniform_i32(BPyGPUBatch *self, PyObject *args)
{
struct {
const char *id;
@@ -628,11 +626,11 @@ static PyObject *bpygwn_VertBatch_uniform_i32(BPyGwn_Batch *self, PyObject *args
return NULL;
}
- GWN_batch_uniform_1i(self->batch, params.id, params.values[0]);
+ GPU_batch_uniform_1i(self->batch, params.id, params.values[0]);
Py_RETURN_NONE;
}
-static PyObject *bpygwn_VertBatch_uniform_f32(BPyGwn_Batch *self, PyObject *args)
+static PyObject *bpygpu_VertBatch_uniform_f32(BPyGPUBatch *self, PyObject *args)
{
struct {
const char *id;
@@ -648,78 +646,78 @@ static PyObject *bpygwn_VertBatch_uniform_f32(BPyGwn_Batch *self, PyObject *args
}
switch (PyTuple_GET_SIZE(args)) {
- case 2: GWN_batch_uniform_1f(self->batch, params.id, params.values[0]); break;
- case 3: GWN_batch_uniform_2f(self->batch, params.id, UNPACK2(params.values)); break;
- case 4: GWN_batch_uniform_3f(self->batch, params.id, UNPACK3(params.values)); break;
- case 5: GWN_batch_uniform_4f(self->batch, params.id, UNPACK4(params.values)); break;
+ case 2: GPU_batch_uniform_1f(self->batch, params.id, params.values[0]); break;
+ case 3: GPU_batch_uniform_2f(self->batch, params.id, UNPACK2(params.values)); break;
+ case 4: GPU_batch_uniform_3f(self->batch, params.id, UNPACK3(params.values)); break;
+ case 5: GPU_batch_uniform_4f(self->batch, params.id, UNPACK4(params.values)); break;
default:
BLI_assert(0);
}
Py_RETURN_NONE;
}
-PyDoc_STRVAR(bpygwn_VertBatch_draw_doc,
+PyDoc_STRVAR(bpygpu_VertBatch_draw_doc,
"TODO"
);
-static PyObject *bpygwn_VertBatch_draw(BPyGwn_Batch *self)
+static PyObject *bpygpu_VertBatch_draw(BPyGPUBatch *self)
{
if (!glIsProgram(self->batch->program)) {
PyErr_SetString(PyExc_ValueError,
"batch program has not not set");
}
- GWN_batch_draw(self->batch);
+ GPU_batch_draw(self->batch);
Py_RETURN_NONE;
}
-static PyObject *bpygwn_VertBatch_program_use_begin(BPyGwn_Batch *self)
+static PyObject *bpygpu_VertBatch_program_use_begin(BPyGPUBatch *self)
{
if (!glIsProgram(self->batch->program)) {
PyErr_SetString(PyExc_ValueError,
"batch program has not not set");
}
- GWN_batch_program_use_begin(self->batch);
+ GPU_batch_program_use_begin(self->batch);
Py_RETURN_NONE;
}
-static PyObject *bpygwn_VertBatch_program_use_end(BPyGwn_Batch *self)
+static PyObject *bpygpu_VertBatch_program_use_end(BPyGPUBatch *self)
{
if (!glIsProgram(self->batch->program)) {
PyErr_SetString(PyExc_ValueError,
"batch program has not not set");
}
- GWN_batch_program_use_end(self->batch);
+ GPU_batch_program_use_end(self->batch);
Py_RETURN_NONE;
}
-static struct PyMethodDef bpygwn_VertBatch_methods[] = {
- {"vertbuf_add", (PyCFunction)bpygwn_VertBatch_vertbuf_add,
- METH_O, bpygwn_VertBatch_vertbuf_add_doc},
- {"program_set_builtin", (PyCFunction)bpygwn_VertBatch_program_set_builtin,
- METH_VARARGS | METH_KEYWORDS, bpygwn_VertBatch_program_set_builtin_doc},
- {"uniform_bool", (PyCFunction)bpygwn_VertBatch_uniform_bool,
+static struct PyMethodDef bpygpu_VertBatch_methods[] = {
+ {"vertbuf_add", (PyCFunction)bpygpu_VertBatch_vertbuf_add,
+ METH_O, bpygpu_VertBatch_vertbuf_add_doc},
+ {"program_set_builtin", (PyCFunction)bpygpu_VertBatch_program_set_builtin,
+ METH_VARARGS | METH_KEYWORDS, bpygpu_VertBatch_program_set_builtin_doc},
+ {"uniform_bool", (PyCFunction)bpygpu_VertBatch_uniform_bool,
METH_VARARGS, NULL},
- {"uniform_i32", (PyCFunction)bpygwn_VertBatch_uniform_i32,
+ {"uniform_i32", (PyCFunction)bpygpu_VertBatch_uniform_i32,
METH_VARARGS, NULL},
- {"uniform_f32", (PyCFunction)bpygwn_VertBatch_uniform_f32,
+ {"uniform_f32", (PyCFunction)bpygpu_VertBatch_uniform_f32,
METH_VARARGS, NULL},
- {"draw", (PyCFunction) bpygwn_VertBatch_draw,
- METH_NOARGS, bpygwn_VertBatch_draw_doc},
- {"program_use_begin", (PyCFunction)bpygwn_VertBatch_program_use_begin,
+ {"draw", (PyCFunction) bpygpu_VertBatch_draw,
+ METH_NOARGS, bpygpu_VertBatch_draw_doc},
+ {"program_use_begin", (PyCFunction)bpygpu_VertBatch_program_use_begin,
METH_NOARGS, ""},
- {"program_use_end", (PyCFunction)bpygwn_VertBatch_program_use_end,
+ {"program_use_end", (PyCFunction)bpygpu_VertBatch_program_use_end,
METH_NOARGS, ""},
{NULL, NULL, 0, NULL}
};
-#ifdef USE_GWN_PY_REFERENCES
+#ifdef USE_GPU_PY_REFERENCES
-static int bpygwn_Batch_traverse(BPyGwn_Batch *self, visitproc visit, void *arg)
+static int bpygpu_Batch_traverse(BPyGPUBatch *self, visitproc visit, void *arg)
{
Py_VISIT(self->references);
return 0;
}
-static int bpygwn_Batch_clear(BPyGwn_Batch *self)
+static int bpygpu_Batch_clear(BPyGPUBatch *self)
{
Py_CLEAR(self->references);
return 0;
@@ -727,14 +725,14 @@ static int bpygwn_Batch_clear(BPyGwn_Batch *self)
#endif
-static void bpygwn_Batch_dealloc(BPyGwn_Batch *self)
+static void bpygpu_Batch_dealloc(BPyGPUBatch *self)
{
- GWN_batch_discard(self->batch);
+ GPU_batch_discard(self->batch);
-#ifdef USE_GWN_PY_REFERENCES
+#ifdef USE_GPU_PY_REFERENCES
if (self->references) {
PyObject_GC_UnTrack(self);
- bpygwn_Batch_clear(self);
+ bpygpu_Batch_clear(self);
Py_XDECREF(self->references);
}
#endif
@@ -742,52 +740,52 @@ static void bpygwn_Batch_dealloc(BPyGwn_Batch *self)
Py_TYPE(self)->tp_free(self);
}
-PyTypeObject BPyGwn_Batch_Type = {
+PyTypeObject BPyGPUBatch_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "Gwn_Batch",
- .tp_basicsize = sizeof(BPyGwn_Batch),
- .tp_dealloc = (destructor)bpygwn_Batch_dealloc,
-#ifdef USE_GWN_PY_REFERENCES
+ .tp_name = "GPUBatch",
+ .tp_basicsize = sizeof(BPyGPUBatch),
+ .tp_dealloc = (destructor)bpygpu_Batch_dealloc,
+#ifdef USE_GPU_PY_REFERENCES
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- .tp_traverse = (traverseproc)bpygwn_Batch_traverse,
- .tp_clear = (inquiry)bpygwn_Batch_clear,
+ .tp_traverse = (traverseproc)bpygpu_Batch_traverse,
+ .tp_clear = (inquiry)bpygpu_Batch_clear,
#else
.tp_flags = Py_TPFLAGS_DEFAULT,
#endif
- .tp_methods = bpygwn_VertBatch_methods,
- .tp_new = bpygwn_Batch_new,
+ .tp_methods = bpygpu_VertBatch_methods,
+ .tp_new = bpygpu_Batch_new,
};
/* -------------------------------------------------------------------- */
-/** \name Gawain Types Module
+/** \name GPU Types Module
* \{ */
static struct PyModuleDef BPy_BM_types_module_def = {
PyModuleDef_HEAD_INIT,
- .m_name = "_gawain.types",
+ .m_name = "_gpu.types",
};
-PyObject *BPyInit_gawain_types(void)
+PyObject *BPyInit_gpu_types(void)
{
PyObject *submodule;
submodule = PyModule_Create(&BPy_BM_types_module_def);
- if (PyType_Ready(&BPyGwn_VertFormat_Type) < 0)
+ if (PyType_Ready(&BPyGPUVertFormat_Type) < 0)
return NULL;
- if (PyType_Ready(&BPyGwn_VertBuf_Type) < 0)
+ if (PyType_Ready(&BPyGPUVertBuf_Type) < 0)
return NULL;
- if (PyType_Ready(&BPyGwn_Batch_Type) < 0)
+ if (PyType_Ready(&BPyGPUBatch_Type) < 0)
return NULL;
#define MODULE_TYPE_ADD(s, t) \
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
- MODULE_TYPE_ADD(submodule, BPyGwn_VertFormat_Type);
- MODULE_TYPE_ADD(submodule, BPyGwn_VertBuf_Type);
- MODULE_TYPE_ADD(submodule, BPyGwn_Batch_Type);
+ MODULE_TYPE_ADD(submodule, BPyGPUVertFormat_Type);
+ MODULE_TYPE_ADD(submodule, BPyGPUVertBuf_Type);
+ MODULE_TYPE_ADD(submodule, BPyGPUBatch_Type);
#undef MODULE_TYPE_ADD
@@ -802,11 +800,11 @@ PyObject *BPyInit_gawain_types(void)
/** \name Public API
* \{ */
-PyObject *BPyGwn_VertFormat_CreatePyObject(Gwn_VertFormat *fmt)
+PyObject *BPyGPUVertFormat_CreatePyObject(GPUVertFormat *fmt)
{
- BPyGwn_VertFormat *self;
+ BPyGPUVertFormat *self;
- self = PyObject_New(BPyGwn_VertFormat, &BPyGwn_VertFormat_Type);
+ self = PyObject_New(BPyGPUVertFormat, &BPyGPUVertFormat_Type);
if (fmt) {
self->fmt = *fmt;
}
@@ -817,26 +815,26 @@ PyObject *BPyGwn_VertFormat_CreatePyObject(Gwn_VertFormat *fmt)
return (PyObject *)self;
}
-PyObject *BPyGwn_VertBuf_CreatePyObject(Gwn_VertBuf *buf)
+PyObject *BPyGPUVertBuf_CreatePyObject(GPUVertBuf *buf)
{
- BPyGwn_VertBuf *self;
+ BPyGPUVertBuf *self;
- self = PyObject_New(BPyGwn_VertBuf, &BPyGwn_VertBuf_Type);
+ self = PyObject_New(BPyGPUVertBuf, &BPyGPUVertBuf_Type);
self->buf = buf;
return (PyObject *)self;
}
-PyObject *BPyGwn_Batch_CreatePyObject(Gwn_Batch *batch)
+PyObject *BPyGPUBatch_CreatePyObject(GPUBatch *batch)
{
- BPyGwn_Batch *self;
+ BPyGPUBatch *self;
-#ifdef USE_GWN_PY_REFERENCES
- self = (BPyGwn_Batch *)_PyObject_GC_New(&BPyGwn_Batch_Type);
+#ifdef USE_GPU_PY_REFERENCES
+ self = (BPyGPUBatch *)_PyObject_GC_New(&BPyGPUBatch_Type);
self->references = NULL;
#else
- self = PyObject_New(BPyGwn_Batch, &BPyGwn_Batch_Type);
+ self = PyObject_New(BPyGPUBatch, &BPyGPUBatch_Type);
#endif
self->batch = batch;
diff --git a/source/blender/python/gawain/gwn_py_types.h b/source/blender/python/gpu/gpu_py_types.h
index dde6cf98827..f736a8f749a 100644
--- a/source/blender/python/gawain/gwn_py_types.h
+++ b/source/blender/python/gpu/gpu_py_types.h
@@ -18,50 +18,50 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/python/gawain/gwn_py_types.h
- * \ingroup pygawain
+/** \file blender/python/gpu/gpu_py_types.h
+ * \ingroup pygpu
*/
-#ifndef __GWN_PY_TYPES_H__
-#define __GWN_PY_TYPES_H__
+#ifndef __GPU_PY_TYPES_H__
+#define __GPU_PY_TYPES_H__
#include "BLI_compiler_attrs.h"
-#define USE_GWN_PY_REFERENCES
+#define USE_GPU_PY_REFERENCES
-extern PyTypeObject BPyGwn_VertFormat_Type;
-extern PyTypeObject BPyGwn_VertBuf_Type;
-extern PyTypeObject BPyGwn_Batch_Type;
+extern PyTypeObject BPyGPUVertFormat_Type;
+extern PyTypeObject BPyGPUVertBuf_Type;
+extern PyTypeObject BPyGPUBatch_Type;
-#define BPyGwn_VertFormat_Check(v) (Py_TYPE(v) == &BPyGwn_VertFormat_Type)
-#define BPyGwn_VertBuf_Check(v) (Py_TYPE(v) == &BPyGwn_VertBuf_Type)
-#define BPyGwn_Batch_Check(v) (Py_TYPE(v) == &BPyGwn_Batch_Type)
+#define BPyGPUVertFormat_Check(v) (Py_TYPE(v) == &BPyGPUVertFormat_Type)
+#define BPyGPUVertBuf_Check(v) (Py_TYPE(v) == &BPyGPUVertBuf_Type)
+#define BPyGPUBatch_Check(v) (Py_TYPE(v) == &BPyGPUBatch_Type)
-typedef struct BPyGwn_VertFormat {
+typedef struct BPyGPUVertFormat {
PyObject_VAR_HEAD
- struct Gwn_VertFormat fmt;
-} BPyGwn_VertFormat;
+ struct GPUVertFormat fmt;
+} BPyGPUVertFormat;
-typedef struct BPyGwn_VertBuf {
+typedef struct BPyGPUVertBuf {
PyObject_VAR_HEAD
/* The buf is owned, we may support thin wrapped batches later. */
- struct Gwn_VertBuf *buf;
-} BPyGwn_VertBuf;
+ struct GPUVertBuf *buf;
+} BPyGPUVertBuf;
-typedef struct BPyGwn_Batch {
+typedef struct BPyGPUBatch {
PyObject_VAR_HEAD
/* The batch is owned, we may support thin wrapped batches later. */
- struct Gwn_Batch *batch;
-#ifdef USE_GWN_PY_REFERENCES
+ struct GPUBatch *batch;
+#ifdef USE_GPU_PY_REFERENCES
/* Just to keep a user to prevent freeing buf's we're using */
PyObject *references;
#endif
-} BPyGwn_Batch;
+} BPyGPUBatch;
-PyObject *BPyInit_gawain_types(void);
+PyObject *BPyInit_gpu_types(void);
-PyObject *BPyGwn_VertFormat_CreatePyObject(struct Gwn_VertFormat *fmt);
-PyObject *BPyGwn_VertBuf_CreatePyObject(struct Gwn_VertBuf *vbo) ATTR_NONNULL(1);
-PyObject *BPyGwn_Batch_CreatePyObject(struct Gwn_Batch *batch) ATTR_NONNULL(1);
+PyObject *BPyGPUVertFormat_CreatePyObject(struct GPUVertFormat *fmt);
+PyObject *BPyGPUVertBuf_CreatePyObject(struct GPUVertBuf *vbo) ATTR_NONNULL(1);
+PyObject *BPyGPUBatch_CreatePyObject(struct GPUBatch *batch) ATTR_NONNULL(1);
-#endif /* __GWN_PY_TYPES_H__ */
+#endif /* __GPU_PY_TYPES_H__ */
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index d3464ea5841..a94708c0602 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -254,7 +254,7 @@ static void pydriver_error(ChannelDriver *driver)
#define OK_OP(op) [op] = 1
-const char secure_opcodes[255] = {
+static const char secure_opcodes[255] = {
OK_OP(POP_TOP),
OK_OP(ROT_TWO),
OK_OP(ROT_THREE),
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c
index 4b71ea92010..2a932cb6a99 100644
--- a/source/blender/python/intern/bpy_gizmo_wrap.c
+++ b/source/blender/python/intern/bpy_gizmo_wrap.c
@@ -54,7 +54,7 @@
static bool bpy_gizmotype_target_property_def(
- wmGizmoType *wt, PyObject *item)
+ wmGizmoType *gzt, PyObject *item)
{
/* Note: names based on 'rna_rna.c' */
PyObject *empty_tuple = PyTuple_New(0);
@@ -102,7 +102,7 @@ static bool bpy_gizmotype_target_property_def(
goto fail;
}
- WM_gizmotype_target_property_def(wt, params.id, params.type, params.array_length);
+ WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length);
Py_DECREF(empty_tuple);
return true;
@@ -111,17 +111,17 @@ fail:
return false;
}
-static void gizmo_properties_init(wmGizmoType *wt)
+static void gizmo_properties_init(wmGizmoType *gzt)
{
- PyTypeObject *py_class = wt->ext.data;
- RNA_struct_blender_type_set(wt->ext.srna, wt);
+ PyTypeObject *py_class = gzt->ext.data;
+ RNA_struct_blender_type_set(gzt->ext.srna, gzt);
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
- RNA_def_struct_identifier_no_struct_map(wt->srna, wt->idname);
+ RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname);
- if (pyrna_deferred_register_class(wt->srna, py_class) != 0) {
+ if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
@@ -149,7 +149,7 @@ static void gizmo_properties_init(wmGizmoType *wt)
PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
for (uint i = 0; i < items_len; i++) {
- if (!bpy_gizmotype_target_property_def(wt, items[i])) {
+ if (!bpy_gizmotype_target_property_def(gzt, items[i])) {
PyErr_Print();
PyErr_Clear();
break;
@@ -161,25 +161,25 @@ static void gizmo_properties_init(wmGizmoType *wt)
}
}
-void BPY_RNA_gizmo_wrapper(wmGizmoType *wt, void *userdata)
+void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata)
{
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
- StructRNA *srna = wt->srna;
- *wt = *((wmGizmoType *)userdata);
- wt->srna = srna; /* restore */
+ StructRNA *srna = gzt->srna;
+ *gzt = *((wmGizmoType *)userdata);
+ gzt->srna = srna; /* restore */
/* don't do translations here yet */
#if 0
/* Use i18n context from ext.srna if possible (py gizmogroups). */
- if (wt->ext.srna) {
- RNA_def_struct_translation_context(wt->srna, RNA_struct_translation_context(wt->ext.srna));
+ if (gt->ext.srna) {
+ RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna));
}
#endif
- wt->struct_size = sizeof(wmGizmo);
+ gzt->struct_size = sizeof(wmGizmo);
- gizmo_properties_init(wt);
+ gizmo_properties_init(gzt);
}
/** \} */
@@ -190,46 +190,46 @@ void BPY_RNA_gizmo_wrapper(wmGizmoType *wt, void *userdata)
/** \name Gizmo Group
* \{ */
-static void gizmogroup_properties_init(wmGizmoGroupType *wgt)
+static void gizmogroup_properties_init(wmGizmoGroupType *gzgt)
{
#ifdef USE_SRNA
- PyTypeObject *py_class = wgt->ext.data;
+ PyTypeObject *py_class = gzgt->ext.data;
#endif
- RNA_struct_blender_type_set(wgt->ext.srna, wgt);
+ RNA_struct_blender_type_set(gzgt->ext.srna, gzgt);
#ifdef USE_SRNA
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
- RNA_def_struct_identifier(wgt->srna, wgt->idname);
+ RNA_def_struct_identifier(gzgt->srna, gzgt->idname);
- if (pyrna_deferred_register_class(wgt->srna, py_class) != 0) {
+ if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
#endif
}
-void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *wgt, void *userdata)
+void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata)
{
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
#ifdef USE_SRNA
- StructRNA *srna = wgt->srna;
+ StructRNA *srna = gzgt->srna;
#endif
- *wgt = *((wmGizmoGroupType *)userdata);
+ *gzgt = *((wmGizmoGroupType *)userdata);
#ifdef USE_SRNA
- wgt->srna = srna; /* restore */
+ gzgt->srna = srna; /* restore */
#endif
#ifdef USE_SRNA
/* Use i18n context from ext.srna if possible (py gizmogroups). */
- if (wgt->ext.srna) {
- RNA_def_struct_translation_context(wgt->srna, RNA_struct_translation_context(wgt->ext.srna));
+ if (gzgt->ext.srna) {
+ RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna));
}
#endif
- gizmogroup_properties_init(wgt);
+ gizmogroup_properties_init(gzgt);
}
/** \} */
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.h b/source/blender/python/intern/bpy_gizmo_wrap.h
index 4d6639d977f..96f15312a4e 100644
--- a/source/blender/python/intern/bpy_gizmo_wrap.h
+++ b/source/blender/python/intern/bpy_gizmo_wrap.h
@@ -29,7 +29,7 @@ struct wmGizmoType;
struct wmGizmoGroupType;
/* exposed to rna/wm api */
-void BPY_RNA_gizmo_wrapper(struct wmGizmoType *wt, void *userdata);
-void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *wgt, void *userdata);
+void BPY_RNA_gizmo_wrapper(struct wmGizmoType *gzt, void *userdata);
+void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *gzgt, void *userdata);
#endif /* __BPY_GIZMO_WRAP_H__ */
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 0d7b0c92a90..64bc54c6221 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -75,7 +75,7 @@
#include "../generic/blf_py_api.h"
#include "../generic/idprop_py_api.h"
#include "../generic/imbuf_py_api.h"
-#include "../gawain/gwn_py_api.h"
+#include "../gpu/gpu_py_api.h"
#include "../bmesh/bmesh_py_api.h"
#include "../mathutils/mathutils.h"
@@ -219,7 +219,7 @@ static struct _inittab bpy_internal_modules[] = {
{"mathutils.kdtree", PyInit_mathutils_kdtree},
#endif
{"_bpy_path", BPyInit__bpy_path},
- {"_gawain", BPyInit_gawain},
+ {"_gpu", BPyInit_gpu},
{"bgl", BPyInit_bgl},
{"blf", BPyInit_blf},
{"imbuf", BPyInit_imbuf},
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index e0fbd144590..30bd3bc5ca3 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -5118,6 +5118,9 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
case PROP_RAW_DOUBLE:
item = PyFloat_FromDouble((double) ((double *)array)[i]);
break;
+ case PROP_RAW_BOOLEAN:
+ item = PyBool_FromLong((long) ((bool *)array)[i]);
+ break;
default: /* PROP_RAW_UNSET */
/* should never happen */
BLI_assert(!"Invalid array type - get");
diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c
index e834595114a..ded26f777a5 100644
--- a/source/blender/python/intern/bpy_rna_gizmo.c
+++ b/source/blender/python/intern/bpy_rna_gizmo.c
@@ -67,26 +67,26 @@ struct BPyGizmoHandlerUserData {
};
static void py_rna_gizmo_handler_get_cb(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
- struct BPyGizmoHandlerUserData *data = mpr_prop->custom_func.user_data;
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], NULL);
if (ret == NULL) {
goto fail;
}
- if (mpr_prop->type->data_type == PROP_FLOAT) {
+ if (gz_prop->type->data_type == PROP_FLOAT) {
float *value = value_p;
- if (mpr_prop->type->array_length == 1) {
+ if (gz_prop->type->array_length == 1) {
if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
goto fail;
}
}
else {
- if (PyC_AsArray(value, ret, mpr_prop->type->array_length, &PyFloat_Type, false,
+ if (PyC_AsArray(value, ret, gz_prop->type->array_length, &PyFloat_Type, false,
"Gizmo get callback: ") == -1)
{
goto fail;
@@ -111,23 +111,23 @@ fail:
}
static void py_rna_gizmo_handler_set_cb(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
const void *value_p)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
- struct BPyGizmoHandlerUserData *data = mpr_prop->custom_func.user_data;
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
PyObject *args = PyTuple_New(1);
- if (mpr_prop->type->data_type == PROP_FLOAT) {
+ if (gz_prop->type->data_type == PROP_FLOAT) {
const float *value = value_p;
PyObject *py_value;
- if (mpr_prop->type->array_length == 1) {
+ if (gz_prop->type->array_length == 1) {
py_value = PyFloat_FromDouble(*value);
}
else {
- py_value = PyC_Tuple_PackArray_F32(value, mpr_prop->type->array_length);
+ py_value = PyC_Tuple_PackArray_F32(value, gz_prop->type->array_length);
}
if (py_value == NULL) {
goto fail;
@@ -158,10 +158,10 @@ fail:
}
static void py_rna_gizmo_handler_range_get_cb(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop,
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
void *value_p)
{
- struct BPyGizmoHandlerUserData *data = mpr_prop->custom_func.user_data;
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
PyGILState_STATE gilstate = PyGILState_Ensure();
@@ -184,7 +184,7 @@ static void py_rna_gizmo_handler_range_get_cb(
goto fail;
}
- if (mpr_prop->type->data_type == PROP_FLOAT) {
+ if (gz_prop->type->data_type == PROP_FLOAT) {
float range[2];
for (int i = 0; i < 2; i++) {
if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == 0) {
@@ -215,9 +215,9 @@ fail:
}
static void py_rna_gizmo_handler_free_cb(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop)
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop)
{
- struct BPyGizmoHandlerUserData *data = mpr_prop->custom_func.user_data;
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
PyGILState_STATE gilstate = PyGILState_Ensure();
for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
@@ -271,14 +271,14 @@ static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *
goto fail;
}
- wmGizmo *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
- const wmGizmoPropertyType *mpr_prop_type =
- WM_gizmotype_target_property_find(mpr->type, params.target);
- if (mpr_prop_type == NULL) {
+ const wmGizmoPropertyType *gz_prop_type =
+ WM_gizmotype_target_property_find(gz->type, params.target);
+ if (gz_prop_type == NULL) {
PyErr_Format(PyExc_ValueError,
"Gizmo target property '%s.%s' not found",
- mpr->type->idname, params.target);
+ gz->type->idname, params.target);
goto fail;
}
@@ -307,7 +307,7 @@ static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *
}
WM_gizmo_target_property_def_func_ptr(
- mpr, mpr_prop_type,
+ gz, gz_prop_type,
&(const struct wmGizmoPropertyFnParams) {
.value_get_fn = py_rna_gizmo_handler_get_cb,
.value_set_fn = py_rna_gizmo_handler_set_cb,
@@ -361,28 +361,28 @@ static PyObject *bpy_gizmo_target_get_value(PyObject *UNUSED(self), PyObject *ar
goto fail;
}
- wmGizmo *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
- wmGizmoProperty *mpr_prop =
- WM_gizmo_target_property_find(mpr, params.target);
- if (mpr_prop == NULL) {
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
PyErr_Format(PyExc_ValueError,
"Gizmo target property '%s.%s' not found",
- mpr->type->idname, params.target);
+ gz->type->idname, params.target);
goto fail;
}
- const int array_len = WM_gizmo_target_property_array_length(mpr, mpr_prop);
- switch (mpr_prop->type->data_type) {
+ const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
+ switch (gz_prop->type->data_type) {
case PROP_FLOAT:
{
if (array_len != 0) {
float *value = BLI_array_alloca(value, array_len);
- WM_gizmo_target_property_value_get_array(mpr, mpr_prop, value);
+ WM_gizmo_target_property_value_get_array(gz, gz_prop, value);
return PyC_Tuple_PackArray_F32(value, array_len);
}
else {
- float value = WM_gizmo_target_property_value_get(mpr, mpr_prop);
+ float value = WM_gizmo_target_property_value_get(gz, gz_prop);
return PyFloat_FromDouble(value);
}
break;
@@ -429,36 +429,36 @@ static PyObject *bpy_gizmo_target_set_value(PyObject *UNUSED(self), PyObject *ar
goto fail;
}
- wmGizmo *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
- wmGizmoProperty *mpr_prop =
- WM_gizmo_target_property_find(mpr, params.target);
- if (mpr_prop == NULL) {
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
PyErr_Format(PyExc_ValueError,
"Gizmo target property '%s.%s' not found",
- mpr->type->idname, params.target);
+ gz->type->idname, params.target);
goto fail;
}
- const int array_len = WM_gizmo_target_property_array_length(mpr, mpr_prop);
- switch (mpr_prop->type->data_type) {
+ const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
+ switch (gz_prop->type->data_type) {
case PROP_FLOAT:
{
if (array_len != 0) {
float *value = BLI_array_alloca(value, array_len);
- if (PyC_AsArray(value, params.value, mpr_prop->type->array_length, &PyFloat_Type, false,
+ if (PyC_AsArray(value, params.value, gz_prop->type->array_length, &PyFloat_Type, false,
"Gizmo target property array") == -1)
{
goto fail;
}
- WM_gizmo_target_property_value_set_array(BPy_GetContext(), mpr, mpr_prop, value);
+ WM_gizmo_target_property_value_set_array(BPy_GetContext(), gz, gz_prop, value);
}
else {
float value;
if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
goto fail;
}
- WM_gizmo_target_property_value_set(BPy_GetContext(), mpr, mpr_prop, value);
+ WM_gizmo_target_property_value_set(BPy_GetContext(), gz, gz_prop, value);
}
Py_RETURN_NONE;
}
@@ -504,22 +504,22 @@ static PyObject *bpy_gizmo_target_get_range(PyObject *UNUSED(self), PyObject *ar
goto fail;
}
- wmGizmo *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
- wmGizmoProperty *mpr_prop =
- WM_gizmo_target_property_find(mpr, params.target);
- if (mpr_prop == NULL) {
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
PyErr_Format(PyExc_ValueError,
"Gizmo target property '%s.%s' not found",
- mpr->type->idname, params.target);
+ gz->type->idname, params.target);
goto fail;
}
- switch (mpr_prop->type->data_type) {
+ switch (gz_prop->type->data_type) {
case PROP_FLOAT:
{
float range[2];
- WM_gizmo_target_property_range_get(mpr, mpr_prop, range);
+ WM_gizmo_target_property_range_get(gz, gz_prop, range);
return PyC_Tuple_PackArray_F32(range, 2);
}
default:
diff --git a/source/blender/python/intern/gpu_py_matrix.c b/source/blender/python/intern/gpu_py_matrix.c
index 68b08dfb324..2ab6fd864eb 100644
--- a/source/blender/python/intern/gpu_py_matrix.c
+++ b/source/blender/python/intern/gpu_py_matrix.c
@@ -102,7 +102,7 @@ static PyObject *pygpu_matrix_push(PyObject *UNUSED(self))
if (!pygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
- gpuPushMatrix();
+ GPU_matrix_push();
Py_RETURN_NONE;
}
@@ -116,7 +116,7 @@ static PyObject *pygpu_matrix_pop(PyObject *UNUSED(self))
if (!pygpu_stack_is_pop_model_view_ok_or_error()) {
return NULL;
}
- gpuPopMatrix();
+ GPU_matrix_pop();
Py_RETURN_NONE;
}
@@ -130,7 +130,7 @@ static PyObject *pygpu_matrix_push_projection(PyObject *UNUSED(self))
if (!pygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
- gpuPushProjectionMatrix();
+ GPU_matrix_push_projection();
Py_RETURN_NONE;
}
@@ -144,7 +144,7 @@ static PyObject *pygpu_matrix_pop_projection(PyObject *UNUSED(self))
if (!pygpu_stack_is_pop_projection_ok_or_error()) {
return NULL;
}
- gpuPopProjectionMatrix();
+ GPU_matrix_pop_projection();
Py_RETURN_NONE;
}
@@ -197,14 +197,14 @@ static PyObject *pygpu_matrix_stack_context_enter(BPy_GPU_MatrixStackContext *se
if (!pygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
- gpuPushMatrix();
+ GPU_matrix_push();
self->level = GPU_matrix_stack_level_get_model_view();
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
if (!pygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
- gpuPushProjectionMatrix();
+ GPU_matrix_push_projection();
self->level = GPU_matrix_stack_level_get_projection();
}
else {
@@ -227,7 +227,7 @@ static PyObject *pygpu_matrix_stack_context_exit(BPy_GPU_MatrixStackContext *sel
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d\n", self->level, level);
}
if (level != 0) {
- gpuPopMatrix();
+ GPU_matrix_pop();
}
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
@@ -236,7 +236,7 @@ static PyObject *pygpu_matrix_stack_context_exit(BPy_GPU_MatrixStackContext *sel
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d", self->level, level);
}
if (level != 0) {
- gpuPopProjectionMatrix();
+ GPU_matrix_pop_projection();
}
}
else {
@@ -294,7 +294,7 @@ static PyObject *pygpu_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject *
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
- gpuMultMatrix(pymat->matrix);
+ GPU_matrix_mul(pymat->matrix);
Py_RETURN_NONE;
}
@@ -314,10 +314,10 @@ static PyObject *pygpu_matrix_scale(PyObject *UNUSED(self), PyObject *value)
return NULL;
}
if (len == 2) {
- gpuScale2fv(scale);
+ GPU_matrix_scale_2fv(scale);
}
else {
- gpuScale3fv(scale);
+ GPU_matrix_scale_3fv(scale);
}
Py_RETURN_NONE;
}
@@ -337,7 +337,7 @@ static PyObject *pygpu_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *va
Py_TYPE(value)->tp_name);
return NULL;
}
- gpuScaleUniform(scalar);
+ GPU_matrix_scale_1f(scalar);
Py_RETURN_NONE;
}
@@ -357,10 +357,10 @@ static PyObject *pygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value)
return NULL;
}
if (len == 2) {
- gpuTranslate2fv(offset);
+ GPU_matrix_translate_2fv(offset);
}
else {
- gpuTranslate3fv(offset);
+ GPU_matrix_translate_3fv(offset);
}
Py_RETURN_NONE;
}
@@ -378,7 +378,7 @@ PyDoc_STRVAR(pygpu_matrix_reset_doc,
);
static PyObject *pygpu_matrix_reset(PyObject *UNUSED(self))
{
- gpuMatrixReset();
+ GPU_matrix_reset();
Py_RETURN_NONE;
}
@@ -389,7 +389,7 @@ PyDoc_STRVAR(pygpu_matrix_load_identity_doc,
);
static PyObject *pygpu_matrix_load_identity(PyObject *UNUSED(self))
{
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
Py_RETURN_NONE;
}
@@ -407,7 +407,7 @@ static PyObject *pygpu_matrix_load_matrix(PyObject *UNUSED(self), PyObject *valu
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
- gpuLoadMatrix(pymat->matrix);
+ GPU_matrix_set(pymat->matrix);
Py_RETURN_NONE;
}
@@ -428,7 +428,7 @@ PyDoc_STRVAR(pygpu_matrix_get_projection_matrix_doc,
static PyObject *pygpu_matrix_get_projection_matrix(PyObject *UNUSED(self))
{
float matrix[4][4];
- gpuGetModelViewMatrix(matrix);
+ GPU_matrix_model_view_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
}
@@ -444,7 +444,7 @@ PyDoc_STRVAR(pygpu_matrix_get_modal_view_matrix_doc,
static PyObject *pygpu_matrix_get_modal_view_matrix(PyObject *UNUSED(self))
{
float matrix[4][4];
- gpuGetProjectionMatrix(matrix);
+ GPU_matrix_projection_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
}
@@ -459,7 +459,7 @@ PyDoc_STRVAR(pygpu_matrix_get_normal_matrix_doc,
static PyObject *pygpu_matrix_get_normal_matrix(PyObject *UNUSED(self))
{
float matrix[3][3];
- gpuGetNormalMatrix(matrix);
+ GPU_matrix_normal_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 3, 3, NULL);
}
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 70c400f99b8..3bd40cca5c6 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -2321,7 +2321,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
- * multiplication */
+ * element-wise multiplication */
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
@@ -2332,7 +2332,6 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
{
float scalar;
- int vec_size;
MatrixObject *mat1 = NULL, *mat2 = NULL;
@@ -2348,15 +2347,124 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
/* MATRIX * MATRIX */
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+#endif
+ }
+ else if (mat2) {
+ /*FLOAT/INT * MATRIX */
+ if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat2, scalar);
+ }
+ }
+ else if (mat1) {
+ /* MATRIX * FLOAT/INT */
+ if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * Inplace element-wise multiplication */
+static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
+{
+ float scalar;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ /* MATRIX *= MATRIX */
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 *= matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* MATRIX *= FLOAT/INT */
+ mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
+/*------------------------obj @ obj------------------------------
+ * matrix multiplication */
+static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
+{
+ int vec_size;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @ MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+
int col, row, item;
if (mat1->num_col != mat2->num_row) {
PyErr_SetString(PyExc_ValueError,
- "matrix1 * matrix2: matrix1 number of columns "
- "and the matrix2 number of rows must be the same");
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
return NULL;
}
@@ -2372,14 +2480,8 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
- else if (mat2) {
- /*FLOAT/INT * MATRIX */
- if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat2, scalar);
- }
- }
else if (mat1) {
- /* MATRIX * VECTOR */
+ /* MATRIX @ VECTOR */
if (VectorObject_Check(m2)) {
VectorObject *vec2 = (VectorObject *)m2;
float tvec[MATRIX_MAX_DIM];
@@ -2398,20 +2500,69 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
- /*FLOAT/INT * MATRIX */
- else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat1, scalar);
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Matrix multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+}
+/*------------------------obj @= obj------------------------------
+ * inplace matrix multiplication */
+static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
+{
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @= MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ int col, row, item;
+
+ if (mat1->num_col != mat2->num_row) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
+ return NULL;
}
+
+ for (col = 0; col < mat2->num_col; col++) {
+ for (row = 0; row < mat1->num_row; row++) {
+ double dot = 0.0f;
+ for (item = 0; item < mat1->num_col; item++) {
+ dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
+ }
+ /* store in new matrix as overwriting original at this point will cause
+ * subsequent iterations to use incorrect values */
+ mat[(col * mat1->num_row) + row] = (float)dot;
+ }
+ }
+
+ /* copy matrix back */
+ memcpy(mat1->matrix, mat, mat1->num_row * mat1->num_col);
}
else {
- BLI_assert(!"internal error");
+ PyErr_Format(PyExc_TypeError,
+ "Inplace matrix multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
}
- PyErr_Format(PyExc_TypeError,
- "Matrix multiplication: "
- "not supported between '%.200s' and '%.200s' types",
- Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
- return NULL;
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
@@ -2527,7 +2678,7 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Matrix_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -2540,6 +2691,8 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Matrix_translation_doc,
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 1a6fd0ee86f..bb5983af535 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -834,7 +834,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
* multiplication */
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
- float quat[QUAT_SIZE], scalar;
+ float scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if (QuaternionObject_Check(q1)) {
@@ -848,9 +848,12 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return NULL;
}
- if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
- mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ float quat[QUAT_SIZE];
+ mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE);
return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+#endif
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -858,17 +861,96 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return quat_mul_float(quat2, scalar);
}
}
+ else if (quat1) { /* QUAT * FLOAT */
+ if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ return quat_mul_float(quat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * inplace multiplication */
+static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2)
+{
+ float scalar;
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* QUAT *= FLOAT */
+ mul_qt_fl(quat1->quat, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
+/*------------------------obj @ obj------------------------------
+ * quaternion multiplication */
+static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+ }
else if (quat1) {
- /* QUAT * VEC */
+ /* QUAT @ VEC */
if (VectorObject_Check(q2)) {
VectorObject *vec2 = (VectorObject *)q2;
float tvec[3];
if (vec2->size != 3) {
PyErr_SetString(PyExc_ValueError,
- "Vector multiplication: "
- "only 3D vector rotations (with quats) "
- "currently supported");
+ "Vector multiplication: "
+ "only 3D vector rotations (with quats) "
+ "currently supported");
return NULL;
}
if (BaseMath_ReadCallback(vec2) == -1) {
@@ -880,21 +962,48 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
- /* QUAT * FLOAT */
- else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
- return quat_mul_float(quat1, scalar);
- }
- }
- else {
- BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
- "Quaternion multiplication: "
- "not supported between '%.200s' and '%.200s' types",
- Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ "Quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace quaternion multiplication */
+static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ copy_qt_qt(quat1->quat, quat);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
/* -obj
* returns the negative of this object*/
@@ -952,7 +1061,7 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Quaternion_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -965,6 +1074,8 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Quaternion_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Quaternion_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Quaternion_axis_doc,
@@ -1100,7 +1211,8 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
{
PyObject *seq = NULL;
double angle = 0.0f;
- float quat[QUAT_SIZE] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float quat[QUAT_SIZE];
+ unit_qt(quat);
if (kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index a06a63c8067..dc05f463d22 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1127,23 +1127,17 @@ PyDoc_STRVAR(Vector_project_doc,
static PyObject *Vector_project(VectorObject *self, PyObject *value)
{
const int size = self->size;
- float tvec[MAX_DIMENSIONS];
- float vec[MAX_DIMENSIONS];
+ float *tvec;
double dot = 0.0f, dot2 = 0.0f;
int x;
- if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1)
+ if (BaseMath_ReadCallback(self) == -1)
return NULL;
- if (self->size > 4) {
- PyErr_SetString(PyExc_ValueError,
- "Vector must be 2D, 3D or 4D");
+ if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) {
return NULL;
}
- if (BaseMath_ReadCallback(self) == -1)
- return NULL;
-
/* get dot products */
for (x = 0; x < size; x++) {
dot += (double)(self->vec[x] * tvec[x]);
@@ -1152,9 +1146,9 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
/* projection */
dot /= dot2;
for (x = 0; x < size; x++) {
- vec[x] = (float)dot * tvec[x];
+ tvec[x] *= (float)dot;
}
- return Vector_CreatePyObject(vec, size, Py_TYPE(self));
+ return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
@@ -1712,12 +1706,25 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
}
+#ifdef USE_MATHUTILS_ELEM_MUL
+static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
+{
+ float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
+ if (tvec == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "vec * vec: "
+ "problem allocating pointer space");
+ return NULL;
+ }
+ mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
+ return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
+}
+#endif
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- int vec_size;
if (VectorObject_Check(v1)) {
vec1 = (VectorObject *)v1;
@@ -1735,6 +1742,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* make sure v1 is always the vector */
if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
if (vec1->size != vec2->size) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
@@ -1742,30 +1750,12 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return NULL;
}
- /*dot product*/
- return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ /* element-wise product */
+ return vector_mul_vec(vec1, vec2);
+#endif
}
else if (vec1) {
- if (MatrixObject_Check(v2)) {
- /* VEC * MATRIX */
- float tvec[MAX_DIMENSIONS];
-
- if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
- return NULL;
- if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
- return NULL;
- }
-
- if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
- vec_size = 3;
- }
- else {
- vec_size = ((MatrixObject *)v2)->num_col;
- }
-
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
- }
- else if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
+ if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
return vector_mul_float(vec1, scalar);
}
}
@@ -1774,12 +1764,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return vector_mul_float(vec2, scalar);
}
}
- else {
- BLI_assert(!"internal error");
- }
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: "
+ "Element-wise multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
@@ -1788,32 +1775,129 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* multiplication in-place: obj *= obj */
static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
{
- VectorObject *vec = (VectorObject *)v1;
+ VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if (BaseMath_ReadCallback_ForWrite(vec) == -1)
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1)
return NULL;
/* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
- /* only support 'vec *= float'
- * vec*=vec result is a float so that wont work */
- if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC *= FLOAT */
- mul_vn_fl(vec->vec, vec->size, scalar);
+ if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /* element-wise product inplace */
+ mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */
+ mul_vn_fl(vec1->vec, vec1->size, scalar);
}
else {
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: (%s *= %s) "
- "invalid type for this operation",
- Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
- (void)BaseMath_WriteCallback(vec);
+ (void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
+static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
+{
+ VectorObject *vec1 = NULL, *vec2 = NULL;
+ int vec_size;
+
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+
+ /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
+
+ /* make sure v1 is always the vector */
+ if (vec1 && vec2) {
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /*dot product*/
+ return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ }
+ else if (vec1) {
+ if (MatrixObject_Check(v2)) {
+ /* VEC @ MATRIX */
+ float tvec[MAX_DIMENSIONS];
+
+ if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
+ return NULL;
+ if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
+ return NULL;
+ }
+
+ if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
+ vec_size = 3;
+ }
+ else {
+ vec_size = ((MatrixObject *)v2)->num_col;
+ }
+
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
+static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
+{
+ PyErr_Format(PyExc_TypeError,
+ "Inplace vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
/* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
@@ -2125,6 +2209,8 @@ static PyNumberMethods Vector_NumMethods = {
NULL, /* nb_inplace_floor_divide */
Vector_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Vector_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */
};
/*------------------PY_OBECT DEFINITION--------------------------*/
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index d3fef51e9e9..8f921d7850a 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../nodes
../physics
../draw
+ ../gpu
../../../intern/atomic
../../../intern/guardedalloc
../../../intern/mikktspace
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index cb32efb0b0f..df8953857ee 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -315,7 +315,7 @@ void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void
void RE_gl_context_create(Render *re);
void RE_gl_context_destroy(Render *re);
void *RE_gl_context_get(Render *re);
-void *RE_gwn_context_get(Render *re);
+void *RE_gpu_context_get(Render *re);
/* should move to kernel once... still unsure on how/where */
float RE_filter_value(int type, float x);
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 3096949b49f..ab7eee128f0 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -123,7 +123,7 @@ bool render_result_has_views(struct RenderResult *rr);
iter_ != NULL; \
iter_ = iter_->next, nr_++) \
{ \
- if ((re_)->r.scemode & R_SINGLE_LAYER) { \
+ if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \
if (nr_ != re->active_view_layer) { \
continue; \
} \
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 117b82570e7..5d5d12f028a 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -160,7 +160,7 @@ struct Render {
/* TODO replace by a whole draw manager. */
void *gl_context;
- void *gwn_context;
+ void *gpu_context;
};
/* **************** defines ********************* */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 5c3f510ffca..09ab3e39d5f 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -739,7 +739,16 @@ int RE_engine_render(Render *re, int do_all)
type->render(engine, engine->depsgraph);
+ /* grease pencil render over previous render result */
+ if (!RE_engine_test_break(engine)) {
+ DRW_render_gpencil(engine, engine->depsgraph);
+ }
+
engine_depsgraph_free(engine);
+
+ if (RE_engine_test_break(engine)) {
+ break;
+ }
}
FOREACH_VIEW_LAYER_TO_RENDER_END;
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 82595527d30..510a4aa4685 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -97,7 +97,7 @@
#include "../../../windowmanager/WM_api.h" /* XXX */
#include "../../../windowmanager/wm_window.h" /* XXX */
-#include "../../../intern/gawain/gawain/gwn_context.h"
+#include "GPU_context.h"
#ifdef WITH_FREESTYLE
# include "FRS_freestyle.h"
@@ -1043,10 +1043,10 @@ void RE_gl_context_create(Render *re)
void RE_gl_context_destroy(Render *re)
{
/* Needs to be called from the thread which used the ogl context for rendering. */
- if (re->gwn_context) {
- GWN_context_active_set(re->gwn_context);
- GWN_context_discard(re->gwn_context);
- re->gwn_context = NULL;
+ if (re->gpu_context) {
+ GPU_context_active_set(re->gpu_context);
+ GPU_context_discard(re->gpu_context);
+ re->gpu_context = NULL;
}
if (re->gl_context) {
WM_opengl_context_dispose(re->gl_context);
@@ -1059,12 +1059,12 @@ void *RE_gl_context_get(Render *re)
return re->gl_context;
}
-void *RE_gwn_context_get(Render *re)
+void *RE_gpu_context_get(Render *re)
{
- if (re->gwn_context == NULL) {
- re->gwn_context = GWN_context_create();
+ if (re->gpu_context == NULL) {
+ re->gpu_context = GPU_context_create();
}
- return re->gwn_context;
+ return re->gpu_context;
}
/* ********* add object data (later) ******** */
diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt
new file mode 100644
index 00000000000..dacc0b3f063
--- /dev/null
+++ b/source/blender/shader_fx/CMakeLists.txt
@@ -0,0 +1,64 @@
+# ***** 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) 2018, Blender Foundation
+# All rights reserved.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+ ../blenkernel
+ ../blenlib
+ ../blenfont
+ ../depsgraph
+ ../makesdna
+ ../makesrna
+ ../bmesh
+ ../render/extern/include
+ ../../../intern/elbeem/extern
+ ../../../intern/guardedalloc
+ ../../../intern/eigen
+)
+
+set(INC_SYS
+ ${ZLIB_INCLUDE_DIRS}
+)
+
+set(SRC
+ intern/FX_shader_util.h
+
+ intern/FX_shader_util.c
+ intern/FX_shader_blur.c
+ intern/FX_shader_colorize.c
+ intern/FX_shader_flip.c
+ intern/FX_shader_light.c
+ intern/FX_shader_pixel.c
+ intern/FX_shader_rim.c
+ intern/FX_shader_swirl.c
+ intern/FX_shader_wave.c
+
+ FX_shader_types.h
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_shader_fx "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/shader_fx/FX_shader_types.h b/source/blender/shader_fx/FX_shader_types.h
new file mode 100644
index 00000000000..b8d8f04e07f
--- /dev/null
+++ b/source/blender/shader_fx/FX_shader_types.h
@@ -0,0 +1,47 @@
+/*
+ * ***** 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): Ben Batt
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file FX_shader_types.h
+ * \ingroup shader_fx
+ */
+
+#ifndef __FX_SHADER_TYPES_H__
+#define __FX_SHADER_TYPES_H__
+
+#include "BKE_shader_fx.h"
+
+/* ****************** Type structures for all effects ****************** */
+
+extern ShaderFxTypeInfo shaderfx_Type_None;
+extern ShaderFxTypeInfo shaderfx_Type_Blur;
+extern ShaderFxTypeInfo shaderfx_Type_Colorize;
+extern ShaderFxTypeInfo shaderfx_Type_Flip;
+extern ShaderFxTypeInfo shaderfx_Type_Light;
+extern ShaderFxTypeInfo shaderfx_Type_Pixel;
+extern ShaderFxTypeInfo shaderfx_Type_Rim;
+extern ShaderFxTypeInfo shaderfx_Type_Swirl;
+extern ShaderFxTypeInfo shaderfx_Type_Wave;
+
+/* FX_shaderfx_util.c */
+void shaderfx_type_init(ShaderFxTypeInfo *types[]);
+
+#endif /* __FX_SHADER_TYPES_H__ */
diff --git a/source/blender/shader_fx/intern/FX_shader_blur.c b/source/blender/shader_fx/intern/FX_shader_blur.c
new file mode 100644
index 00000000000..128ebba8875
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_blur.c
@@ -0,0 +1,66 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_blur.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ BlurShaderFxData *gpfx = (BlurShaderFxData *)fx;
+ ARRAY_SET_ITEMS(gpfx->radius, 1, 1);
+ gpfx->samples = 4;
+ gpfx->coc = 0.025f;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Blur = {
+ /* name */ "Blur",
+ /* structName */ "BlurShaderFxData",
+ /* structSize */ sizeof(BlurShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ eShaderFxTypeFlag_Single,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_colorize.c b/source/blender/shader_fx/intern/FX_shader_colorize.c
new file mode 100644
index 00000000000..edf276b842c
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_colorize.c
@@ -0,0 +1,69 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_colorize.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_shader_fx_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ ColorizeShaderFxData *gpfx = (ColorizeShaderFxData *)fx;
+ ARRAY_SET_ITEMS(gpfx->low_color, 0.0f, 0.0f, 0.0f, 1.0f);
+ ARRAY_SET_ITEMS(gpfx->high_color, 1.0f, 1.0f, 1.0f, 1.0f);
+ gpfx->mode = eShaderFxColorizeMode_GrayScale;
+ gpfx->factor = 0.5f;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Colorize = {
+ /* name */ "Colorize",
+ /* structName */ "ColorizeShaderFxData",
+ /* structSize */ sizeof(ColorizeShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c
new file mode 100644
index 00000000000..404e2f8160e
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_flip.c
@@ -0,0 +1,69 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_flip.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ FlipShaderFxData *gpfx = (FlipShaderFxData *)fx;
+ gpfx->flag |= FX_FLIP_HORIZONTAL;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Flip = {
+ /* name */ "Flip",
+ /* structName */ "FlipShaderFxData",
+ /* structSize */ sizeof(FlipShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ eShaderFxTypeFlag_Single,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_light.c b/source/blender/shader_fx/intern/FX_shader_light.c
new file mode 100644
index 00000000000..9a17ea8ae5f
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_light.c
@@ -0,0 +1,104 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_light.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_shader_fx.h"
+
+#include "FX_shader_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+static void initData(ShaderFxData *fx)
+{
+ LightShaderFxData *gpfx = (LightShaderFxData *)fx;
+ gpfx->energy = 10.0f;
+ gpfx->ambient = 5.0f;
+ gpfx->object = NULL;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+static void updateDepsgraph(ShaderFxData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ LightShaderFxData *fxd = (LightShaderFxData *)md;
+ if (fxd->object != NULL) {
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_GEOMETRY, "Light ShaderFx");
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_TRANSFORM, "Light ShaderFx");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Light ShaderFx");
+}
+
+static bool isDisabled(ShaderFxData *fx, int UNUSED(userRenderParams))
+{
+ LightShaderFxData *fxd = (LightShaderFxData *)fx;
+
+ return !fxd->object;
+}
+
+static void foreachObjectLink(
+ ShaderFxData *fx, Object *ob,
+ ShaderFxObjectWalkFunc walk, void *userData)
+{
+ LightShaderFxData *fxd = (LightShaderFxData *)fx;
+
+ walk(userData, ob, &fxd->object, IDWALK_CB_NOP);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Light = {
+ /* name */ "Light",
+ /* structName */ "LightShaderFxData",
+ /* structSize */ sizeof(LightShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_pixel.c b/source/blender/shader_fx/intern/FX_shader_pixel.c
new file mode 100644
index 00000000000..a3ffd3a9b0d
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_pixel.c
@@ -0,0 +1,66 @@
+/*
+ * ***** 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
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_pixel.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ PixelShaderFxData *gpfx = (PixelShaderFxData *)fx;
+ ARRAY_SET_ITEMS(gpfx->size, 5, 5);
+ ARRAY_SET_ITEMS(gpfx->rgba, 0.0f, 0.0f, 0.0f, 0.9f);
+ gpfx->flag |= FX_PIXEL_USE_LINES;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Pixel = {
+ /* name */ "Pixelate",
+ /* structName */ "PixelShaderFxData",
+ /* structSize */ sizeof(PixelShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ eShaderFxTypeFlag_Single,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_rim.c b/source/blender/shader_fx/intern/FX_shader_rim.c
new file mode 100644
index 00000000000..bea6f645033
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_rim.c
@@ -0,0 +1,70 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_rim.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_shader_fx_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ RimShaderFxData *gpfx = (RimShaderFxData *)fx;
+ ARRAY_SET_ITEMS(gpfx->offset, 50, -100);
+ ARRAY_SET_ITEMS(gpfx->rim_rgb, 1.0f, 1.0f, 0.5f);
+ ARRAY_SET_ITEMS(gpfx->mask_rgb, 0.0f, 0.0f, 0.0f);
+ gpfx->mode = eShaderFxRimMode_Multiply;
+ ARRAY_SET_ITEMS(gpfx->blur, 0, 0);
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Rim = {
+ /* name */ "Rim",
+ /* structName */ "RimShaderFxData",
+ /* structSize */ sizeof(RimShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_swirl.c b/source/blender/shader_fx/intern/FX_shader_swirl.c
new file mode 100644
index 00000000000..9667f466eec
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_swirl.c
@@ -0,0 +1,103 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_swirl.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_shader_fx.h"
+
+#include "FX_shader_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+static void initData(ShaderFxData *md)
+{
+ SwirlShaderFxData *gpmd = (SwirlShaderFxData *)md;
+ gpmd->radius = 100;
+ gpmd->angle = M_PI_2;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx)
+{
+ SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
+ if (fxd->object != NULL) {
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_GEOMETRY, "Swirl ShaderFx");
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_TRANSFORM, "Swirl ShaderFx");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Swirl ShaderFx");
+}
+
+static bool isDisabled(ShaderFxData *fx, int UNUSED(userRenderParams))
+{
+ SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
+
+ return !fxd->object;
+}
+
+static void foreachObjectLink(
+ ShaderFxData *fx, Object *ob,
+ ShaderFxObjectWalkFunc walk, void *userData)
+{
+ SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
+
+ walk(userData, ob, &fxd->object, IDWALK_CB_NOP);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Swirl = {
+ /* name */ "Swirl",
+ /* structName */ "SwirlShaderFxData",
+ /* structSize */ sizeof(SwirlShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_util.c b/source/blender/shader_fx/intern/FX_shader_util.c
new file mode 100644
index 00000000000..64a1553adec
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_util.c
@@ -0,0 +1,55 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_util.c
+ * \ingroup shader_fx
+ */
+
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_shader_fx.h"
+
+#include "FX_shader_types.h"
+#include "FX_shader_util.h"
+
+void shaderfx_type_init(ShaderFxTypeInfo *types[])
+{
+#define INIT_FX_TYPE(typeName) (types[eShaderFxType_##typeName] = &shaderfx_Type_##typeName)
+ INIT_FX_TYPE(Blur);
+ INIT_FX_TYPE(Colorize);
+ INIT_FX_TYPE(Flip);
+ INIT_FX_TYPE(Light);
+ INIT_FX_TYPE(Pixel);
+ INIT_FX_TYPE(Rim);
+ INIT_FX_TYPE(Swirl);
+ INIT_FX_TYPE(Wave);
+#undef INIT_FX_TYPE
+}
diff --git a/source/blender/blenloader/BLO_runtime.h b/source/blender/shader_fx/intern/FX_shader_util.h
index 09f25bdca53..e2fdcd6fb4c 100644
--- a/source/blender/blenloader/BLO_runtime.h
+++ b/source/blender/shader_fx/intern/FX_shader_util.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.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -23,31 +23,14 @@
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
- *
*/
-#ifndef __BLO_RUNTIME_H__
-#define __BLO_RUNTIME_H__
-
-/** \file BLO_runtime.h
- * \ingroup blenloader
+/** \file blender/shader_fx/intern/FX_shader_util.h
+ * \ingroup shader_fx
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct BlendFileData;
-struct Main;
-struct ReportList;
-
-int BLO_is_a_runtime(const char *file);
-struct BlendFileData *BLO_read_runtime(const char *file, struct ReportList *reports);
-
-bool BLO_main_validate_libraries(struct Main *bmain, struct ReportList *reports);
-#ifdef __cplusplus
-}
-#endif
+#ifndef __FX_SHADER_UTIL_H__
+#define __FX_SHADER_UTIL_H__
-#endif /* __BLO_RUNTIME_H__ */
+#endif /* __FX_SHADER_UTIL_H__ */
diff --git a/source/blender/shader_fx/intern/FX_shader_wave.c b/source/blender/shader_fx/intern/FX_shader_wave.c
new file mode 100644
index 00000000000..ea4563a00e1
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_wave.c
@@ -0,0 +1,71 @@
+/*
+ * ***** 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) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_wave.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "FX_shader_types.h"
+
+static void initData(ShaderFxData *fx)
+{
+ WaveShaderFxData *gpfx = (WaveShaderFxData *)fx;
+ gpfx->amplitude = 10.0f;
+ gpfx->period = 20.0f;
+ gpfx->phase = 0.0f;
+ gpfx->orientation = 1;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Wave = {
+ /* name */ "Wave Distorsion",
+ /* structName */ "WaveShaderFxData",
+ /* structSize */ sizeof(WaveShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ eShaderFxTypeFlag_Single,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 67ca5f8a08a..b15ce2d11ad 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -485,10 +485,16 @@ void WM_drag_free(struct wmDrag *drag);
void WM_drag_free_list(struct ListBase *lb);
struct wmDropBox *WM_dropbox_add(
- ListBase *lb, const char *idname, bool (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
+ ListBase *lb, const char *idname,
+ bool (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event, const char **),
void (*copy)(struct wmDrag *, struct wmDropBox *));
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
+ /* ID drag and drop */
+void WM_drag_add_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent);
+struct ID *WM_drag_ID(const struct wmDrag *drag, short idcode);
+struct ID *WM_drag_ID_from_event(const struct wmEvent *event, short idcode);
+
/* Set OpenGL viewport and scissor */
void wmViewport(const struct rcti *rect);
void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 547028c88f9..2e84140707d 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -70,6 +70,10 @@ wmKeyMapItem *WM_keymap_add_panel(struct wmKeyMap *keymap, const char *idname, i
wmKeyMapItem *WM_keymap_add_tool(struct wmKeyMap *keymap, const char *idname, int type,
int val, int modifier, int keymodifier);
+void WM_keymap_add_context_enum_set_items(
+ wmKeyMap *keymap, const struct EnumPropertyItem *items, const char *data_path,
+ int type_start, int val, int modifier, int keymodifier);
+
bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
int WM_keymap_item_to_string(wmKeyMapItem *kmi, const bool compact, char *result, const int result_len);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index a5536dbd652..4882741680a 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -111,6 +111,7 @@ struct wmEvent;
struct wmWindowManager;
struct wmMsgBus;
struct wmOperator;
+struct ID;
struct ImBuf;
#include "RNA_types.h"
@@ -145,6 +146,7 @@ enum {
OPTYPE_LOCK_BYPASS = (1 << 7), /* Allow operator to run when interface is locked */
OPTYPE_UNDO_GROUPED = (1 << 8), /* Special type of undo which doesn't store itself multiple times */
+ OPTYPE_USE_EVAL_DATA = (1 << 9), /* Need evaluated data (i.e. a valid, up-to-date depsgraph for current context) */
};
/* context to call operator in for WM_operator_name_call */
@@ -585,6 +587,12 @@ typedef struct wmOperatorType {
* that the operator might still fail to execute even if this return true */
bool (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT;
+ /* Use to check of properties should be displayed in auto-generated UI.
+ * Use 'check' callback to enforce refreshing. */
+ bool (*poll_property)(
+ const struct bContext *C, struct wmOperator *op,
+ const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT;
+
/* optional panel for redo and repeat, autogenerated if not set */
void (*ui)(struct bContext *, struct wmOperator *);
@@ -653,6 +661,12 @@ typedef enum wmDragFlags {
/* note: structs need not exported? */
+typedef struct wmDragID {
+ struct wmDragID *next, *prev;
+ struct ID *id;
+ struct ID *from_parent;
+} wmDragID;
+
typedef struct wmDrag {
struct wmDrag *next, *prev;
@@ -667,6 +681,8 @@ typedef struct wmDrag {
char opname[200]; /* if set, draws operator name*/
unsigned int flags;
+
+ ListBase ids; /* List of wmDragIDs, all are guaranteed to have the same ID type. */
} wmDrag;
/* dropboxes are like keymaps, part of the screen/area/region definition */
@@ -675,7 +691,7 @@ typedef struct wmDropBox {
struct wmDropBox *next, *prev;
/* test if the dropbox is active, then can print optype name */
- bool (*poll)(struct bContext *, struct wmDrag *, const wmEvent *);
+ bool (*poll)(struct bContext *, struct wmDrag *, const wmEvent *, const char **);
/* before exec, this copies drag info to wmDrop properties */
void (*copy)(struct wmDrag *, struct wmDropBox *);
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
index a93597d4f64..dd39cc96d6f 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
@@ -60,57 +60,57 @@ struct wmMsgSubscribeValue;
/* wmGizmo */
struct wmGizmo *WM_gizmo_new_ptr(
- const struct wmGizmoType *wt, struct wmGizmoGroup *mgroup,
+ const struct wmGizmoType *gzt, struct wmGizmoGroup *gzgroup,
struct PointerRNA *properties);
struct wmGizmo *WM_gizmo_new(
- const char *idname, struct wmGizmoGroup *mgroup,
+ const char *idname, struct wmGizmoGroup *gzgroup,
struct PointerRNA *properties);
-void WM_gizmo_free(struct wmGizmo *mpr);
+void WM_gizmo_free(struct wmGizmo *gz);
void WM_gizmo_unlink(
- ListBase *gizmolist, struct wmGizmoMap *mmap, struct wmGizmo *mpr,
+ ListBase *gizmolist, struct wmGizmoMap *gzmap, struct wmGizmo *gz,
struct bContext *C);
-void WM_gizmo_name_set(struct wmGizmoGroup *mgroup, struct wmGizmo *mpr, const char *name);
+void WM_gizmo_name_set(struct wmGizmoGroup *gzgroup, struct wmGizmo *gz, const char *name);
-bool WM_gizmo_select_unlink(struct wmGizmoMap *mmap, struct wmGizmo *mpr);
-bool WM_gizmo_select_set(struct wmGizmoMap *mmap, struct wmGizmo *mpr, bool select);
-void WM_gizmo_highlight_set(struct wmGizmoMap *mmap, struct wmGizmo *mpr);
+bool WM_gizmo_select_unlink(struct wmGizmoMap *gzmap, struct wmGizmo *gz);
+bool WM_gizmo_select_set(struct wmGizmoMap *gzmap, struct wmGizmo *gz, bool select);
+void WM_gizmo_highlight_set(struct wmGizmoMap *gzmap, struct wmGizmo *gz);
void WM_gizmo_modal_set_from_setup(
- struct wmGizmoMap *mmap, struct bContext *C,
- struct wmGizmo *mpr, int part_index, const struct wmEvent *event);
+ struct wmGizmoMap *gzmap, struct bContext *C,
+ struct wmGizmo *gz, int part_index, const struct wmEvent *event);
struct wmGizmoOpElem *WM_gizmo_operator_get(
- struct wmGizmo *mpr, int part_index);
+ struct wmGizmo *gz, int part_index);
struct PointerRNA *WM_gizmo_operator_set(
- struct wmGizmo *mpr, int part_index,
+ struct wmGizmo *gz, int part_index,
struct wmOperatorType *ot, struct IDProperty *properties);
/* callbacks */
-void WM_gizmo_set_fn_custom_modal(struct wmGizmo *mpr, wmGizmoFnModal fn);
+void WM_gizmo_set_fn_custom_modal(struct wmGizmo *gz, wmGizmoFnModal fn);
void WM_gizmo_set_matrix_location(
- struct wmGizmo *mpr, const float origin[3]);
+ struct wmGizmo *gz, const float origin[3]);
void WM_gizmo_set_matrix_rotation_from_z_axis(
- struct wmGizmo *mpr, const float z_axis[3]);
+ struct wmGizmo *gz, const float z_axis[3]);
void WM_gizmo_set_matrix_rotation_from_yz_axis(
- struct wmGizmo *mpr, const float y_axis[3], const float z_axis[3]);
+ struct wmGizmo *gz, const float y_axis[3], const float z_axis[3]);
void WM_gizmo_set_matrix_offset_location(
- struct wmGizmo *mpr, const float origin[3]);
+ struct wmGizmo *gz, const float origin[3]);
void WM_gizmo_set_matrix_offset_rotation_from_z_axis(
- struct wmGizmo *mpr, const float z_axis[3]);
+ struct wmGizmo *gz, const float z_axis[3]);
void WM_gizmo_set_matrix_offset_rotation_from_yz_axis(
- struct wmGizmo *mpr, const float y_axis[3], const float z_axis[3]);
+ struct wmGizmo *gz, const float y_axis[3], const float z_axis[3]);
-void WM_gizmo_set_flag(struct wmGizmo *mpr, const int flag, const bool enable);
-void WM_gizmo_set_scale(struct wmGizmo *mpr, float scale);
-void WM_gizmo_set_line_width(struct wmGizmo *mpr, const float line_width);
+void WM_gizmo_set_flag(struct wmGizmo *gz, const int flag, const bool enable);
+void WM_gizmo_set_scale(struct wmGizmo *gz, const float scale);
+void WM_gizmo_set_line_width(struct wmGizmo *gz, const float line_width);
-void WM_gizmo_get_color(const struct wmGizmo *mpr, float color[4]);
-void WM_gizmo_set_color(struct wmGizmo *mpr, const float color[4]);
-void WM_gizmo_get_color_highlight(const struct wmGizmo *mpr, float color_hi[4]);
-void WM_gizmo_set_color_highlight(struct wmGizmo *mpr, const float color[4]);
+void WM_gizmo_get_color(const struct wmGizmo *gz, float color[4]);
+void WM_gizmo_set_color(struct wmGizmo *gz, const float color[4]);
+void WM_gizmo_get_color_highlight(const struct wmGizmo *gz, float color_hi[4]);
+void WM_gizmo_set_color_highlight(struct wmGizmo *gz, const float color[4]);
/**
* Leaving values NULL use values from #wmGizmo.
@@ -123,16 +123,16 @@ struct WM_GizmoMatrixParams {
};
void WM_gizmo_calc_matrix_final_params(
- const struct wmGizmo *mpr, const struct WM_GizmoMatrixParams *params,
+ const struct wmGizmo *gz, const struct WM_GizmoMatrixParams *params,
float r_mat[4][4]);
void WM_gizmo_calc_matrix_final_no_offset(
- const struct wmGizmo *mpr, float r_mat[4][4]);
+ const struct wmGizmo *gz, float r_mat[4][4]);
void WM_gizmo_calc_matrix_final(
- const struct wmGizmo *mpr, float r_mat[4][4]);
+ const struct wmGizmo *gz, float r_mat[4][4]);
/* properties */
-void WM_gizmo_properties_create_ptr(struct PointerRNA *ptr, struct wmGizmoType *wt);
+void WM_gizmo_properties_create_ptr(struct PointerRNA *ptr, struct wmGizmoType *gzt);
void WM_gizmo_properties_create(struct PointerRNA *ptr, const char *opstring);
void WM_gizmo_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *wtstring);
void WM_gizmo_properties_sanitize(struct PointerRNA *ptr, const bool no_context);
@@ -147,7 +147,7 @@ const struct wmGizmoType *WM_gizmotype_find(const char *idname, bool quiet);
void WM_gizmotype_append(void (*wtfunc)(struct wmGizmoType *));
void WM_gizmotype_append_ptr(void (*mnpfunc)(struct wmGizmoType *, void *), void *userdata);
bool WM_gizmotype_remove(struct bContext *C, struct Main *bmain, const char *idname);
-void WM_gizmotype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmGizmoType *wt);
+void WM_gizmotype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmGizmoType *gzt);
void WM_gizmotype_iter(struct GHashIterator *ghi);
/* wm_gizmo_group_type.c */
@@ -159,111 +159,111 @@ void WM_gizmogrouptype_free_ptr(struct wmGizmoGroupType *wt);
void WM_gizmogrouptype_iter(struct GHashIterator *ghi);
struct wmGizmoGroupTypeRef *WM_gizmogrouptype_append_and_link(
- struct wmGizmoMapType *mmap_type,
+ struct wmGizmoMapType *gzmap_type,
void (*wtfunc)(struct wmGizmoGroupType *));
/* wm_gizmo_map.c */
/* Dynamic Updates (for RNA runtime registration) */
-void WM_gizmoconfig_update_tag_init(struct wmGizmoMapType *mmap_type, struct wmGizmoGroupType *wgt);
-void WM_gizmoconfig_update_tag_remove(struct wmGizmoMapType *mmap_type, struct wmGizmoGroupType *wgt);
+void WM_gizmoconfig_update_tag_init(struct wmGizmoMapType *gzmap_type, struct wmGizmoGroupType *gzgt);
+void WM_gizmoconfig_update_tag_remove(struct wmGizmoMapType *gzmap_type, struct wmGizmoGroupType *gzgt);
void WM_gizmoconfig_update(struct Main *bmain);
/* wm_maniulator_target_props.c */
-struct wmGizmoProperty *WM_gizmo_target_property_array(struct wmGizmo *mpr);
+struct wmGizmoProperty *WM_gizmo_target_property_array(struct wmGizmo *gz);
struct wmGizmoProperty *WM_gizmo_target_property_at_index(
- struct wmGizmo *mpr, int index);
+ struct wmGizmo *gz, int index);
struct wmGizmoProperty *WM_gizmo_target_property_find(
- struct wmGizmo *mpr, const char *idname);
+ struct wmGizmo *gz, const char *idname);
void WM_gizmo_target_property_def_rna_ptr(
- struct wmGizmo *mpr, const struct wmGizmoPropertyType *mpr_prop_type,
+ struct wmGizmo *gz, const struct wmGizmoPropertyType *gz_prop_type,
struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
void WM_gizmo_target_property_def_rna(
- struct wmGizmo *mpr, const char *idname,
+ struct wmGizmo *gz, const char *idname,
struct PointerRNA *ptr, const char *propname, int index);
void WM_gizmo_target_property_def_func_ptr(
- struct wmGizmo *mpr, const struct wmGizmoPropertyType *mpr_prop_type,
+ struct wmGizmo *gz, const struct wmGizmoPropertyType *gz_prop_type,
const struct wmGizmoPropertyFnParams *params);
void WM_gizmo_target_property_def_func(
- struct wmGizmo *mpr, const char *idname,
+ struct wmGizmo *gz, const char *idname,
const struct wmGizmoPropertyFnParams *params);
void WM_gizmo_target_property_clear_rna_ptr(
- struct wmGizmo *mpr, const struct wmGizmoPropertyType *mpr_prop_type);
+ struct wmGizmo *gz, const struct wmGizmoPropertyType *gz_prop_type);
void WM_gizmo_target_property_clear_rna(
- struct wmGizmo *mpr, const char *idname);
+ struct wmGizmo *gz, const char *idname);
-bool WM_gizmo_target_property_is_valid_any(struct wmGizmo *mpr);
+bool WM_gizmo_target_property_is_valid_any(struct wmGizmo *gz);
bool WM_gizmo_target_property_is_valid(
- const struct wmGizmoProperty *mpr_prop);
+ const struct wmGizmoProperty *gz_prop);
float WM_gizmo_target_property_value_get(
- const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop);
+ const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop);
void WM_gizmo_target_property_value_set(
- struct bContext *C, const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop,
+ struct bContext *C, const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop,
const float value);
void WM_gizmo_target_property_value_get_array(
- const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop,
+ const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop,
float *value);
void WM_gizmo_target_property_value_set_array(
- struct bContext *C, const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop,
+ struct bContext *C, const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop,
const float *value);
bool WM_gizmo_target_property_range_get(
- const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop,
+ const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop,
float range[2]);
int WM_gizmo_target_property_array_length(
- const struct wmGizmo *mpr, struct wmGizmoProperty *mpr_prop);
+ const struct wmGizmo *gz, struct wmGizmoProperty *gz_prop);
/* definitions */
const struct wmGizmoPropertyType *WM_gizmotype_target_property_find(
- const struct wmGizmoType *wt, const char *idname);
+ const struct wmGizmoType *gzt, const char *idname);
void WM_gizmotype_target_property_def(
- struct wmGizmoType *wt, const char *idname, int data_type, int array_length);
+ struct wmGizmoType *gzt, const char *idname, int data_type, int array_length);
/* utilities */
void WM_gizmo_do_msg_notify_tag_refresh(
struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
void WM_gizmo_target_property_subscribe_all(
- struct wmGizmo *mpr, struct wmMsgBus *mbus, struct ARegion *ar);
+ struct wmGizmo *gz, struct wmMsgBus *mbus, struct ARegion *ar);
/* -------------------------------------------------------------------- */
/* wmGizmoGroup */
/* Callbacks for 'wmGizmoGroupType.setup_keymap' */
struct wmKeyMap *WM_gizmogroup_keymap_common(
- const struct wmGizmoGroupType *wgt, struct wmKeyConfig *config);
+ const struct wmGizmoGroupType *gzgt, struct wmKeyConfig *config);
struct wmKeyMap *WM_gizmogroup_keymap_common_select(
- const struct wmGizmoGroupType *wgt, struct wmKeyConfig *config);
+ const struct wmGizmoGroupType *gzgt, struct wmKeyConfig *config);
/* -------------------------------------------------------------------- */
/* wmGizmoMap */
struct wmGizmoMap *WM_gizmomap_new_from_type(
- const struct wmGizmoMapType_Params *mmap_params);
-const struct ListBase *WM_gizmomap_group_list(struct wmGizmoMap *mmap);
+ const struct wmGizmoMapType_Params *gzmap_params);
+const struct ListBase *WM_gizmomap_group_list(struct wmGizmoMap *gzmap);
struct wmGizmoGroup *WM_gizmomap_group_find(
- struct wmGizmoMap *mmap,
+ struct wmGizmoMap *gzmap,
const char *idname);
struct wmGizmoGroup *WM_gizmomap_group_find_ptr(
- struct wmGizmoMap *mmap,
- const struct wmGizmoGroupType *wgt);
-void WM_gizmomap_tag_refresh(struct wmGizmoMap *mmap);
+ struct wmGizmoMap *gzmap,
+ const struct wmGizmoGroupType *gzgt);
+void WM_gizmomap_tag_refresh(struct wmGizmoMap *gzmap);
void WM_gizmomap_draw(
- struct wmGizmoMap *mmap, const struct bContext *C, const eWM_GizmoFlagMapDrawStep drawstep);
-void WM_gizmomap_add_handlers(struct ARegion *ar, struct wmGizmoMap *mmap);
-bool WM_gizmomap_select_all(struct bContext *C, struct wmGizmoMap *mmap, const int action);
-bool WM_gizmomap_cursor_set(const struct wmGizmoMap *mmap, struct wmWindow *win);
+ struct wmGizmoMap *gzmap, const struct bContext *C, const eWM_GizmoFlagMapDrawStep drawstep);
+void WM_gizmomap_add_handlers(struct ARegion *ar, struct wmGizmoMap *gzmap);
+bool WM_gizmomap_select_all(struct bContext *C, struct wmGizmoMap *gzmap, const int action);
+bool WM_gizmomap_cursor_set(const struct wmGizmoMap *gzmap, struct wmWindow *win);
void WM_gizmomap_message_subscribe(
- struct bContext *C, struct wmGizmoMap *mmap, struct ARegion *ar, struct wmMsgBus *mbus);
-bool WM_gizmomap_is_any_selected(const struct wmGizmoMap *mmap);
+ struct bContext *C, struct wmGizmoMap *gzmap, struct ARegion *ar, struct wmMsgBus *mbus);
+bool WM_gizmomap_is_any_selected(const struct wmGizmoMap *gzmap);
bool WM_gizmomap_minmax(
- const struct wmGizmoMap *mmap, bool use_hidden, bool use_select,
+ const struct wmGizmoMap *gzmap, bool use_hidden, bool use_select,
float r_min[3], float r_max[3]);
struct ARegion *WM_gizmomap_tooltip_init(
@@ -273,34 +273,34 @@ struct ARegion *WM_gizmomap_tooltip_init(
/* wmGizmoMapType */
struct wmGizmoMapType *WM_gizmomaptype_find(
- const struct wmGizmoMapType_Params *mmap_params);
+ const struct wmGizmoMapType_Params *gzmap_params);
struct wmGizmoMapType *WM_gizmomaptype_ensure(
- const struct wmGizmoMapType_Params *mmap_params);
+ const struct wmGizmoMapType_Params *gzmap_params);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find(
- struct wmGizmoMapType *mmap_type,
+ struct wmGizmoMapType *gzmap_type,
const char *idname);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find_ptr(
- struct wmGizmoMapType *mmap_type,
- const struct wmGizmoGroupType *wgt);
+ struct wmGizmoMapType *gzmap_type,
+ const struct wmGizmoGroupType *gzgt);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_link(
- struct wmGizmoMapType *mmap_type,
+ struct wmGizmoMapType *gzmap_type,
const char *idname);
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_link_ptr(
- struct wmGizmoMapType *mmap_type,
- struct wmGizmoGroupType *wgt);
+ struct wmGizmoMapType *gzmap_type,
+ struct wmGizmoGroupType *gzgt);
void WM_gizmomaptype_group_init_runtime_keymap(
const struct Main *bmain,
- struct wmGizmoGroupType *wgt);
+ struct wmGizmoGroupType *gzgt);
void WM_gizmomaptype_group_init_runtime(
- const struct Main *bmain, struct wmGizmoMapType *mmap_type,
- struct wmGizmoGroupType *wgt);
+ const struct Main *bmain, struct wmGizmoMapType *gzmap_type,
+ struct wmGizmoGroupType *gzgt);
void WM_gizmomaptype_group_unlink(
- struct bContext *C, struct Main *bmain, struct wmGizmoMapType *mmap_type,
- const struct wmGizmoGroupType *wgt);
+ struct bContext *C, struct Main *bmain, struct wmGizmoMapType *gzmap_type,
+ const struct wmGizmoGroupType *gzgt);
-void WM_gizmomaptype_group_free(struct wmGizmoGroupTypeRef *wgt);
+void WM_gizmomaptype_group_free(struct wmGizmoGroupTypeRef *gzgt);
/* -------------------------------------------------------------------- */
/* GizmoGroup */
@@ -308,36 +308,36 @@ void WM_gizmomaptype_group_free(struct wmGizmoGroupTypeRef *wgt);
/* Add/Ensure/Remove (High level API) */
void WM_gizmo_group_type_add_ptr_ex(
- struct wmGizmoGroupType *wgt,
- struct wmGizmoMapType *mmap_type);
+ struct wmGizmoGroupType *gzgt,
+ struct wmGizmoMapType *gzmap_type);
void WM_gizmo_group_type_add_ptr(
- struct wmGizmoGroupType *wgt);
+ struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_type_add(const char *idname);
void WM_gizmo_group_type_ensure_ptr_ex(
- struct wmGizmoGroupType *wgt,
- struct wmGizmoMapType *mmap_type);
+ struct wmGizmoGroupType *gzgt,
+ struct wmGizmoMapType *gzmap_type);
void WM_gizmo_group_type_ensure_ptr(
- struct wmGizmoGroupType *wgt);
+ struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_type_ensure(const char *idname);
void WM_gizmo_group_type_remove_ptr_ex(
- struct Main *bmain, struct wmGizmoGroupType *wgt,
- struct wmGizmoMapType *mmap_type);
+ struct Main *bmain, struct wmGizmoGroupType *gzgt,
+ struct wmGizmoMapType *gzmap_type);
void WM_gizmo_group_type_remove_ptr(
- struct Main *bmain, struct wmGizmoGroupType *wgt);
+ struct Main *bmain, struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_type_remove(struct Main *bmain, const char *idname);
void WM_gizmo_group_type_unlink_delayed_ptr_ex(
- struct wmGizmoGroupType *wgt,
- struct wmGizmoMapType *mmap_type);
+ struct wmGizmoGroupType *gzgt,
+ struct wmGizmoMapType *gzmap_type);
void WM_gizmo_group_type_unlink_delayed_ptr(
- struct wmGizmoGroupType *wgt);
+ struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_type_unlink_delayed(const char *idname);
/* Utilities */
bool WM_gizmo_context_check_drawstep(const struct bContext *C, eWM_GizmoFlagMapDrawStep step);
-bool WM_gizmo_group_type_poll(const struct bContext *C, const struct wmGizmoGroupType *wgt);
+bool WM_gizmo_group_type_poll(const struct bContext *C, const struct wmGizmoGroupType *gzgt);
#endif /* __WM_GIZMO_API_H__ */
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index ecdda256306..2339523db5e 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -171,7 +171,7 @@ struct wmGizmo {
wmGizmoFnModal custom_modal;
/* pointer back to group this gizmo is in (just for quick access) */
- struct wmGizmoGroup *parent_mgroup;
+ struct wmGizmoGroup *parent_gzgroup;
void *py_instance;
@@ -385,7 +385,7 @@ typedef struct wmGizmoGroupType {
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag;
/* same as gizmo-maps, so registering/unregistering goes to the correct region */
- struct wmGizmoMapType_Params mmap_params;
+ struct wmGizmoMapType_Params gzmap_params;
} wmGizmoGroupType;
@@ -395,7 +395,7 @@ typedef struct wmGizmoGroup {
struct wmGizmoGroupType *type;
ListBase gizmos;
- struct wmGizmoMap *parent_mmap;
+ struct wmGizmoMap *parent_gzmap;
void *py_instance; /* python stores the class instance here */
struct ReportList *reports; /* errors and warnings storage */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
index da8b301b536..14deb0be725 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
@@ -67,98 +67,98 @@
#include "wm_gizmo_intern.h"
static void wm_gizmo_register(
- wmGizmoGroup *mgroup, wmGizmo *mpr);
+ wmGizmoGroup *gzgroup, wmGizmo *gz);
/**
* \note Follow #wm_operator_create convention.
*/
static wmGizmo *wm_gizmo_create(
- const wmGizmoType *wt,
+ const wmGizmoType *gzt,
PointerRNA *properties)
{
- BLI_assert(wt != NULL);
- BLI_assert(wt->struct_size >= sizeof(wmGizmo));
+ BLI_assert(gzt != NULL);
+ BLI_assert(gzt->struct_size >= sizeof(wmGizmo));
- wmGizmo *mpr = MEM_callocN(
- wt->struct_size + (sizeof(wmGizmoProperty) * wt->target_property_defs_len), __func__);
- mpr->type = wt;
+ wmGizmo *gz = MEM_callocN(
+ gzt->struct_size + (sizeof(wmGizmoProperty) * gzt->target_property_defs_len), __func__);
+ gz->type = gzt;
/* initialize properties, either copy or create */
- mpr->ptr = MEM_callocN(sizeof(PointerRNA), "wmGizmoPtrRNA");
+ gz->ptr = MEM_callocN(sizeof(PointerRNA), "wmGizmoPtrRNA");
if (properties && properties->data) {
- mpr->properties = IDP_CopyProperty(properties->data);
+ gz->properties = IDP_CopyProperty(properties->data);
}
else {
IDPropertyTemplate val = {0};
- mpr->properties = IDP_New(IDP_GROUP, &val, "wmGizmoProperties");
+ gz->properties = IDP_New(IDP_GROUP, &val, "wmGizmoProperties");
}
- RNA_pointer_create(G_MAIN->wm.first, wt->srna, mpr->properties, mpr->ptr);
+ RNA_pointer_create(G_MAIN->wm.first, gzt->srna, gz->properties, gz->ptr);
- WM_gizmo_properties_sanitize(mpr->ptr, 0);
+ WM_gizmo_properties_sanitize(gz->ptr, 0);
- unit_m4(mpr->matrix_space);
- unit_m4(mpr->matrix_basis);
- unit_m4(mpr->matrix_offset);
+ unit_m4(gz->matrix_space);
+ unit_m4(gz->matrix_basis);
+ unit_m4(gz->matrix_offset);
- mpr->drag_part = -1;
+ gz->drag_part = -1;
- return mpr;
+ return gz;
}
wmGizmo *WM_gizmo_new_ptr(
- const wmGizmoType *wt, wmGizmoGroup *mgroup,
+ const wmGizmoType *gzt, wmGizmoGroup *gzgroup,
PointerRNA *properties)
{
- wmGizmo *mpr = wm_gizmo_create(wt, properties);
+ wmGizmo *gz = wm_gizmo_create(gzt, properties);
- wm_gizmo_register(mgroup, mpr);
+ wm_gizmo_register(gzgroup, gz);
- if (mpr->type->setup != NULL) {
- mpr->type->setup(mpr);
+ if (gz->type->setup != NULL) {
+ gz->type->setup(gz);
}
- return mpr;
+ return gz;
}
/**
- * \param wt: Must be valid,
+ * \param gt: Must be valid,
* if you need to check it exists use #WM_gizmo_new_ptr
* because callers of this function don't NULL check the return value.
*/
wmGizmo *WM_gizmo_new(
- const char *idname, wmGizmoGroup *mgroup,
+ const char *idname, wmGizmoGroup *gzgroup,
PointerRNA *properties)
{
- const wmGizmoType *wt = WM_gizmotype_find(idname, false);
- return WM_gizmo_new_ptr(wt, mgroup, properties);
+ const wmGizmoType *gzt = WM_gizmotype_find(idname, false);
+ return WM_gizmo_new_ptr(gzt, gzgroup, properties);
}
/**
* Initialize default values and allocate needed memory for members.
*/
-static void gizmo_init(wmGizmo *mpr)
+static void gizmo_init(wmGizmo *gz)
{
const float color_default[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- mpr->scale_basis = 1.0f;
- mpr->line_width = 1.0f;
+ gz->scale_basis = 1.0f;
+ gz->line_width = 1.0f;
/* defaults */
- copy_v4_v4(mpr->color, color_default);
- copy_v4_v4(mpr->color_hi, color_default);
+ copy_v4_v4(gz->color, color_default);
+ copy_v4_v4(gz->color_hi, color_default);
}
/**
* Register \a gizmo.
*
- * \param name: name used to create a unique idname for \a gizmo in \a mgroup
+ * \param name: name used to create a unique idname for \a gizmo in \a gzgroup
*
* \note Not to be confused with type registration from RNA.
*/
-static void wm_gizmo_register(wmGizmoGroup *mgroup, wmGizmo *mpr)
+static void wm_gizmo_register(wmGizmoGroup *gzgroup, wmGizmo *gz)
{
- gizmo_init(mpr);
- wm_gizmogroup_gizmo_register(mgroup, mpr);
+ gizmo_init(gz);
+ wm_gizmogroup_gizmo_register(gzgroup, gz);
}
/**
@@ -166,70 +166,70 @@ static void wm_gizmo_register(wmGizmoGroup *mgroup, wmGizmo *mpr)
* Typical use is when freeing the windowing data,
* where caller can manage clearing selection, highlight... etc.
*/
-void WM_gizmo_free(wmGizmo *mpr)
+void WM_gizmo_free(wmGizmo *gz)
{
- if (mpr->type->free != NULL) {
- mpr->type->free(mpr);
+ if (gz->type->free != NULL) {
+ gz->type->free(gz);
}
#ifdef WITH_PYTHON
- if (mpr->py_instance) {
+ if (gz->py_instance) {
/* do this first in case there are any __del__ functions or
* similar that use properties */
- BPY_DECREF_RNA_INVALIDATE(mpr->py_instance);
+ BPY_DECREF_RNA_INVALIDATE(gz->py_instance);
}
#endif
- if (mpr->op_data) {
- for (int i = 0; i < mpr->op_data_len; i++) {
- WM_operator_properties_free(&mpr->op_data[i].ptr);
+ if (gz->op_data) {
+ for (int i = 0; i < gz->op_data_len; i++) {
+ WM_operator_properties_free(&gz->op_data[i].ptr);
}
- MEM_freeN(mpr->op_data);
+ MEM_freeN(gz->op_data);
}
- if (mpr->ptr != NULL) {
- WM_gizmo_properties_free(mpr->ptr);
- MEM_freeN(mpr->ptr);
+ if (gz->ptr != NULL) {
+ WM_gizmo_properties_free(gz->ptr);
+ MEM_freeN(gz->ptr);
}
- if (mpr->type->target_property_defs_len != 0) {
- wmGizmoProperty *mpr_prop_array = WM_gizmo_target_property_array(mpr);
- for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
- wmGizmoProperty *mpr_prop = &mpr_prop_array[i];
- if (mpr_prop->custom_func.free_fn) {
- mpr_prop->custom_func.free_fn(mpr, mpr_prop);
+ if (gz->type->target_property_defs_len != 0) {
+ wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (gz_prop->custom_func.free_fn) {
+ gz_prop->custom_func.free_fn(gz, gz_prop);
}
}
}
- MEM_freeN(mpr);
+ MEM_freeN(gz);
}
/**
* Free \a gizmo and unlink from \a gizmolist.
* \a gizmolist is allowed to be NULL.
*/
-void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *mmap, wmGizmo *mpr, bContext *C)
+void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C)
{
- if (mpr->state & WM_GIZMO_STATE_HIGHLIGHT) {
- wm_gizmomap_highlight_set(mmap, C, NULL, 0);
+ if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
+ wm_gizmomap_highlight_set(gzmap, C, NULL, 0);
}
- if (mpr->state & WM_GIZMO_STATE_MODAL) {
- wm_gizmomap_modal_set(mmap, C, mpr, NULL, false);
+ if (gz->state & WM_GIZMO_STATE_MODAL) {
+ wm_gizmomap_modal_set(gzmap, C, gz, NULL, false);
}
/* Unlink instead of setting so we don't run callbacks. */
- if (mpr->state & WM_GIZMO_STATE_SELECT) {
- WM_gizmo_select_unlink(mmap, mpr);
+ if (gz->state & WM_GIZMO_STATE_SELECT) {
+ WM_gizmo_select_unlink(gzmap, gz);
}
if (gizmolist) {
- BLI_remlink(gizmolist, mpr);
+ BLI_remlink(gizmolist, gz);
}
- BLI_assert(mmap->mmap_context.highlight != mpr);
- BLI_assert(mmap->mmap_context.modal != mpr);
+ BLI_assert(gzmap->gzmap_context.highlight != gz);
+ BLI_assert(gzmap->gzmap_context.modal != gz);
- WM_gizmo_free(mpr);
+ WM_gizmo_free(gz);
}
/* -------------------------------------------------------------------- */
@@ -240,25 +240,25 @@ void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *mmap, wmGizmo *mpr, bConte
* \{ */
struct wmGizmoOpElem *WM_gizmo_operator_get(
- wmGizmo *mpr, int part_index)
+ wmGizmo *gz, int part_index)
{
- if (mpr->op_data && ((part_index >= 0) && (part_index < mpr->op_data_len))) {
- return &mpr->op_data[part_index];
+ if (gz->op_data && ((part_index >= 0) && (part_index < gz->op_data_len))) {
+ return &gz->op_data[part_index];
}
return NULL;
}
PointerRNA *WM_gizmo_operator_set(
- wmGizmo *mpr, int part_index,
+ wmGizmo *gz, int part_index,
wmOperatorType *ot, IDProperty *properties)
{
BLI_assert(part_index < 255);
/* We could pre-allocate these but using multiple is such a rare thing. */
- if (part_index >= mpr->op_data_len) {
- mpr->op_data_len = part_index + 1;
- mpr->op_data = MEM_recallocN(mpr->op_data, sizeof(*mpr->op_data) * mpr->op_data_len);
+ if (part_index >= gz->op_data_len) {
+ gz->op_data_len = part_index + 1;
+ gz->op_data = MEM_recallocN(gz->op_data, sizeof(*gz->op_data) * gz->op_data_len);
}
- wmGizmoOpElem *mpop = &mpr->op_data[part_index];
+ wmGizmoOpElem *mpop = &gz->op_data[part_index];
mpop->type = ot;
if (mpop->ptr.data) {
@@ -305,56 +305,56 @@ static void wm_gizmo_set_matrix_rotation_from_yz_axis__internal(
* wmGizmo.matrix utils.
*/
void WM_gizmo_set_matrix_rotation_from_z_axis(
- wmGizmo *mpr, const float z_axis[3])
+ wmGizmo *gz, const float z_axis[3])
{
- wm_gizmo_set_matrix_rotation_from_z_axis__internal(mpr->matrix_basis, z_axis);
+ wm_gizmo_set_matrix_rotation_from_z_axis__internal(gz->matrix_basis, z_axis);
}
void WM_gizmo_set_matrix_rotation_from_yz_axis(
- wmGizmo *mpr, const float y_axis[3], const float z_axis[3])
+ wmGizmo *gz, const float y_axis[3], const float z_axis[3])
{
- wm_gizmo_set_matrix_rotation_from_yz_axis__internal(mpr->matrix_basis, y_axis, z_axis);
+ wm_gizmo_set_matrix_rotation_from_yz_axis__internal(gz->matrix_basis, y_axis, z_axis);
}
-void WM_gizmo_set_matrix_location(wmGizmo *mpr, const float origin[3])
+void WM_gizmo_set_matrix_location(wmGizmo *gz, const float origin[3])
{
- copy_v3_v3(mpr->matrix_basis[3], origin);
+ copy_v3_v3(gz->matrix_basis[3], origin);
}
/**
* wmGizmo.matrix_offset utils.
*/
void WM_gizmo_set_matrix_offset_rotation_from_z_axis(
- wmGizmo *mpr, const float z_axis[3])
+ wmGizmo *gz, const float z_axis[3])
{
- wm_gizmo_set_matrix_rotation_from_z_axis__internal(mpr->matrix_offset, z_axis);
+ wm_gizmo_set_matrix_rotation_from_z_axis__internal(gz->matrix_offset, z_axis);
}
void WM_gizmo_set_matrix_offset_rotation_from_yz_axis(
- wmGizmo *mpr, const float y_axis[3], const float z_axis[3])
+ wmGizmo *gz, const float y_axis[3], const float z_axis[3])
{
- wm_gizmo_set_matrix_rotation_from_yz_axis__internal(mpr->matrix_offset, y_axis, z_axis);
+ wm_gizmo_set_matrix_rotation_from_yz_axis__internal(gz->matrix_offset, y_axis, z_axis);
}
-void WM_gizmo_set_matrix_offset_location(wmGizmo *mpr, const float offset[3])
+void WM_gizmo_set_matrix_offset_location(wmGizmo *gz, const float offset[3])
{
- copy_v3_v3(mpr->matrix_offset[3], offset);
+ copy_v3_v3(gz->matrix_offset[3], offset);
}
-void WM_gizmo_set_flag(wmGizmo *mpr, const int flag, const bool enable)
+void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
{
if (enable) {
- mpr->flag |= flag;
+ gz->flag |= flag;
}
else {
- mpr->flag &= ~flag;
+ gz->flag &= ~flag;
}
}
-void WM_gizmo_set_scale(wmGizmo *mpr, const float scale)
+void WM_gizmo_set_scale(wmGizmo *gz, const float scale)
{
- mpr->scale_basis = scale;
+ gz->scale_basis = scale;
}
-void WM_gizmo_set_line_width(wmGizmo *mpr, const float line_width)
+void WM_gizmo_set_line_width(wmGizmo *gz, const float line_width)
{
- mpr->line_width = line_width;
+ gz->line_width = line_width;
}
/**
@@ -363,22 +363,22 @@ void WM_gizmo_set_line_width(wmGizmo *mpr, const float line_width)
* \param col Normal state color.
* \param col_hi Highlighted state color.
*/
-void WM_gizmo_get_color(const wmGizmo *mpr, float color[4])
+void WM_gizmo_get_color(const wmGizmo *gz, float color[4])
{
- copy_v4_v4(color, mpr->color);
+ copy_v4_v4(color, gz->color);
}
-void WM_gizmo_set_color(wmGizmo *mpr, const float color[4])
+void WM_gizmo_set_color(wmGizmo *gz, const float color[4])
{
- copy_v4_v4(mpr->color, color);
+ copy_v4_v4(gz->color, color);
}
-void WM_gizmo_get_color_highlight(const wmGizmo *mpr, float color_hi[4])
+void WM_gizmo_get_color_highlight(const wmGizmo *gz, float color_hi[4])
{
- copy_v4_v4(color_hi, mpr->color_hi);
+ copy_v4_v4(color_hi, gz->color_hi);
}
-void WM_gizmo_set_color_highlight(wmGizmo *mpr, const float color_hi[4])
+void WM_gizmo_set_color_highlight(wmGizmo *gz, const float color_hi[4])
{
- copy_v4_v4(mpr->color_hi, color_hi);
+ copy_v4_v4(gz->color_hi, color_hi);
}
@@ -390,9 +390,9 @@ void WM_gizmo_set_color_highlight(wmGizmo *mpr, const float color_hi[4])
*
* \{ */
-void WM_gizmo_set_fn_custom_modal(struct wmGizmo *mpr, wmGizmoFnModal fn)
+void WM_gizmo_set_fn_custom_modal(struct wmGizmo *gz, wmGizmoFnModal fn)
{
- mpr->custom_modal = fn;
+ gz->custom_modal = fn;
}
/** \} */
@@ -407,26 +407,26 @@ void WM_gizmo_set_fn_custom_modal(struct wmGizmo *mpr, wmGizmoFnModal fn)
* \return if the selection has changed.
*/
bool wm_gizmo_select_set_ex(
- wmGizmoMap *mmap, wmGizmo *mpr, bool select,
+ wmGizmoMap *gzmap, wmGizmo *gz, bool select,
bool use_array, bool use_callback)
{
bool changed = false;
if (select) {
- if ((mpr->state & WM_GIZMO_STATE_SELECT) == 0) {
+ if ((gz->state & WM_GIZMO_STATE_SELECT) == 0) {
if (use_array) {
- wm_gizmomap_select_array_push_back(mmap, mpr);
+ wm_gizmomap_select_array_push_back(gzmap, gz);
}
- mpr->state |= WM_GIZMO_STATE_SELECT;
+ gz->state |= WM_GIZMO_STATE_SELECT;
changed = true;
}
}
else {
- if (mpr->state & WM_GIZMO_STATE_SELECT) {
+ if (gz->state & WM_GIZMO_STATE_SELECT) {
if (use_array) {
- wm_gizmomap_select_array_remove(mmap, mpr);
+ wm_gizmomap_select_array_remove(gzmap, gz);
}
- mpr->state &= ~WM_GIZMO_STATE_SELECT;
+ gz->state &= ~WM_GIZMO_STATE_SELECT;
changed = true;
}
}
@@ -434,8 +434,8 @@ bool wm_gizmo_select_set_ex(
/* In the case of unlinking we only want to remove from the array
* and not write to the external state */
if (use_callback && changed) {
- if (mpr->type->select_refresh) {
- mpr->type->select_refresh(mpr);
+ if (gz->type->select_refresh) {
+ gz->type->select_refresh(gz);
}
}
@@ -443,25 +443,25 @@ bool wm_gizmo_select_set_ex(
}
/* Remove from selection array without running callbacks. */
-bool WM_gizmo_select_unlink(wmGizmoMap *mmap, wmGizmo *mpr)
+bool WM_gizmo_select_unlink(wmGizmoMap *gzmap, wmGizmo *gz)
{
- return wm_gizmo_select_set_ex(mmap, mpr, false, true, false);
+ return wm_gizmo_select_set_ex(gzmap, gz, false, true, false);
}
-bool WM_gizmo_select_set(wmGizmoMap *mmap, wmGizmo *mpr, bool select)
+bool WM_gizmo_select_set(wmGizmoMap *gzmap, wmGizmo *gz, bool select)
{
- return wm_gizmo_select_set_ex(mmap, mpr, select, true, true);
+ return wm_gizmo_select_set_ex(gzmap, gz, select, true, true);
}
-void WM_gizmo_highlight_set(wmGizmoMap *mmap, wmGizmo *mpr)
+void WM_gizmo_highlight_set(wmGizmoMap *gzmap, wmGizmo *gz)
{
- wm_gizmomap_highlight_set(mmap, NULL, mpr, mpr ? mpr->highlight_part : 0);
+ wm_gizmomap_highlight_set(gzmap, NULL, gz, gz ? gz->highlight_part : 0);
}
-bool wm_gizmo_select_and_highlight(bContext *C, wmGizmoMap *mmap, wmGizmo *mpr)
+bool wm_gizmo_select_and_highlight(bContext *C, wmGizmoMap *gzmap, wmGizmo *gz)
{
- if (WM_gizmo_select_set(mmap, mpr, true)) {
- wm_gizmomap_highlight_set(mmap, C, mpr, mpr->highlight_part);
+ if (WM_gizmo_select_set(gzmap, gz, true)) {
+ wm_gizmomap_highlight_set(gzmap, C, gz, gz->highlight_part);
return true;
}
else {
@@ -475,13 +475,13 @@ bool wm_gizmo_select_and_highlight(bContext *C, wmGizmoMap *mmap, wmGizmo *mpr)
* We could do this when linking them, but this complicates things since the window update code needs to run first.
*/
void WM_gizmo_modal_set_from_setup(
- struct wmGizmoMap *mmap, struct bContext *C,
- struct wmGizmo *mpr, int part_index, const wmEvent *event)
+ struct wmGizmoMap *gzmap, struct bContext *C,
+ struct wmGizmo *gz, int part_index, const wmEvent *event)
{
- mpr->highlight_part = part_index;
- WM_gizmo_highlight_set(mmap, mpr);
+ gz->highlight_part = part_index;
+ WM_gizmo_highlight_set(gzmap, gz);
if (false) {
- wm_gizmomap_modal_set(mmap, C, mpr, event, true);
+ wm_gizmomap_modal_set(gzmap, C, gz, event, true);
}
else {
/* WEAK: but it works. */
@@ -489,23 +489,23 @@ void WM_gizmo_modal_set_from_setup(
}
}
-void wm_gizmo_calculate_scale(wmGizmo *mpr, const bContext *C)
+void wm_gizmo_calculate_scale(wmGizmo *gz, const bContext *C)
{
const RegionView3D *rv3d = CTX_wm_region_view3d(C);
float scale = UI_DPI_FAC;
- if ((mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_SCALE) == 0) {
+ if ((gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_SCALE) == 0) {
scale *= U.gizmo_size;
if (rv3d) {
/* 'ED_view3d_pixel_size' includes 'U.pixelsize', remove it. */
float matrix_world[4][4];
- if (mpr->type->matrix_basis_get) {
+ if (gz->type->matrix_basis_get) {
float matrix_basis[4][4];
- mpr->type->matrix_basis_get(mpr, matrix_basis);
- mul_m4_m4m4(matrix_world, mpr->matrix_space, matrix_basis);
+ gz->type->matrix_basis_get(gz, matrix_basis);
+ mul_m4_m4m4(matrix_world, gz->matrix_space, matrix_basis);
}
else {
- mul_m4_m4m4(matrix_world, mpr->matrix_space, mpr->matrix_basis);
+ mul_m4_m4m4(matrix_world, gz->matrix_space, gz->matrix_basis);
}
/* Exclude matrix_offset from scale. */
@@ -516,45 +516,45 @@ void wm_gizmo_calculate_scale(wmGizmo *mpr, const bContext *C)
}
}
- mpr->scale_final = mpr->scale_basis * scale;
+ gz->scale_final = gz->scale_basis * scale;
}
-static void gizmo_update_prop_data(wmGizmo *mpr)
+static void gizmo_update_prop_data(wmGizmo *gz)
{
/* gizmo property might have been changed, so update gizmo */
- if (mpr->type->property_update) {
- wmGizmoProperty *mpr_prop_array = WM_gizmo_target_property_array(mpr);
- for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
- wmGizmoProperty *mpr_prop = &mpr_prop_array[i];
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- mpr->type->property_update(mpr, mpr_prop);
+ if (gz->type->property_update) {
+ wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ gz->type->property_update(gz, gz_prop);
}
}
}
}
-void wm_gizmo_update(wmGizmo *mpr, const bContext *C, const bool refresh_map)
+void wm_gizmo_update(wmGizmo *gz, const bContext *C, const bool refresh_map)
{
if (refresh_map) {
- gizmo_update_prop_data(mpr);
+ gizmo_update_prop_data(gz);
}
- wm_gizmo_calculate_scale(mpr, C);
+ wm_gizmo_calculate_scale(gz, C);
}
-int wm_gizmo_is_visible(wmGizmo *mpr)
+int wm_gizmo_is_visible(wmGizmo *gz)
{
- if (mpr->flag & WM_GIZMO_HIDDEN) {
+ if (gz->flag & WM_GIZMO_HIDDEN) {
return 0;
}
- if ((mpr->state & WM_GIZMO_STATE_MODAL) &&
- !(mpr->flag & (WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_VALUE)))
+ if ((gz->state & WM_GIZMO_STATE_MODAL) &&
+ !(gz->flag & (WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_VALUE)))
{
/* don't draw while modal (dragging) */
return 0;
}
- if ((mpr->flag & WM_GIZMO_DRAW_HOVER) &&
- !(mpr->state & WM_GIZMO_STATE_HIGHLIGHT) &&
- !(mpr->state & WM_GIZMO_STATE_SELECT)) /* still draw selected gizmos */
+ if ((gz->flag & WM_GIZMO_DRAW_HOVER) &&
+ !(gz->state & WM_GIZMO_STATE_HIGHLIGHT) &&
+ !(gz->state & WM_GIZMO_STATE_SELECT)) /* still draw selected gizmos */
{
/* update but don't draw */
return WM_GIZMO_IS_VISIBLE_UPDATE;
@@ -564,28 +564,28 @@ int wm_gizmo_is_visible(wmGizmo *mpr)
}
void WM_gizmo_calc_matrix_final_params(
- const wmGizmo *mpr,
+ const wmGizmo *gz,
const struct WM_GizmoMatrixParams *params,
float r_mat[4][4])
{
- const float (* const matrix_space)[4] = params->matrix_space ? params->matrix_space : mpr->matrix_space;
- const float (* const matrix_basis)[4] = params->matrix_basis ? params->matrix_basis : mpr->matrix_basis;
- const float (* const matrix_offset)[4] = params->matrix_offset ? params->matrix_offset : mpr->matrix_offset;
- const float *scale_final = params->scale_final ? params->scale_final : &mpr->scale_final;
+ const float (* const matrix_space)[4] = params->matrix_space ? params->matrix_space : gz->matrix_space;
+ const float (* const matrix_basis)[4] = params->matrix_basis ? params->matrix_basis : gz->matrix_basis;
+ const float (* const matrix_offset)[4] = params->matrix_offset ? params->matrix_offset : gz->matrix_offset;
+ const float *scale_final = params->scale_final ? params->scale_final : &gz->scale_final;
float final_matrix[4][4];
- if (params->matrix_basis == NULL && mpr->type->matrix_basis_get) {
- mpr->type->matrix_basis_get(mpr, final_matrix);
+ if (params->matrix_basis == NULL && gz->type->matrix_basis_get) {
+ gz->type->matrix_basis_get(gz, final_matrix);
}
else {
copy_m4_m4(final_matrix, matrix_basis);
}
- if (mpr->flag & WM_GIZMO_DRAW_NO_SCALE) {
+ if (gz->flag & WM_GIZMO_DRAW_NO_SCALE) {
mul_m4_m4m4(final_matrix, final_matrix, matrix_offset);
}
else {
- if (mpr->flag & WM_GIZMO_DRAW_OFFSET_SCALE) {
+ if (gz->flag & WM_GIZMO_DRAW_OFFSET_SCALE) {
mul_mat3_m4_fl(final_matrix, *scale_final);
mul_m4_m4m4(final_matrix, final_matrix, matrix_offset);
}
@@ -598,13 +598,13 @@ void WM_gizmo_calc_matrix_final_params(
mul_m4_m4m4(r_mat, matrix_space, final_matrix);
}
-void WM_gizmo_calc_matrix_final_no_offset(const wmGizmo *mpr, float r_mat[4][4])
+void WM_gizmo_calc_matrix_final_no_offset(const wmGizmo *gz, float r_mat[4][4])
{
float mat_identity[4][4];
unit_m4(mat_identity);
WM_gizmo_calc_matrix_final_params(
- mpr,
+ gz,
&((struct WM_GizmoMatrixParams) {
.matrix_space = NULL,
.matrix_basis = NULL,
@@ -614,10 +614,10 @@ void WM_gizmo_calc_matrix_final_no_offset(const wmGizmo *mpr, float r_mat[4][4])
);
}
-void WM_gizmo_calc_matrix_final(const wmGizmo *mpr, float r_mat[4][4])
+void WM_gizmo_calc_matrix_final(const wmGizmo *gz, float r_mat[4][4])
{
WM_gizmo_calc_matrix_final_params(
- mpr,
+ gz,
&((struct WM_GizmoMatrixParams) {
.matrix_space = NULL,
.matrix_basis = NULL,
@@ -634,24 +634,24 @@ void WM_gizmo_calc_matrix_final(const wmGizmo *mpr, float r_mat[4][4])
* \{ */
-void WM_gizmo_properties_create_ptr(PointerRNA *ptr, wmGizmoType *wt)
+void WM_gizmo_properties_create_ptr(PointerRNA *ptr, wmGizmoType *gzt)
{
- RNA_pointer_create(NULL, wt->srna, NULL, ptr);
+ RNA_pointer_create(NULL, gzt->srna, NULL, ptr);
}
-void WM_gizmo_properties_create(PointerRNA *ptr, const char *wtstring)
+void WM_gizmo_properties_create(PointerRNA *ptr, const char *gtstring)
{
- const wmGizmoType *wt = WM_gizmotype_find(wtstring, false);
+ const wmGizmoType *gzt = WM_gizmotype_find(gtstring, false);
- if (wt)
- WM_gizmo_properties_create_ptr(ptr, (wmGizmoType *)wt);
+ if (gzt)
+ WM_gizmo_properties_create_ptr(ptr, (wmGizmoType *)gzt);
else
RNA_pointer_create(NULL, &RNA_GizmoProperties, NULL, ptr);
}
/* similar to the function above except its uses ID properties
* used for keymaps and macros */
-void WM_gizmo_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *wtstring)
+void WM_gizmo_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *gtstring)
{
if (*properties == NULL) {
IDPropertyTemplate val = {0};
@@ -660,7 +660,7 @@ void WM_gizmo_properties_alloc(PointerRNA **ptr, IDProperty **properties, const
if (*ptr == NULL) {
*ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr");
- WM_gizmo_properties_create(*ptr, wtstring);
+ WM_gizmo_properties_create(*ptr, gtstring);
}
(*ptr)->data = *properties;
@@ -733,19 +733,19 @@ bool WM_gizmo_properties_default(PointerRNA *ptr, const bool do_update)
}
/* remove all props without PROP_SKIP_SAVE */
-void WM_gizmo_properties_reset(wmGizmo *mpr)
+void WM_gizmo_properties_reset(wmGizmo *gz)
{
- if (mpr->ptr->data) {
+ if (gz->ptr->data) {
PropertyRNA *iterprop;
- iterprop = RNA_struct_iterator_property(mpr->type->srna);
+ iterprop = RNA_struct_iterator_property(gz->type->srna);
- RNA_PROP_BEGIN (mpr->ptr, itemptr, iterprop)
+ RNA_PROP_BEGIN (gz->ptr, itemptr, iterprop)
{
PropertyRNA *prop = itemptr.data;
if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
const char *identifier = RNA_property_identifier(prop);
- RNA_struct_idprops_unset(mpr->ptr, identifier);
+ RNA_struct_idprops_unset(gz->ptr, identifier);
}
}
RNA_PROP_END;
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index f30744859aa..3ba9fa71601 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -74,87 +74,87 @@
* \{ */
/**
- * Create a new gizmo-group from \a wgt.
+ * Create a new gizmo-group from \a gzgt.
*/
wmGizmoGroup *wm_gizmogroup_new_from_type(
- wmGizmoMap *mmap, wmGizmoGroupType *wgt)
+ wmGizmoMap *gzmap, wmGizmoGroupType *gzgt)
{
- wmGizmoGroup *mgroup = MEM_callocN(sizeof(*mgroup), "gizmo-group");
- mgroup->type = wgt;
+ wmGizmoGroup *gzgroup = MEM_callocN(sizeof(*gzgroup), "gizmo-group");
+ gzgroup->type = gzgt;
/* keep back-link */
- mgroup->parent_mmap = mmap;
+ gzgroup->parent_gzmap = gzmap;
- BLI_addtail(&mmap->groups, mgroup);
+ BLI_addtail(&gzmap->groups, gzgroup);
- return mgroup;
+ return gzgroup;
}
-void wm_gizmogroup_free(bContext *C, wmGizmoGroup *mgroup)
+void wm_gizmogroup_free(bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmoMap *mmap = mgroup->parent_mmap;
+ wmGizmoMap *gzmap = gzgroup->parent_gzmap;
- /* Similar to WM_gizmo_unlink, but only to keep mmap state correct,
+ /* Similar to WM_gizmo_unlink, but only to keep gzmap state correct,
* we don't want to run callbacks. */
- if (mmap->mmap_context.highlight && mmap->mmap_context.highlight->parent_mgroup == mgroup) {
- wm_gizmomap_highlight_set(mmap, C, NULL, 0);
+ if (gzmap->gzmap_context.highlight && gzmap->gzmap_context.highlight->parent_gzgroup == gzgroup) {
+ wm_gizmomap_highlight_set(gzmap, C, NULL, 0);
}
- if (mmap->mmap_context.modal && mmap->mmap_context.modal->parent_mgroup == mgroup) {
- wm_gizmomap_modal_set(mmap, C, mmap->mmap_context.modal, NULL, false);
+ if (gzmap->gzmap_context.modal && gzmap->gzmap_context.modal->parent_gzgroup == gzgroup) {
+ wm_gizmomap_modal_set(gzmap, C, gzmap->gzmap_context.modal, NULL, false);
}
- for (wmGizmo *mpr = mgroup->gizmos.first, *mpr_next; mpr; mpr = mpr_next) {
- mpr_next = mpr->next;
- if (mmap->mmap_context.select.len) {
- WM_gizmo_select_unlink(mmap, mpr);
+ for (wmGizmo *gz = gzgroup->gizmos.first, *gz_next; gz; gz = gz_next) {
+ gz_next = gz->next;
+ if (gzmap->gzmap_context.select.len) {
+ WM_gizmo_select_unlink(gzmap, gz);
}
- WM_gizmo_free(mpr);
+ WM_gizmo_free(gz);
}
- BLI_listbase_clear(&mgroup->gizmos);
+ BLI_listbase_clear(&gzgroup->gizmos);
#ifdef WITH_PYTHON
- if (mgroup->py_instance) {
+ if (gzgroup->py_instance) {
/* do this first in case there are any __del__ functions or
* similar that use properties */
- BPY_DECREF_RNA_INVALIDATE(mgroup->py_instance);
+ BPY_DECREF_RNA_INVALIDATE(gzgroup->py_instance);
}
#endif
- if (mgroup->reports && (mgroup->reports->flag & RPT_FREE)) {
- BKE_reports_clear(mgroup->reports);
- MEM_freeN(mgroup->reports);
+ if (gzgroup->reports && (gzgroup->reports->flag & RPT_FREE)) {
+ BKE_reports_clear(gzgroup->reports);
+ MEM_freeN(gzgroup->reports);
}
- if (mgroup->customdata_free) {
- mgroup->customdata_free(mgroup->customdata);
+ if (gzgroup->customdata_free) {
+ gzgroup->customdata_free(gzgroup->customdata);
}
else {
- MEM_SAFE_FREE(mgroup->customdata);
+ MEM_SAFE_FREE(gzgroup->customdata);
}
- BLI_remlink(&mmap->groups, mgroup);
+ BLI_remlink(&gzmap->groups, gzgroup);
- MEM_freeN(mgroup);
+ MEM_freeN(gzgroup);
}
/**
- * Add \a gizmo to \a mgroup and make sure its name is unique within the group.
+ * Add \a gizmo to \a gzgroup and make sure its name is unique within the group.
*/
-void wm_gizmogroup_gizmo_register(wmGizmoGroup *mgroup, wmGizmo *mpr)
+void wm_gizmogroup_gizmo_register(wmGizmoGroup *gzgroup, wmGizmo *gz)
{
- BLI_assert(BLI_findindex(&mgroup->gizmos, mpr) == -1);
- BLI_addtail(&mgroup->gizmos, mpr);
- mpr->parent_mgroup = mgroup;
+ BLI_assert(BLI_findindex(&gzgroup->gizmos, gz) == -1);
+ BLI_addtail(&gzgroup->gizmos, gz);
+ gz->parent_gzgroup = gzgroup;
}
wmGizmo *wm_gizmogroup_find_intersected_gizmo(
- const wmGizmoGroup *mgroup, bContext *C, const wmEvent *event,
+ const wmGizmoGroup *gzgroup, bContext *C, const wmEvent *event,
int *r_part)
{
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if (mpr->type->test_select && (mpr->flag & WM_GIZMO_HIDDEN) == 0) {
- if ((*r_part = mpr->type->test_select(C, mpr, event)) != -1) {
- return mpr;
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if (gz->type->test_select && (gz->flag & WM_GIZMO_HIDDEN) == 0) {
+ if ((*r_part = gz->type->test_select(C, gz, event->mval)) != -1) {
+ return gz;
}
}
}
@@ -163,78 +163,78 @@ wmGizmo *wm_gizmogroup_find_intersected_gizmo(
}
/**
- * Adds all gizmos of \a mgroup that can be selected to the head of \a listbase. Added items need freeing!
+ * Adds all gizmos of \a gzgroup that can be selected to the head of \a listbase. Added items need freeing!
*/
-void wm_gizmogroup_intersectable_gizmos_to_list(const wmGizmoGroup *mgroup, ListBase *listbase)
+void wm_gizmogroup_intersectable_gizmos_to_list(const wmGizmoGroup *gzgroup, ListBase *listbase)
{
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if ((mpr->flag & WM_GIZMO_HIDDEN) == 0) {
- if (((mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) && mpr->type->draw_select) ||
- ((mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && mpr->type->test_select))
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if ((gz->flag & WM_GIZMO_HIDDEN) == 0) {
+ if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) && (gz->type->draw_select || gz->type->test_select)) ||
+ ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && gz->type->test_select))
{
- BLI_addhead(listbase, BLI_genericNodeN(mpr));
+ BLI_addhead(listbase, BLI_genericNodeN(gz));
}
}
}
}
-void wm_gizmogroup_ensure_initialized(wmGizmoGroup *mgroup, const bContext *C)
+void wm_gizmogroup_ensure_initialized(wmGizmoGroup *gzgroup, const bContext *C)
{
/* prepare for first draw */
- if (UNLIKELY((mgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) {
- mgroup->type->setup(C, mgroup);
+ if (UNLIKELY((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) {
+ gzgroup->type->setup(C, gzgroup);
/* Not ideal, initialize keymap here, needed for RNA runtime generated gizmos. */
- wmGizmoGroupType *wgt = mgroup->type;
- if (wgt->keymap == NULL) {
+ wmGizmoGroupType *gzgt = gzgroup->type;
+ if (gzgt->keymap == NULL) {
wmWindowManager *wm = CTX_wm_manager(C);
- wm_gizmogrouptype_setup_keymap(wgt, wm->defaultconf);
- BLI_assert(wgt->keymap != NULL);
+ wm_gizmogrouptype_setup_keymap(gzgt, wm->defaultconf);
+ BLI_assert(gzgt->keymap != NULL);
}
- mgroup->init_flag |= WM_GIZMOGROUP_INIT_SETUP;
+ gzgroup->init_flag |= WM_GIZMOGROUP_INIT_SETUP;
}
/* refresh may be called multiple times, this just ensures its called at least once before we draw. */
- if (UNLIKELY((mgroup->init_flag & WM_GIZMOGROUP_INIT_REFRESH) == 0)) {
- if (mgroup->type->refresh) {
- mgroup->type->refresh(C, mgroup);
+ if (UNLIKELY((gzgroup->init_flag & WM_GIZMOGROUP_INIT_REFRESH) == 0)) {
+ if (gzgroup->type->refresh) {
+ gzgroup->type->refresh(C, gzgroup);
}
- mgroup->init_flag |= WM_GIZMOGROUP_INIT_REFRESH;
+ gzgroup->init_flag |= WM_GIZMOGROUP_INIT_REFRESH;
}
}
-bool WM_gizmo_group_type_poll(const bContext *C, const struct wmGizmoGroupType *wgt)
+bool WM_gizmo_group_type_poll(const bContext *C, const struct wmGizmoGroupType *gzgt)
{
/* If we're tagged, only use compatible. */
- if (wgt->owner_id[0] != '\0') {
+ if (gzgt->owner_id[0] != '\0') {
const WorkSpace *workspace = CTX_wm_workspace(C);
- if (BKE_workspace_owner_id_check(workspace, wgt->owner_id) == false) {
+ if (BKE_workspace_owner_id_check(workspace, gzgt->owner_id) == false) {
return false;
}
}
/* Check for poll function, if gizmo-group belongs to an operator, also check if the operator is running. */
- return (!wgt->poll || wgt->poll(C, (wmGizmoGroupType *)wgt));
+ return (!gzgt->poll || gzgt->poll(C, (wmGizmoGroupType *)gzgt));
}
bool wm_gizmogroup_is_visible_in_drawstep(
- const wmGizmoGroup *mgroup, const eWM_GizmoFlagMapDrawStep drawstep)
+ const wmGizmoGroup *gzgroup, const eWM_GizmoFlagMapDrawStep drawstep)
{
switch (drawstep) {
case WM_GIZMOMAP_DRAWSTEP_2D:
- return (mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
+ return (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
case WM_GIZMOMAP_DRAWSTEP_3D:
- return (mgroup->type->flag & WM_GIZMOGROUPTYPE_3D);
+ return (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D);
default:
BLI_assert(0);
return false;
}
}
-bool wm_gizmogroup_is_any_selected(const wmGizmoGroup *mgroup)
+bool wm_gizmogroup_is_any_selected(const wmGizmoGroup *gzgroup)
{
- if (mgroup->type->flag & WM_GIZMOGROUPTYPE_SELECT) {
- for (const wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if (mpr->state & WM_GIZMO_STATE_SELECT) {
+ if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_SELECT) {
+ for (const wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if (gz->state & WM_GIZMO_STATE_SELECT) {
return true;
}
}
@@ -253,9 +253,9 @@ bool wm_gizmogroup_is_any_selected(const wmGizmoGroup *mgroup)
static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *mmap = ar->gizmo_map;
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
- wmGizmo *highlight = mmap->mmap_context.highlight;
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
+ wmGizmo *highlight = gzmap->gzmap_context.highlight;
bool extend = RNA_boolean_get(op->ptr, "extend");
bool deselect = RNA_boolean_get(op->ptr, "deselect");
@@ -263,7 +263,7 @@ static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
/* deselect all first */
if (extend == false && deselect == false && toggle == false) {
- wm_gizmomap_deselect_all(mmap);
+ wm_gizmomap_deselect_all(gzmap);
BLI_assert(msel->items == NULL && msel->len == 0);
UNUSED_VARS_NDEBUG(msel);
}
@@ -278,11 +278,11 @@ static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
}
if (deselect) {
- if (is_selected && WM_gizmo_select_set(mmap, highlight, false)) {
+ if (is_selected && WM_gizmo_select_set(gzmap, highlight, false)) {
redraw = true;
}
}
- else if (wm_gizmo_select_and_highlight(C, mmap, highlight)) {
+ else if (wm_gizmo_select_and_highlight(C, gzmap, highlight)) {
redraw = true;
}
@@ -296,8 +296,6 @@ static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
BLI_assert(0);
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
-
- return OPERATOR_PASS_THROUGH;
}
void GIZMOGROUP_OT_gizmo_select(wmOperatorType *ot)
@@ -316,9 +314,9 @@ void GIZMOGROUP_OT_gizmo_select(wmOperatorType *ot)
}
typedef struct GizmoTweakData {
- wmGizmoMap *mmap;
- wmGizmoGroup *mgroup;
- wmGizmo *mpr_modal;
+ wmGizmoMap *gzmap;
+ wmGizmoGroup *gzgroup;
+ wmGizmo *gz_modal;
int init_event; /* initial event type */
int flag; /* tweak flags */
@@ -342,18 +340,18 @@ typedef struct GizmoTweakData {
} GizmoTweakData;
static bool gizmo_tweak_start(
- bContext *C, wmGizmoMap *mmap, wmGizmo *mpr, const wmEvent *event)
+ bContext *C, wmGizmoMap *gzmap, wmGizmo *gz, const wmEvent *event)
{
/* activate highlighted gizmo */
- wm_gizmomap_modal_set(mmap, C, mpr, event, true);
+ wm_gizmomap_modal_set(gzmap, C, gz, event, true);
- return (mpr->state & WM_GIZMO_STATE_MODAL);
+ return (gz->state & WM_GIZMO_STATE_MODAL);
}
static bool gizmo_tweak_start_and_finish(
- bContext *C, wmGizmoMap *mmap, wmGizmo *mpr, const wmEvent *event, bool *r_is_modal)
+ bContext *C, wmGizmoMap *gzmap, wmGizmo *gz, const wmEvent *event, bool *r_is_modal)
{
- wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, mpr->highlight_part);
+ wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, gz->highlight_part);
if (r_is_modal) {
*r_is_modal = false;
}
@@ -377,7 +375,7 @@ static bool gizmo_tweak_start_and_finish(
* conflicting with modal operator attached to gizmo */
if (mpop->type->modal) {
/* activate highlighted gizmo */
- wm_gizmomap_modal_set(mmap, C, mpr, event, true);
+ wm_gizmomap_modal_set(gzmap, C, gz, event, true);
if (r_is_modal) {
*r_is_modal = true;
}
@@ -396,15 +394,15 @@ static bool gizmo_tweak_start_and_finish(
static void gizmo_tweak_finish(bContext *C, wmOperator *op, const bool cancel, bool clear_modal)
{
GizmoTweakData *mtweak = op->customdata;
- if (mtweak->mpr_modal->type->exit) {
- mtweak->mpr_modal->type->exit(C, mtweak->mpr_modal, cancel);
+ if (mtweak->gz_modal->type->exit) {
+ mtweak->gz_modal->type->exit(C, mtweak->gz_modal, cancel);
}
if (clear_modal) {
/* The gizmo may have been removed. */
- if ((BLI_findindex(&mtweak->mmap->groups, mtweak->mgroup) != -1) &&
- (BLI_findindex(&mtweak->mgroup->gizmos, mtweak->mpr_modal) != -1))
+ if ((BLI_findindex(&mtweak->gzmap->groups, mtweak->gzgroup) != -1) &&
+ (BLI_findindex(&mtweak->gzgroup->gizmos, mtweak->gz_modal) != -1))
{
- wm_gizmomap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+ wm_gizmomap_modal_set(mtweak->gzmap, C, mtweak->gz_modal, NULL, false);
}
}
MEM_freeN(mtweak);
@@ -413,22 +411,22 @@ static void gizmo_tweak_finish(bContext *C, wmOperator *op, const bool cancel, b
static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
GizmoTweakData *mtweak = op->customdata;
- wmGizmo *mpr = mtweak->mpr_modal;
+ wmGizmo *gz = mtweak->gz_modal;
int retval = OPERATOR_PASS_THROUGH;
bool clear_modal = true;
- if (mpr == NULL) {
+ if (gz == NULL) {
BLI_assert(0);
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
#ifdef USE_DRAG_DETECT
- wmGizmoMap *mmap = mtweak->mmap;
+ wmGizmoMap *gzmap = mtweak->gzmap;
if (mtweak->drag_state == DRAG_DETECT) {
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- if (len_manhattan_v2v2_int(&event->x, mmap->mmap_context.event_xy) > 2) {
+ if (len_manhattan_v2v2_int(&event->x, gzmap->gzmap_context.event_xy) > 2) {
mtweak->drag_state = DRAG_IDLE;
- mpr->highlight_part = mpr->drag_part;
+ gz->highlight_part = gz->drag_part;
}
}
else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
@@ -439,20 +437,20 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (mtweak->drag_state != DRAG_DETECT) {
/* Follow logic in 'gizmo_tweak_invoke' */
bool is_modal = false;
- if (gizmo_tweak_start_and_finish(C, mmap, mpr, event, &is_modal)) {
+ if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, &is_modal)) {
if (is_modal) {
clear_modal = false;
}
}
else {
- if (!gizmo_tweak_start(C, mmap, mpr, event)) {
+ if (!gizmo_tweak_start(C, gzmap, gz, event)) {
retval = OPERATOR_FINISHED;
}
}
}
}
if (mtweak->drag_state == DRAG_IDLE) {
- if (mmap->mmap_context.modal != NULL) {
+ if (gzmap->gzmap_context.modal != NULL) {
return OPERATOR_PASS_THROUGH;
}
else {
@@ -498,9 +496,9 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* handle gizmo */
- wmGizmoFnModal modal_fn = mpr->custom_modal ? mpr->custom_modal : mpr->type->modal;
+ wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
if (modal_fn) {
- int modal_retval = modal_fn(C, mpr, event, mtweak->flag);
+ int modal_retval = modal_fn(C, gz, event, mtweak->flag);
if ((modal_retval & OPERATOR_RUNNING_MODAL) == 0) {
gizmo_tweak_finish(C, op, (modal_retval & OPERATOR_CANCELLED) != 0, true);
@@ -520,13 +518,13 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *mmap = ar->gizmo_map;
- wmGizmo *mpr = mmap->mmap_context.highlight;
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmo *gz = gzmap->gzmap_context.highlight;
/* Needed for single click actions which don't enter modal state. */
WM_tooltip_clear(C, CTX_wm_window(C));
- if (!mpr) {
+ if (!gz) {
/* wm_handlers_do_intern shouldn't let this happen */
BLI_assert(0);
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
@@ -535,11 +533,11 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool use_drag_fallback = false;
#ifdef USE_DRAG_DETECT
- use_drag_fallback = !ELEM(mpr->drag_part, -1, mpr->highlight_part);
+ use_drag_fallback = !ELEM(gz->drag_part, -1, gz->highlight_part);
#endif
if (use_drag_fallback == false) {
- if (gizmo_tweak_start_and_finish(C, mmap, mpr, event, NULL)) {
+ if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, NULL)) {
return OPERATOR_FINISHED;
}
}
@@ -547,7 +545,7 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool use_drag_detect = false;
#ifdef USE_DRAG_DETECT
if (use_drag_fallback) {
- wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, mpr->highlight_part);
+ wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, gz->highlight_part);
if (mpop && mpop->type) {
if (mpop->type->modal == NULL) {
use_drag_detect = true;
@@ -557,7 +555,7 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#endif
if (use_drag_detect == false) {
- if (!gizmo_tweak_start(C, mmap, mpr, event)) {
+ if (!gizmo_tweak_start(C, gzmap, gz, event)) {
/* failed to start */
return OPERATOR_PASS_THROUGH;
}
@@ -566,9 +564,9 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
GizmoTweakData *mtweak = MEM_mallocN(sizeof(GizmoTweakData), __func__);
mtweak->init_event = WM_userdef_event_type_from_keymap_type(event->type);
- mtweak->mpr_modal = mmap->mmap_context.highlight;
- mtweak->mgroup = mtweak->mpr_modal->parent_mgroup;
- mtweak->mmap = mmap;
+ mtweak->gz_modal = gzmap->gzmap_context.highlight;
+ mtweak->gzgroup = mtweak->gz_modal->parent_gzgroup;
+ mtweak->gzmap = gzmap;
mtweak->flag = 0;
#ifdef USE_DRAG_DETECT
@@ -603,7 +601,7 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
/** \} */
-static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *mgroupname)
+static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *gzgroupname)
{
wmKeyMap *keymap;
char name[KMAP_MAX_NAME];
@@ -619,7 +617,7 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char
};
- BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", mgroupname);
+ BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", gzgroupname);
keymap = WM_modalkeymap_get(keyconf, name);
/* this function is called for each spacetype, only needs to add map once */
@@ -655,13 +653,13 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char
* Common default keymap for gizmo groups
*/
wmKeyMap *WM_gizmogroup_keymap_common(
- const wmGizmoGroupType *wgt, wmKeyConfig *config)
+ const wmGizmoGroupType *gzgt, wmKeyConfig *config)
{
/* Use area and region id since we might have multiple gizmos with the same name in different areas/regions */
- wmKeyMap *km = WM_keymap_find(config, wgt->name, wgt->mmap_params.spaceid, wgt->mmap_params.regionid);
+ wmKeyMap *km = WM_keymap_find(config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid);
WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
- gizmogroup_tweak_modal_keymap(config, wgt->name);
+ gizmogroup_tweak_modal_keymap(config, gzgt->name);
return km;
}
@@ -670,14 +668,14 @@ wmKeyMap *WM_gizmogroup_keymap_common(
* Variation of #WM_gizmogroup_keymap_common but with keymap items for selection
*/
wmKeyMap *WM_gizmogroup_keymap_common_select(
- const wmGizmoGroupType *wgt, wmKeyConfig *config)
+ const wmGizmoGroupType *gzgt, wmKeyConfig *config)
{
/* Use area and region id since we might have multiple gizmos with the same name in different areas/regions */
- wmKeyMap *km = WM_keymap_find(config, wgt->name, wgt->mmap_params.spaceid, wgt->mmap_params.regionid);
+ wmKeyMap *km = WM_keymap_find(config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid);
WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", EVT_TWEAK_S, KM_ANY, 0, 0);
- gizmogroup_tweak_modal_keymap(config, wgt->name);
+ gizmogroup_tweak_modal_keymap(config, gzgt->name);
wmKeyMapItem *kmi = WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_select", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -699,32 +697,32 @@ wmKeyMap *WM_gizmogroup_keymap_common_select(
* \{ */
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find_ptr(
- struct wmGizmoMapType *mmap_type,
- const wmGizmoGroupType *wgt)
+ struct wmGizmoMapType *gzmap_type,
+ const wmGizmoGroupType *gzgt)
{
/* could use hash lookups as operator types do, for now simple search. */
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
- wgt_ref;
- wgt_ref = wgt_ref->next)
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first;
+ gzgt_ref;
+ gzgt_ref = gzgt_ref->next)
{
- if (wgt_ref->type == wgt) {
- return wgt_ref;
+ if (gzgt_ref->type == gzgt) {
+ return gzgt_ref;
}
}
return NULL;
}
struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find(
- struct wmGizmoMapType *mmap_type,
+ struct wmGizmoMapType *gzmap_type,
const char *idname)
{
/* could use hash lookups as operator types do, for now simple search. */
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
- wgt_ref;
- wgt_ref = wgt_ref->next)
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first;
+ gzgt_ref;
+ gzgt_ref = gzgt_ref->next)
{
- if (STREQ(idname, wgt_ref->type->idname)) {
- return wgt_ref;
+ if (STREQ(idname, gzgt_ref->type->idname)) {
+ return gzgt_ref;
}
}
return NULL;
@@ -734,33 +732,33 @@ struct wmGizmoGroupTypeRef *WM_gizmomaptype_group_find(
* Use this for registering gizmos on startup. For runtime, use #WM_gizmomaptype_group_link_runtime.
*/
wmGizmoGroupTypeRef *WM_gizmomaptype_group_link(
- wmGizmoMapType *mmap_type, const char *idname)
+ wmGizmoMapType *gzmap_type, const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- BLI_assert(wgt != NULL);
- return WM_gizmomaptype_group_link_ptr(mmap_type, wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ BLI_assert(gzgt != NULL);
+ return WM_gizmomaptype_group_link_ptr(gzmap_type, gzgt);
}
wmGizmoGroupTypeRef *WM_gizmomaptype_group_link_ptr(
- wmGizmoMapType *mmap_type, wmGizmoGroupType *wgt)
+ wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
{
- wmGizmoGroupTypeRef *wgt_ref = MEM_callocN(sizeof(wmGizmoGroupTypeRef), "gizmo-group-ref");
- wgt_ref->type = wgt;
- BLI_addtail(&mmap_type->grouptype_refs, wgt_ref);
- return wgt_ref;
+ wmGizmoGroupTypeRef *gzgt_ref = MEM_callocN(sizeof(wmGizmoGroupTypeRef), "gizmo-group-ref");
+ gzgt_ref->type = gzgt;
+ BLI_addtail(&gzmap_type->grouptype_refs, gzgt_ref);
+ return gzgt_ref;
}
void WM_gizmomaptype_group_init_runtime_keymap(
const Main *bmain,
- wmGizmoGroupType *wgt)
+ wmGizmoGroupType *gzgt)
{
/* init keymap - on startup there's an extra call to init keymaps for 'permanent' gizmo-groups */
- wm_gizmogrouptype_setup_keymap(wgt, ((wmWindowManager *)bmain->wm.first)->defaultconf);
+ wm_gizmogrouptype_setup_keymap(gzgt, ((wmWindowManager *)bmain->wm.first)->defaultconf);
}
void WM_gizmomaptype_group_init_runtime(
- const Main *bmain, wmGizmoMapType *mmap_type,
- wmGizmoGroupType *wgt)
+ const Main *bmain, wmGizmoMapType *gzmap_type,
+ wmGizmoGroupType *gzgt)
{
/* now create a gizmo for all existing areas */
for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
@@ -768,12 +766,12 @@ void WM_gizmomaptype_group_init_runtime(
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
for (ARegion *ar = lb->first; ar; ar = ar->next) {
- wmGizmoMap *mmap = ar->gizmo_map;
- if (mmap && mmap->type == mmap_type) {
- wm_gizmogroup_new_from_type(mmap, wgt);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap && gzmap->type == gzmap_type) {
+ wm_gizmogroup_new_from_type(gzmap, gzgt);
/* just add here, drawing will occur on next update */
- wm_gizmomap_highlight_set(mmap, NULL, NULL, 0);
+ wm_gizmomap_highlight_set(gzmap, NULL, NULL, 0);
ED_region_tag_redraw(ar);
}
}
@@ -786,14 +784,14 @@ void WM_gizmomaptype_group_init_runtime(
/**
* Unlike #WM_gizmomaptype_group_unlink this doesn't maintain correct state, simply free.
*/
-void WM_gizmomaptype_group_free(wmGizmoGroupTypeRef *wgt_ref)
+void WM_gizmomaptype_group_free(wmGizmoGroupTypeRef *gzgt_ref)
{
- MEM_freeN(wgt_ref);
+ MEM_freeN(gzgt_ref);
}
void WM_gizmomaptype_group_unlink(
- bContext *C, Main *bmain, wmGizmoMapType *mmap_type,
- const wmGizmoGroupType *wgt)
+ bContext *C, Main *bmain, wmGizmoMapType *gzmap_type,
+ const wmGizmoGroupType *gzgt)
{
/* Free instances. */
for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
@@ -801,14 +799,14 @@ void WM_gizmomaptype_group_unlink(
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
for (ARegion *ar = lb->first; ar; ar = ar->next) {
- wmGizmoMap *mmap = ar->gizmo_map;
- if (mmap && mmap->type == mmap_type) {
- wmGizmoGroup *mgroup, *mgroup_next;
- for (mgroup = mmap->groups.first; mgroup; mgroup = mgroup_next) {
- mgroup_next = mgroup->next;
- if (mgroup->type == wgt) {
- BLI_assert(mgroup->parent_mmap == mmap);
- wm_gizmogroup_free(C, mgroup);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap && gzmap->type == gzmap_type) {
+ wmGizmoGroup *gzgroup, *gzgroup_next;
+ for (gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup_next) {
+ gzgroup_next = gzgroup->next;
+ if (gzgroup->type == gzgt) {
+ BLI_assert(gzgroup->parent_gzmap == gzmap);
+ wm_gizmogroup_free(C, gzgroup);
ED_region_tag_redraw(ar);
}
}
@@ -819,27 +817,27 @@ void WM_gizmomaptype_group_unlink(
}
/* Free types. */
- wmGizmoGroupTypeRef *wgt_ref = WM_gizmomaptype_group_find_ptr(mmap_type, wgt);
- if (wgt_ref) {
- BLI_remlink(&mmap_type->grouptype_refs, wgt_ref);
- WM_gizmomaptype_group_free(wgt_ref);
+ wmGizmoGroupTypeRef *gzgt_ref = WM_gizmomaptype_group_find_ptr(gzmap_type, gzgt);
+ if (gzgt_ref) {
+ BLI_remlink(&gzmap_type->grouptype_refs, gzgt_ref);
+ WM_gizmomaptype_group_free(gzgt_ref);
}
/* Note, we may want to keep this keymap for editing */
- WM_keymap_remove(wgt->keyconf, wgt->keymap);
+ WM_keymap_remove(gzgt->keyconf, gzgt->keymap);
- BLI_assert(WM_gizmomaptype_group_find_ptr(mmap_type, wgt) == NULL);
+ BLI_assert(WM_gizmomaptype_group_find_ptr(gzmap_type, gzgt) == NULL);
}
void wm_gizmogrouptype_setup_keymap(
- wmGizmoGroupType *wgt, wmKeyConfig *keyconf)
+ wmGizmoGroupType *gzgt, wmKeyConfig *keyconf)
{
/* Use flag since setup_keymap may return NULL,
* in that case we better not keep calling it. */
- if (wgt->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
- wgt->keymap = wgt->setup_keymap(wgt, keyconf);
- wgt->keyconf = keyconf;
- wgt->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
+ if (gzgt->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
+ gzgt->keymap = gzgt->setup_keymap(gzgt, keyconf);
+ gzgt->keyconf = keyconf;
+ gzgt->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
}
}
@@ -861,89 +859,89 @@ void wm_gizmogrouptype_setup_keymap(
* \{ */
void WM_gizmo_group_type_add_ptr_ex(
- wmGizmoGroupType *wgt,
- wmGizmoMapType *mmap_type)
+ wmGizmoGroupType *gzgt,
+ wmGizmoMapType *gzmap_type)
{
- WM_gizmomaptype_group_link_ptr(mmap_type, wgt);
+ WM_gizmomaptype_group_link_ptr(gzmap_type, gzgt);
- WM_gizmoconfig_update_tag_init(mmap_type, wgt);
+ WM_gizmoconfig_update_tag_init(gzmap_type, gzgt);
}
void WM_gizmo_group_type_add_ptr(
- wmGizmoGroupType *wgt)
+ wmGizmoGroupType *gzgt)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wgt->mmap_params);
- WM_gizmo_group_type_add_ptr_ex(wgt, mmap_type);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmo_group_type_add_ptr_ex(gzgt, gzmap_type);
}
void WM_gizmo_group_type_add(const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- BLI_assert(wgt != NULL);
- WM_gizmo_group_type_add_ptr(wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ BLI_assert(gzgt != NULL);
+ WM_gizmo_group_type_add_ptr(gzgt);
}
void WM_gizmo_group_type_ensure_ptr_ex(
- wmGizmoGroupType *wgt,
- wmGizmoMapType *mmap_type)
+ wmGizmoGroupType *gzgt,
+ wmGizmoMapType *gzmap_type)
{
- wmGizmoGroupTypeRef *wgt_ref = WM_gizmomaptype_group_find_ptr(mmap_type, wgt);
- if (wgt_ref == NULL) {
- WM_gizmo_group_type_add_ptr_ex(wgt, mmap_type);
+ wmGizmoGroupTypeRef *gzgt_ref = WM_gizmomaptype_group_find_ptr(gzmap_type, gzgt);
+ if (gzgt_ref == NULL) {
+ WM_gizmo_group_type_add_ptr_ex(gzgt, gzmap_type);
}
}
void WM_gizmo_group_type_ensure_ptr(
- wmGizmoGroupType *wgt)
+ wmGizmoGroupType *gzgt)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wgt->mmap_params);
- WM_gizmo_group_type_ensure_ptr_ex(wgt, mmap_type);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmo_group_type_ensure_ptr_ex(gzgt, gzmap_type);
}
void WM_gizmo_group_type_ensure(const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- BLI_assert(wgt != NULL);
- WM_gizmo_group_type_ensure_ptr(wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ BLI_assert(gzgt != NULL);
+ WM_gizmo_group_type_ensure_ptr(gzgt);
}
void WM_gizmo_group_type_remove_ptr_ex(
- struct Main *bmain, wmGizmoGroupType *wgt,
- wmGizmoMapType *mmap_type)
+ struct Main *bmain, wmGizmoGroupType *gzgt,
+ wmGizmoMapType *gzmap_type)
{
- WM_gizmomaptype_group_unlink(NULL, bmain, mmap_type, wgt);
- WM_gizmogrouptype_free_ptr(wgt);
+ WM_gizmomaptype_group_unlink(NULL, bmain, gzmap_type, gzgt);
+ WM_gizmogrouptype_free_ptr(gzgt);
}
void WM_gizmo_group_type_remove_ptr(
- struct Main *bmain, wmGizmoGroupType *wgt)
+ struct Main *bmain, wmGizmoGroupType *gzgt)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wgt->mmap_params);
- WM_gizmo_group_type_remove_ptr_ex(bmain, wgt, mmap_type);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmo_group_type_remove_ptr_ex(bmain, gzgt, gzmap_type);
}
void WM_gizmo_group_type_remove(struct Main *bmain, const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- BLI_assert(wgt != NULL);
- WM_gizmo_group_type_remove_ptr(bmain, wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ BLI_assert(gzgt != NULL);
+ WM_gizmo_group_type_remove_ptr(bmain, gzgt);
}
/* delayed versions */
void WM_gizmo_group_type_unlink_delayed_ptr_ex(
- wmGizmoGroupType *wgt,
- wmGizmoMapType *mmap_type)
+ wmGizmoGroupType *gzgt,
+ wmGizmoMapType *gzmap_type)
{
- WM_gizmoconfig_update_tag_remove(mmap_type, wgt);
+ WM_gizmoconfig_update_tag_remove(gzmap_type, gzgt);
}
void WM_gizmo_group_type_unlink_delayed_ptr(
- wmGizmoGroupType *wgt)
+ wmGizmoGroupType *gzgt)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wgt->mmap_params);
- WM_gizmo_group_type_unlink_delayed_ptr_ex(wgt, mmap_type);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmo_group_type_unlink_delayed_ptr_ex(gzgt, gzmap_type);
}
void WM_gizmo_group_type_unlink_delayed(const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- BLI_assert(wgt != NULL);
- WM_gizmo_group_type_unlink_delayed_ptr(wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ BLI_assert(gzgt != NULL);
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
}
/** \} */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
index 44f5fac4cd4..a44005a7d28 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
@@ -54,11 +54,11 @@ static GHash *global_gizmogrouptype_hash = NULL;
wmGizmoGroupType *WM_gizmogrouptype_find(const char *idname, bool quiet)
{
if (idname[0]) {
- wmGizmoGroupType *wgt;
+ wmGizmoGroupType *gzgt;
- wgt = BLI_ghash_lookup(global_gizmogrouptype_hash, idname);
- if (wgt) {
- return wgt;
+ gzgt = BLI_ghash_lookup(global_gizmogrouptype_hash, idname);
+ if (gzgt) {
+ return gzgt;
}
if (!quiet) {
@@ -82,46 +82,46 @@ void WM_gizmogrouptype_iter(GHashIterator *ghi)
static wmGizmoGroupType *wm_gizmogrouptype_append__begin(void)
{
- wmGizmoGroupType *wgt = MEM_callocN(sizeof(wmGizmoGroupType), "gizmogrouptype");
+ wmGizmoGroupType *gzgt = MEM_callocN(sizeof(wmGizmoGroupType), "gizmogrouptype");
- return wgt;
+ return gzgt;
}
-static void wm_gizmogrouptype_append__end(wmGizmoGroupType *wgt)
+static void wm_gizmogrouptype_append__end(wmGizmoGroupType *gzgt)
{
- BLI_assert(wgt->name != NULL);
- BLI_assert(wgt->idname != NULL);
+ BLI_assert(gzgt->name != NULL);
+ BLI_assert(gzgt->idname != NULL);
- wgt->type_update_flag |= WM_GIZMOMAPTYPE_KEYMAP_INIT;
+ gzgt->type_update_flag |= WM_GIZMOMAPTYPE_KEYMAP_INIT;
/* if not set, use default */
- if (wgt->setup_keymap == NULL) {
- if (wgt->flag & WM_GIZMOGROUPTYPE_SELECT) {
- wgt->setup_keymap = WM_gizmogroup_keymap_common_select;
+ if (gzgt->setup_keymap == NULL) {
+ if (gzgt->flag & WM_GIZMOGROUPTYPE_SELECT) {
+ gzgt->setup_keymap = WM_gizmogroup_keymap_common_select;
}
else {
- wgt->setup_keymap = WM_gizmogroup_keymap_common;
+ gzgt->setup_keymap = WM_gizmogroup_keymap_common;
}
}
- BLI_ghash_insert(global_gizmogrouptype_hash, (void *)wgt->idname, wgt);
+ BLI_ghash_insert(global_gizmogrouptype_hash, (void *)gzgt->idname, gzgt);
}
wmGizmoGroupType *WM_gizmogrouptype_append(
void (*wtfunc)(struct wmGizmoGroupType *))
{
- wmGizmoGroupType *wgt = wm_gizmogrouptype_append__begin();
- wtfunc(wgt);
- wm_gizmogrouptype_append__end(wgt);
- return wgt;
+ wmGizmoGroupType *gzgt = wm_gizmogrouptype_append__begin();
+ wtfunc(gzgt);
+ wm_gizmogrouptype_append__end(gzgt);
+ return gzgt;
}
wmGizmoGroupType *WM_gizmogrouptype_append_ptr(
void (*wtfunc)(struct wmGizmoGroupType *, void *), void *userdata)
{
- wmGizmoGroupType *wgt = wm_gizmogrouptype_append__begin();
- wtfunc(wgt, userdata);
- wm_gizmogrouptype_append__end(wgt);
- return wgt;
+ wmGizmoGroupType *gzgt = wm_gizmogrouptype_append__begin();
+ wtfunc(gzgt, userdata);
+ wm_gizmogrouptype_append__end(gzgt);
+ return gzgt;
}
/**
@@ -129,56 +129,56 @@ wmGizmoGroupType *WM_gizmogrouptype_append_ptr(
* This is most common for C gizmos which are enabled by default.
*/
wmGizmoGroupTypeRef *WM_gizmogrouptype_append_and_link(
- wmGizmoMapType *mmap_type,
+ wmGizmoMapType *gzmap_type,
void (*wtfunc)(struct wmGizmoGroupType *))
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_append(wtfunc);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_append(wtfunc);
- wgt->mmap_params.spaceid = mmap_type->spaceid;
- wgt->mmap_params.regionid = mmap_type->regionid;
+ gzgt->gzmap_params.spaceid = gzmap_type->spaceid;
+ gzgt->gzmap_params.regionid = gzmap_type->regionid;
- return WM_gizmomaptype_group_link_ptr(mmap_type, wgt);
+ return WM_gizmomaptype_group_link_ptr(gzmap_type, gzgt);
}
/**
* Free but don't remove from ghash.
*/
-static void gizmogrouptype_free(wmGizmoGroupType *wgt)
+static void gizmogrouptype_free(wmGizmoGroupType *gzgt)
{
- if (wgt->ext.srna) { /* python gizmo group, allocs own string */
- MEM_freeN((void *)wgt->idname);
+ if (gzgt->ext.srna) { /* python gizmo group, allocs own string */
+ MEM_freeN((void *)gzgt->idname);
}
- MEM_freeN(wgt);
+ MEM_freeN(gzgt);
}
-void WM_gizmogrouptype_free_ptr(wmGizmoGroupType *wgt)
+void WM_gizmogrouptype_free_ptr(wmGizmoGroupType *gzgt)
{
- BLI_assert(wgt == WM_gizmogrouptype_find(wgt->idname, false));
+ BLI_assert(gzgt == WM_gizmogrouptype_find(gzgt->idname, false));
- BLI_ghash_remove(global_gizmogrouptype_hash, wgt->idname, NULL, NULL);
+ BLI_ghash_remove(global_gizmogrouptype_hash, gzgt->idname, NULL, NULL);
- gizmogrouptype_free(wgt);
+ gizmogrouptype_free(gzgt);
/* XXX, TODO, update the world! */
}
bool WM_gizmogrouptype_free(const char *idname)
{
- wmGizmoGroupType *wgt = BLI_ghash_lookup(global_gizmogrouptype_hash, idname);
+ wmGizmoGroupType *gzgt = BLI_ghash_lookup(global_gizmogrouptype_hash, idname);
- if (wgt == NULL) {
+ if (gzgt == NULL) {
return false;
}
- WM_gizmogrouptype_free_ptr(wgt);
+ WM_gizmogrouptype_free_ptr(gzgt);
return true;
}
-static void wm_gizmogrouptype_ghash_free_cb(wmGizmoGroupType *wgt)
+static void wm_gizmogrouptype_ghash_free_cb(wmGizmoGroupType *gzgt)
{
- gizmogrouptype_free(wgt);
+ gizmogrouptype_free(gzgt);
}
void wm_gizmogrouptype_free(void)
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
index 5eed4f2bda2..d4a9dc4f54c 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
@@ -40,14 +40,14 @@ struct GHashIterator;
bool wm_gizmo_select_set_ex(
- struct wmGizmoMap *mmap, struct wmGizmo *mpr, bool select,
+ struct wmGizmoMap *gzmap, struct wmGizmo *gz, bool select,
bool use_array, bool use_callback);
-bool wm_gizmo_select_and_highlight(bContext *C, struct wmGizmoMap *mmap, struct wmGizmo *mpr);
+bool wm_gizmo_select_and_highlight(bContext *C, struct wmGizmoMap *gzmap, struct wmGizmo *gz);
-void wm_gizmo_calculate_scale(struct wmGizmo *mpr, const bContext *C);
-void wm_gizmo_update(struct wmGizmo *mpr, const bContext *C, const bool refresh_map);
+void wm_gizmo_calculate_scale(struct wmGizmo *gz, const bContext *C);
+void wm_gizmo_update(struct wmGizmo *gz, const bContext *C, const bool refresh_map);
-int wm_gizmo_is_visible(struct wmGizmo *mpr);
+int wm_gizmo_is_visible(struct wmGizmo *gz);
enum {
WM_GIZMO_IS_VISIBLE_UPDATE = (1 << 0),
WM_GIZMO_IS_VISIBLE_DRAW = (1 << 1),
@@ -66,20 +66,20 @@ enum {
};
struct wmGizmoGroup *wm_gizmogroup_new_from_type(
- struct wmGizmoMap *mmap, struct wmGizmoGroupType *wgt);
-void wm_gizmogroup_free(bContext *C, struct wmGizmoGroup *mgroup);
-void wm_gizmogroup_gizmo_register(struct wmGizmoGroup *mgroup, struct wmGizmo *mpr);
+ struct wmGizmoMap *gzmap, struct wmGizmoGroupType *gzgt);
+void wm_gizmogroup_free(bContext *C, struct wmGizmoGroup *gzgroup);
+void wm_gizmogroup_gizmo_register(struct wmGizmoGroup *gzgroup, struct wmGizmo *gz);
struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(
- const struct wmGizmoGroup *mgroup, struct bContext *C, const struct wmEvent *event,
+ const struct wmGizmoGroup *gzgroup, struct bContext *C, const struct wmEvent *event,
int *r_part);
void wm_gizmogroup_intersectable_gizmos_to_list(
- const struct wmGizmoGroup *mgroup, struct ListBase *listbase);
-void wm_gizmogroup_ensure_initialized(struct wmGizmoGroup *mgroup, const struct bContext *C);
+ const struct wmGizmoGroup *gzgroup, struct ListBase *listbase);
+void wm_gizmogroup_ensure_initialized(struct wmGizmoGroup *gzgroup, const struct bContext *C);
bool wm_gizmogroup_is_visible_in_drawstep(
- const struct wmGizmoGroup *mgroup, const eWM_GizmoFlagMapDrawStep drawstep);
+ const struct wmGizmoGroup *gzgroup, const eWM_GizmoFlagMapDrawStep drawstep);
void wm_gizmogrouptype_setup_keymap(
- struct wmGizmoGroupType *wgt, struct wmKeyConfig *keyconf);
+ struct wmGizmoGroupType *gzgt, struct wmKeyConfig *keyconf);
/* -------------------------------------------------------------------- */
@@ -116,7 +116,7 @@ struct wmGizmoMap {
short event_grabcursor;
/* until we have nice cursor push/pop API. */
int last_cursor;
- } mmap_context;
+ } gzmap_context;
};
/**
@@ -135,10 +135,10 @@ struct wmGizmoMapType {
eWM_GizmoFlagMapTypeUpdateFlag type_update_flag;
};
-void wm_gizmomap_select_array_clear(struct wmGizmoMap *mmap);
-bool wm_gizmomap_deselect_all(struct wmGizmoMap *mmap);
-void wm_gizmomap_select_array_shrink(struct wmGizmoMap *mmap, int len_subtract);
-void wm_gizmomap_select_array_push_back(struct wmGizmoMap *mmap, wmGizmo *mpr);
-void wm_gizmomap_select_array_remove(struct wmGizmoMap *mmap, wmGizmo *mpr);
+void wm_gizmomap_select_array_clear(struct wmGizmoMap *gzmap);
+bool wm_gizmomap_deselect_all(struct wmGizmoMap *gzmap);
+void wm_gizmomap_select_array_shrink(struct wmGizmoMap *gzmap, int len_subtract);
+void wm_gizmomap_select_array_push_back(struct wmGizmoMap *gzmap, wmGizmo *gz);
+void wm_gizmomap_select_array_remove(struct wmGizmoMap *gzmap, wmGizmo *gz);
#endif
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 9da1591d535..0b54f0cbec1 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -75,7 +75,7 @@ typedef enum eWM_GizmoFlagGroupTypeGlobalFlag {
WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE = (1 << 1),
} eWM_GizmoFlagGroupTypeGlobalFlag;
-static eWM_GizmoFlagGroupTypeGlobalFlag wm_mmap_type_update_flag = 0;
+static eWM_GizmoFlagGroupTypeGlobalFlag wm_gzmap_type_update_flag = 0;
/**
* Gizmo-map update tagging.
@@ -94,9 +94,9 @@ enum {
*
* \{ */
-static void wm_gizmomap_select_array_ensure_len_alloc(wmGizmoMap *mmap, int len)
+static void wm_gizmomap_select_array_ensure_len_alloc(wmGizmoMap *gzmap, int len)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
if (len <= msel->len_alloc) {
return;
}
@@ -104,20 +104,20 @@ static void wm_gizmomap_select_array_ensure_len_alloc(wmGizmoMap *mmap, int len)
msel->len_alloc = len;
}
-void wm_gizmomap_select_array_clear(wmGizmoMap *mmap)
+void wm_gizmomap_select_array_clear(wmGizmoMap *gzmap)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
MEM_SAFE_FREE(msel->items);
msel->len = 0;
msel->len_alloc = 0;
}
-void wm_gizmomap_select_array_shrink(wmGizmoMap *mmap, int len_subtract)
+void wm_gizmomap_select_array_shrink(wmGizmoMap *gzmap, int len_subtract)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
msel->len -= len_subtract;
if (msel->len <= 0) {
- wm_gizmomap_select_array_clear(mmap);
+ wm_gizmomap_select_array_clear(gzmap);
}
else {
if (msel->len < msel->len_alloc / 2) {
@@ -127,27 +127,27 @@ void wm_gizmomap_select_array_shrink(wmGizmoMap *mmap, int len_subtract)
}
}
-void wm_gizmomap_select_array_push_back(wmGizmoMap *mmap, wmGizmo *mpr)
+void wm_gizmomap_select_array_push_back(wmGizmoMap *gzmap, wmGizmo *gz)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
BLI_assert(msel->len <= msel->len_alloc);
if (msel->len == msel->len_alloc) {
msel->len_alloc = (msel->len + 1) * 2;
msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len_alloc);
}
- msel->items[msel->len++] = mpr;
+ msel->items[msel->len++] = gz;
}
-void wm_gizmomap_select_array_remove(wmGizmoMap *mmap, wmGizmo *mpr)
+void wm_gizmomap_select_array_remove(wmGizmoMap *gzmap, wmGizmo *gz)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
/* remove gizmo from selected_gizmos array */
for (int i = 0; i < msel->len; i++) {
- if (msel->items[i] == mpr) {
+ if (msel->items[i] == gz) {
for (int j = i; j < (msel->len - 1); j++) {
msel->items[j] = msel->items[j + 1];
}
- wm_gizmomap_select_array_shrink(mmap, 1);
+ wm_gizmomap_select_array_shrink(gzmap, 1);
break;
}
}
@@ -166,84 +166,84 @@ void wm_gizmomap_select_array_remove(wmGizmoMap *mmap, wmGizmo *mpr)
* Creates a gizmo-map with all registered gizmos for that type
*/
wmGizmoMap *WM_gizmomap_new_from_type(
- const struct wmGizmoMapType_Params *mmap_params)
+ const struct wmGizmoMapType_Params *gzmap_params)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(mmap_params);
- wmGizmoMap *mmap;
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(gzmap_params);
+ wmGizmoMap *gzmap;
- mmap = MEM_callocN(sizeof(wmGizmoMap), "GizmoMap");
- mmap->type = mmap_type;
- WM_gizmomap_tag_refresh(mmap);
+ gzmap = MEM_callocN(sizeof(wmGizmoMap), "GizmoMap");
+ gzmap->type = gzmap_type;
+ WM_gizmomap_tag_refresh(gzmap);
/* create all gizmo-groups for this gizmo-map. We may create an empty one
* too in anticipation of gizmos from operators etc */
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first; wgt_ref; wgt_ref = wgt_ref->next) {
- wm_gizmogroup_new_from_type(mmap, wgt_ref->type);
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first; gzgt_ref; gzgt_ref = gzgt_ref->next) {
+ wm_gizmogroup_new_from_type(gzmap, gzgt_ref->type);
}
- return mmap;
+ return gzmap;
}
-void wm_gizmomap_remove(wmGizmoMap *mmap)
+void wm_gizmomap_remove(wmGizmoMap *gzmap)
{
/* Clear first so further calls don't waste time trying to maintain correct array state. */
- wm_gizmomap_select_array_clear(mmap);
+ wm_gizmomap_select_array_clear(gzmap);
- for (wmGizmoGroup *mgroup = mmap->groups.first, *mgroup_next; mgroup; mgroup = mgroup_next) {
- mgroup_next = mgroup->next;
- BLI_assert(mgroup->parent_mmap == mmap);
- wm_gizmogroup_free(NULL, mgroup);
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup; gzgroup = gzgroup_next) {
+ gzgroup_next = gzgroup->next;
+ BLI_assert(gzgroup->parent_gzmap == gzmap);
+ wm_gizmogroup_free(NULL, gzgroup);
}
- BLI_assert(BLI_listbase_is_empty(&mmap->groups));
+ BLI_assert(BLI_listbase_is_empty(&gzmap->groups));
- MEM_freeN(mmap);
+ MEM_freeN(gzmap);
}
wmGizmoGroup *WM_gizmomap_group_find(
- struct wmGizmoMap *mmap,
+ struct wmGizmoMap *gzmap,
const char *idname)
{
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- if (wgt) {
- return WM_gizmomap_group_find_ptr(mmap, wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ if (gzgt) {
+ return WM_gizmomap_group_find_ptr(gzmap, gzgt);
}
return NULL;
}
wmGizmoGroup *WM_gizmomap_group_find_ptr(
- struct wmGizmoMap *mmap,
- const struct wmGizmoGroupType *wgt)
+ struct wmGizmoMap *gzmap,
+ const struct wmGizmoGroupType *gzgt)
{
- for (wmGizmoGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- if (mgroup->type == wgt) {
- return mgroup;
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
+ if (gzgroup->type == gzgt) {
+ return gzgroup;
}
}
return NULL;
}
-const ListBase *WM_gizmomap_group_list(wmGizmoMap *mmap)
+const ListBase *WM_gizmomap_group_list(wmGizmoMap *gzmap)
{
- return &mmap->groups;
+ return &gzmap->groups;
}
-bool WM_gizmomap_is_any_selected(const wmGizmoMap *mmap)
+bool WM_gizmomap_is_any_selected(const wmGizmoMap *gzmap)
{
- return mmap->mmap_context.select.len != 0;
+ return gzmap->gzmap_context.select.len != 0;
}
/**
* \note We could use a callback to define bounds, for now just use matrix location.
*/
bool WM_gizmomap_minmax(
- const wmGizmoMap *mmap, bool UNUSED(use_hidden), bool use_select,
+ const wmGizmoMap *gzmap, bool UNUSED(use_hidden), bool use_select,
float r_min[3], float r_max[3])
{
if (use_select) {
int i;
- for (i = 0; i < mmap->mmap_context.select.len; i++) {
- minmax_v3v3_v3(r_min, r_max, mmap->mmap_context.select.items[i]->matrix_basis[3]);
+ for (i = 0; i < gzmap->gzmap_context.select.len; i++) {
+ minmax_v3v3_v3(r_min, r_max, gzmap->gzmap_context.select.items[i]->matrix_basis[3]);
}
return i != 0;
}
@@ -255,7 +255,7 @@ bool WM_gizmomap_minmax(
}
/**
- * Creates and returns idname hash table for (visible) gizmos in \a mmap
+ * Creates and returns idname hash table for (visible) gizmos in \a gzmap
*
* \param poll Polling function for excluding gizmos.
* \param data Custom data passed to \a poll
@@ -264,20 +264,20 @@ bool WM_gizmomap_minmax(
* best we use an iterator function instead of a hash.
*/
static GHash *WM_gizmomap_gizmo_hash_new(
- const bContext *C, wmGizmoMap *mmap,
+ const bContext *C, wmGizmoMap *gzmap,
bool (*poll)(const wmGizmo *, void *),
void *data, const bool include_hidden)
{
GHash *hash = BLI_ghash_ptr_new(__func__);
/* collect gizmos */
- for (wmGizmoGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- if (WM_gizmo_group_type_poll(C, mgroup->type)) {
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if ((include_hidden || (mpr->flag & WM_GIZMO_HIDDEN) == 0) &&
- (!poll || poll(mpr, data)))
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
+ if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if ((include_hidden || (gz->flag & WM_GIZMO_HIDDEN) == 0) &&
+ (!poll || poll(gz, data)))
{
- BLI_ghash_insert(hash, mpr, mpr);
+ BLI_ghash_insert(hash, gz, gz);
}
}
}
@@ -286,12 +286,12 @@ static GHash *WM_gizmomap_gizmo_hash_new(
return hash;
}
-void WM_gizmomap_tag_refresh(wmGizmoMap *mmap)
+void WM_gizmomap_tag_refresh(wmGizmoMap *gzmap)
{
- if (mmap) {
+ if (gzmap) {
/* We might want only to refresh some, for tag all steps. */
for (int i = 0; i < WM_GIZMOMAP_DRAWSTEP_MAX; i++) {
- mmap->update_flag[i] |= (
+ gzmap->update_flag[i] |= (
GIZMOMAP_IS_PREPARE_DRAW |
GIZMOMAP_IS_REFRESH_CALLBACK);
}
@@ -299,11 +299,11 @@ void WM_gizmomap_tag_refresh(wmGizmoMap *mmap)
}
static bool gizmo_prepare_drawing(
- wmGizmoMap *mmap, wmGizmo *mpr,
+ wmGizmoMap *gzmap, wmGizmo *gz,
const bContext *C, ListBase *draw_gizmos,
const eWM_GizmoFlagMapDrawStep drawstep)
{
- int do_draw = wm_gizmo_is_visible(mpr);
+ int do_draw = wm_gizmo_is_visible(gz);
if (do_draw == 0) {
/* skip */
}
@@ -311,10 +311,10 @@ static bool gizmo_prepare_drawing(
/* Ensure we get RNA updates */
if (do_draw & WM_GIZMO_IS_VISIBLE_UPDATE) {
/* hover gizmos need updating, even if we don't draw them */
- wm_gizmo_update(mpr, C, (mmap->update_flag[drawstep] & GIZMOMAP_IS_PREPARE_DRAW) != 0);
+ wm_gizmo_update(gz, C, (gzmap->update_flag[drawstep] & GIZMOMAP_IS_PREPARE_DRAW) != 0);
}
if (do_draw & WM_GIZMO_IS_VISIBLE_DRAW) {
- BLI_addhead(draw_gizmos, BLI_genericNodeN(mpr));
+ BLI_addhead(draw_gizmos, BLI_genericNodeN(gz));
}
return true;
}
@@ -323,23 +323,23 @@ static bool gizmo_prepare_drawing(
}
/**
- * Update gizmos of \a mmap to prepare for drawing. Adds all gizmos that
+ * Update gizmos of \a gzmap to prepare for drawing. Adds all gizmos that
* should be drawn to list \a draw_gizmos, note that added items need freeing.
*/
static void gizmomap_prepare_drawing(
- wmGizmoMap *mmap, const bContext *C, ListBase *draw_gizmos,
+ wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos,
const eWM_GizmoFlagMapDrawStep drawstep)
{
- if (!mmap || BLI_listbase_is_empty(&mmap->groups))
+ if (!gzmap || BLI_listbase_is_empty(&gzmap->groups))
return;
- wmGizmo *mpr_modal = mmap->mmap_context.modal;
+ wmGizmo *gz_modal = gzmap->gzmap_context.modal;
/* only active gizmo needs updating */
- if (mpr_modal) {
- if ((mpr_modal->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) {
- if (wm_gizmogroup_is_visible_in_drawstep(mpr_modal->parent_mgroup, drawstep)) {
- if (gizmo_prepare_drawing(mmap, mpr_modal, C, draw_gizmos, drawstep)) {
- mmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW;
+ if (gz_modal) {
+ if ((gz_modal->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) {
+ if (wm_gizmogroup_is_visible_in_drawstep(gz_modal->parent_gzgroup, drawstep)) {
+ if (gizmo_prepare_drawing(gzmap, gz_modal, C, draw_gizmos, drawstep)) {
+ gzmap->update_flag[drawstep] &= ~GIZMOMAP_IS_PREPARE_DRAW;
}
}
/* don't draw any other gizmos */
@@ -347,46 +347,46 @@ static void gizmomap_prepare_drawing(
}
}
- for (wmGizmoGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
/* check group visibility - drawstep first to avoid unnecessary call of group poll callback */
- if (!wm_gizmogroup_is_visible_in_drawstep(mgroup, drawstep) ||
- !WM_gizmo_group_type_poll(C, mgroup->type))
+ if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep) ||
+ !WM_gizmo_group_type_poll(C, gzgroup->type))
{
continue;
}
/* needs to be initialized on first draw */
/* XXX weak: Gizmo-group may skip refreshing if it's invisible (map gets untagged nevertheless) */
- if (mmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK) {
+ if (gzmap->update_flag[drawstep] & GIZMOMAP_IS_REFRESH_CALLBACK) {
/* force refresh again. */
- mgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
+ gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
}
/* Calls `setup`, `setup_keymap` and `refresh` if they're defined. */
- wm_gizmogroup_ensure_initialized(mgroup, C);
+ wm_gizmogroup_ensure_initialized(gzgroup, C);
/* prepare drawing */
- if (mgroup->type->draw_prepare) {
- mgroup->type->draw_prepare(C, mgroup);
+ if (gzgroup->type->draw_prepare) {
+ gzgroup->type->draw_prepare(C, gzgroup);
}
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- gizmo_prepare_drawing(mmap, mpr, C, draw_gizmos, drawstep);
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ gizmo_prepare_drawing(gzmap, gz, C, draw_gizmos, drawstep);
}
}
- mmap->update_flag[drawstep] &=
+ gzmap->update_flag[drawstep] &=
~(GIZMOMAP_IS_REFRESH_CALLBACK |
GIZMOMAP_IS_PREPARE_DRAW);
}
/**
- * Draw all visible gizmos in \a mmap.
+ * Draw all visible gizmos in \a gzmap.
* Uses global draw_gizmos listbase.
*/
-static void gizmos_draw_list(const wmGizmoMap *mmap, const bContext *C, ListBase *draw_gizmos)
+static void gizmos_draw_list(const wmGizmoMap *gzmap, const bContext *C, ListBase *draw_gizmos)
{
/* Can be empty if we're dynamically added and removed. */
- if ((mmap == NULL) || BLI_listbase_is_empty(&mmap->groups)) {
+ if ((gzmap == NULL) || BLI_listbase_is_empty(&gzmap->groups)) {
return;
}
@@ -397,13 +397,13 @@ static void gizmos_draw_list(const wmGizmoMap *mmap, const bContext *C, ListBase
/* draw_gizmos contains all visible gizmos - draw them */
for (LinkData *link = draw_gizmos->first, *link_next; link; link = link_next) {
- wmGizmo *mpr = link->data;
+ wmGizmo *gz = link->data;
link_next = link->next;
- bool is_depth = (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
+ bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
/* Weak! since we don't 100% support depth yet (select ignores depth) always show highlighted */
- if (is_depth && (mpr->state & WM_GIZMO_STATE_HIGHLIGHT)) {
+ if (is_depth && (gz->state & WM_GIZMO_STATE_HIGHLIGHT)) {
is_depth = false;
}
@@ -424,7 +424,7 @@ static void gizmos_draw_list(const wmGizmoMap *mmap, const bContext *C, ListBase
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
- mpr->type->draw(C, mpr);
+ gz->type->draw(C, gz);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
@@ -439,7 +439,7 @@ static void gizmos_draw_list(const wmGizmoMap *mmap, const bContext *C, ListBase
}
void WM_gizmomap_draw(
- wmGizmoMap *mmap, const bContext *C,
+ wmGizmoMap *gzmap, const bContext *C,
const eWM_GizmoFlagMapDrawStep drawstep)
{
if (!WM_gizmo_context_check_drawstep(C, drawstep)) {
@@ -448,24 +448,32 @@ void WM_gizmomap_draw(
ListBase draw_gizmos = {NULL};
- gizmomap_prepare_drawing(mmap, C, &draw_gizmos, drawstep);
- gizmos_draw_list(mmap, C, &draw_gizmos);
+ gizmomap_prepare_drawing(gzmap, C, &draw_gizmos, drawstep);
+ gizmos_draw_list(gzmap, C, &draw_gizmos);
BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
}
-static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmos)
+static void gizmo_draw_select_3D_loop(
+ const bContext *C, ListBase *visible_gizmos,
+ const wmGizmo *gz_stop)
{
int select_id = 0;
- wmGizmo *mpr;
+ wmGizmo *gz;
/* TODO(campbell): this depends on depth buffer being written to, currently broken for the 3D view. */
bool is_depth_prev = false;
bool is_depth_skip_prev = false;
- for (LinkData *link = visible_gizmos->first; link; link = link->next) {
- mpr = link->data;
+ for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
+ gz = link->data;
+ if (gz == gz_stop) {
+ break;
+ }
+ if (gz->type->draw_select == NULL) {
+ continue;
+ }
- bool is_depth = (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
+ bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
if (is_depth == is_depth_prev) {
/* pass */
}
@@ -478,7 +486,7 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
}
is_depth_prev = is_depth;
}
- bool is_depth_skip = (mpr->flag & WM_GIZMO_SELECT_BACKGROUND) != 0;
+ bool is_depth_skip = (gz->flag & WM_GIZMO_SELECT_BACKGROUND) != 0;
if (is_depth_skip == is_depth_skip_prev) {
/* pass */
}
@@ -489,10 +497,7 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
- mpr->type->draw_select(C, mpr, select_id << 8);
-
-
- select_id++;
+ gz->type->draw_select(C, gz, select_id << 8);
}
if (is_depth_prev) {
@@ -505,7 +510,7 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
static int gizmo_find_intersected_3d_intern(
ListBase *visible_gizmos, const bContext *C, const int co[2],
- const int hotspot)
+ const int hotspot, const wmGizmo *gz_stop)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -525,13 +530,13 @@ static int gizmo_find_intersected_3d_intern(
else
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_ALL, 0);
/* do the drawing */
- gizmo_draw_select_3D_loop(C, visible_gizmos);
+ gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
hits = GPU_select_end();
if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- gizmo_draw_select_3D_loop(C, visible_gizmos);
+ gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
GPU_select_end();
}
@@ -552,36 +557,56 @@ static wmGizmo *gizmo_find_intersected_3d(
wmGizmo *result = NULL;
int hit = -1;
- int hotspot_radii[] = {
- 3 * U.pixelsize,
- /* This runs on mouse move, careful doing too many tests! */
- 10 * U.pixelsize,
- };
-
*r_part = 0;
/* set up view matrices */
view3d_operator_needs_opengl(C);
- hit = -1;
-
- for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
- hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i]);
- if (hit != -1) {
- break;
+ /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
+ bool has_3d = false;
+ {
+ int select_id = 0;
+ for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
+ wmGizmo *gz = link->data;
+ if (gz->type->test_select) {
+ if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
+ hit = select_id;
+ result = gz;
+ break;
+ }
+ }
+ else {
+ has_3d = true;
+ }
}
}
- if (hit != -1) {
- LinkData *link = BLI_findlink(visible_gizmos, hit >> 8);
- if (link != NULL) {
- *r_part = hit & 255;
- result = link->data;
+ /* Search for 3D intersections if they're before 2D that have been found (if any).
+ * This way we always use the first hit. */
+ if (has_3d) {
+ const int hotspot_radii[] = {
+ 3 * U.pixelsize,
+ /* This runs on mouse move, careful doing too many tests! */
+ 10 * U.pixelsize,
+ };
+ for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
+ hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i], result);
+ if (hit != -1) {
+ break;
+ }
}
- else {
- /* All gizmos should use selection ID they're given as part of the callback,
- * if they don't it will attempt tp lookup non-existing index. */
- BLI_assert(0);
+
+ if (hit != -1) {
+ LinkData *link = BLI_findlink(visible_gizmos, hit >> 8);
+ if (link != NULL) {
+ *r_part = hit & 255;
+ result = link->data;
+ }
+ else {
+ /* All gizmos should use selection ID they're given as part of the callback,
+ * if they don't it will attempt tp lookup non-existing index. */
+ BLI_assert(0);
+ }
}
}
@@ -593,10 +618,10 @@ static wmGizmo *gizmo_find_intersected_3d(
* 3D ones (could check for smallest screen-space distance but not needed right now).
*/
wmGizmo *wm_gizmomap_highlight_find(
- wmGizmoMap *mmap, bContext *C, const wmEvent *event,
+ wmGizmoMap *gzmap, bContext *C, const wmEvent *event,
int *r_part)
{
- wmGizmo *mpr = NULL;
+ wmGizmo *gz = NULL;
ListBase visible_3d_gizmos = {NULL};
bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
@@ -604,18 +629,18 @@ wmGizmo *wm_gizmomap_highlight_find(
do_step[i] = WM_gizmo_context_check_drawstep(C, i);
}
- for (wmGizmoGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
/* If it were important we could initialize here,
* but this only happens when events are handled before drawing,
* just skip to keep code-path for initializing gizmos simple. */
- if ((mgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0) {
+ if ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0) {
continue;
}
- if (WM_gizmo_group_type_poll(C, mgroup->type)) {
+ if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
eWM_GizmoFlagMapDrawStep step;
- if (mgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
+ if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
step = WM_GIZMOMAP_DRAWSTEP_3D;
}
else {
@@ -623,17 +648,17 @@ wmGizmo *wm_gizmomap_highlight_find(
}
if (do_step[step]) {
- if ((mmap->update_flag[step] & GIZMOMAP_IS_REFRESH_CALLBACK) &&
- (mgroup->type->refresh != NULL))
+ if ((gzmap->update_flag[step] & GIZMOMAP_IS_REFRESH_CALLBACK) &&
+ (gzgroup->type->refresh != NULL))
{
- mgroup->type->refresh(C, mgroup);
+ gzgroup->type->refresh(C, gzgroup);
/* cleared below */
}
if (step == WM_GIZMOMAP_DRAWSTEP_3D) {
- wm_gizmogroup_intersectable_gizmos_to_list(mgroup, &visible_3d_gizmos);
+ wm_gizmogroup_intersectable_gizmos_to_list(gzgroup, &visible_3d_gizmos);
}
else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
- if ((mpr = wm_gizmogroup_find_intersected_gizmo(mgroup, C, event, r_part))) {
+ if ((gz = wm_gizmogroup_find_intersected_gizmo(gzgroup, C, event, r_part))) {
break;
}
}
@@ -643,32 +668,32 @@ wmGizmo *wm_gizmomap_highlight_find(
if (!BLI_listbase_is_empty(&visible_3d_gizmos)) {
/* 2D gizmos get priority. */
- if (mpr == NULL) {
- mpr = gizmo_find_intersected_3d(C, event->mval, &visible_3d_gizmos, r_part);
+ if (gz == NULL) {
+ gz = gizmo_find_intersected_3d(C, event->mval, &visible_3d_gizmos, r_part);
}
BLI_freelistN(&visible_3d_gizmos);
}
- mmap->update_flag[WM_GIZMOMAP_DRAWSTEP_3D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
- mmap->update_flag[WM_GIZMOMAP_DRAWSTEP_2D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
+ gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_3D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
+ gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_2D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
- return mpr;
+ return gz;
}
-void WM_gizmomap_add_handlers(ARegion *ar, wmGizmoMap *mmap)
+void WM_gizmomap_add_handlers(ARegion *ar, wmGizmoMap *gzmap)
{
wmEventHandler *handler;
for (handler = ar->handlers.first; handler; handler = handler->next) {
- if (handler->gizmo_map == mmap) {
+ if (handler->gizmo_map == gzmap) {
return;
}
}
handler = MEM_callocN(sizeof(wmEventHandler), "gizmo handler");
- BLI_assert(mmap == ar->gizmo_map);
- handler->gizmo_map = mmap;
+ BLI_assert(gzmap == ar->gizmo_map);
+ handler->gizmo_map = gzmap;
BLI_addtail(&ar->handlers, handler);
}
@@ -682,8 +707,8 @@ void wm_gizmomaps_handled_modal_update(
return;
}
- wmGizmoMap *mmap = handler->op_region->gizmo_map;
- wmGizmo *mpr = wm_gizmomap_modal_get(mmap);
+ wmGizmoMap *gzmap = handler->op_region->gizmo_map;
+ wmGizmo *gz = wm_gizmomap_modal_get(gzmap);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
@@ -691,11 +716,11 @@ void wm_gizmomaps_handled_modal_update(
/* regular update for running operator */
if (modal_running) {
- wmGizmoOpElem *mpop = mpr ? WM_gizmo_operator_get(mpr, mpr->highlight_part) : NULL;
- if (mpr && mpop && (mpop->type != NULL) && (mpop->type == handler->op->type)) {
- wmGizmoFnModal modal_fn = mpr->custom_modal ? mpr->custom_modal : mpr->type->modal;
+ wmGizmoOpElem *mpop = gz ? WM_gizmo_operator_get(gz, gz->highlight_part) : NULL;
+ if (gz && mpop && (mpop->type != NULL) && (mpop->type == handler->op->type)) {
+ wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal;
if (modal_fn != NULL) {
- int retval = modal_fn(C, mpr, event, 0);
+ int retval = modal_fn(C, gz, event, 0);
/* The gizmo is tried to the operator, we can't choose when to exit. */
BLI_assert(retval & OPERATOR_RUNNING_MODAL);
UNUSED_VARS_NDEBUG(retval);
@@ -704,14 +729,14 @@ void wm_gizmomaps_handled_modal_update(
}
/* operator not running anymore */
else {
- wm_gizmomap_highlight_set(mmap, C, NULL, 0);
- if (mpr) {
+ wm_gizmomap_highlight_set(gzmap, C, NULL, 0);
+ if (gz) {
/* This isn't defined if it ends because of success of cancel, we may want to change. */
bool cancel = true;
- if (mpr->type->exit) {
- mpr->type->exit(C, mpr, cancel);
+ if (gz->type->exit) {
+ gz->type->exit(C, gz, cancel);
}
- wm_gizmomap_modal_set(mmap, C, mpr, NULL, false);
+ wm_gizmomap_modal_set(gzmap, C, gz, NULL, false);
}
}
@@ -721,58 +746,58 @@ void wm_gizmomaps_handled_modal_update(
}
/**
- * Deselect all selected gizmos in \a mmap.
+ * Deselect all selected gizmos in \a gzmap.
* \return if selection has changed.
*/
-bool wm_gizmomap_deselect_all(wmGizmoMap *mmap)
+bool wm_gizmomap_deselect_all(wmGizmoMap *gzmap)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
if (msel->items == NULL || msel->len == 0) {
return false;
}
for (int i = 0; i < msel->len; i++) {
- wm_gizmo_select_set_ex(mmap, msel->items[i], false, false, true);
+ wm_gizmo_select_set_ex(gzmap, msel->items[i], false, false, true);
}
- wm_gizmomap_select_array_clear(mmap);
+ wm_gizmomap_select_array_clear(gzmap);
/* always return true, we already checked
* if there's anything to deselect */
return true;
}
-BLI_INLINE bool gizmo_selectable_poll(const wmGizmo *mpr, void *UNUSED(data))
+BLI_INLINE bool gizmo_selectable_poll(const wmGizmo *gz, void *UNUSED(data))
{
- return (mpr->parent_mgroup->type->flag & WM_GIZMOGROUPTYPE_SELECT);
+ return (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_SELECT);
}
/**
- * Select all selectable gizmos in \a mmap.
+ * Select all selectable gizmos in \a gzmap.
* \return if selection has changed.
*/
static bool wm_gizmomap_select_all_intern(
- bContext *C, wmGizmoMap *mmap)
+ bContext *C, wmGizmoMap *gzmap)
{
- wmGizmoMapSelectState *msel = &mmap->mmap_context.select;
+ wmGizmoMapSelectState *msel = &gzmap->gzmap_context.select;
/* GHash is used here to avoid having to loop over all gizmos twice (once to
* get tot_sel for allocating, once for actually selecting). Instead we collect
* selectable gizmos in hash table and use this to get tot_sel and do selection */
- GHash *hash = WM_gizmomap_gizmo_hash_new(C, mmap, gizmo_selectable_poll, NULL, true);
+ GHash *hash = WM_gizmomap_gizmo_hash_new(C, gzmap, gizmo_selectable_poll, NULL, true);
GHashIterator gh_iter;
int i;
bool changed = false;
- wm_gizmomap_select_array_ensure_len_alloc(mmap, BLI_ghash_len(hash));
+ wm_gizmomap_select_array_ensure_len_alloc(gzmap, BLI_ghash_len(hash));
GHASH_ITER_INDEX (gh_iter, hash, i) {
- wmGizmo *mpr_iter = BLI_ghashIterator_getValue(&gh_iter);
- WM_gizmo_select_set(mmap, mpr_iter, true);
+ wmGizmo *gz_iter = BLI_ghashIterator_getValue(&gh_iter);
+ WM_gizmo_select_set(gzmap, gz_iter, true);
}
/* highlight first gizmo */
- wm_gizmomap_highlight_set(mmap, C, msel->items[0], msel->items[0]->highlight_part);
+ wm_gizmomap_highlight_set(gzmap, C, msel->items[0], msel->items[0]->highlight_part);
BLI_assert(BLI_ghash_len(hash) == msel->len);
@@ -781,21 +806,21 @@ static bool wm_gizmomap_select_all_intern(
}
/**
- * Select/Deselect all selectable gizmos in \a mmap.
+ * Select/Deselect all selectable gizmos in \a gzmap.
* \return if selection has changed.
*
* TODO select all by type
*/
-bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *mmap, const int action)
+bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
{
bool changed = false;
switch (action) {
case SEL_SELECT:
- changed = wm_gizmomap_select_all_intern(C, mmap);
+ changed = wm_gizmomap_select_all_intern(C, gzmap);
break;
case SEL_DESELECT:
- changed = wm_gizmomap_deselect_all(mmap);
+ changed = wm_gizmomap_deselect_all(gzmap);
break;
default:
BLI_assert(0);
@@ -846,11 +871,11 @@ void wm_gizmomap_handler_context(bContext *C, wmEventHandler *handler)
}
}
-bool WM_gizmomap_cursor_set(const wmGizmoMap *mmap, wmWindow *win)
+bool WM_gizmomap_cursor_set(const wmGizmoMap *gzmap, wmWindow *win)
{
- wmGizmo *mpr = mmap->mmap_context.highlight;
- if (mpr && mpr->type->cursor_get) {
- WM_cursor_set(win, mpr->type->cursor_get(mpr));
+ wmGizmo *gz = gzmap->gzmap_context.highlight;
+ if (gz && gz->type->cursor_get) {
+ WM_cursor_set(win, gz->type->cursor_get(gz));
return true;
}
@@ -858,33 +883,33 @@ bool WM_gizmomap_cursor_set(const wmGizmoMap *mmap, wmWindow *win)
}
bool wm_gizmomap_highlight_set(
- wmGizmoMap *mmap, const bContext *C, wmGizmo *mpr, int part)
+ wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part)
{
- if ((mpr != mmap->mmap_context.highlight) ||
- (mpr && part != mpr->highlight_part))
+ if ((gz != gzmap->gzmap_context.highlight) ||
+ (gz && part != gz->highlight_part))
{
- if (mmap->mmap_context.highlight) {
- mmap->mmap_context.highlight->state &= ~WM_GIZMO_STATE_HIGHLIGHT;
- mmap->mmap_context.highlight->highlight_part = -1;
+ if (gzmap->gzmap_context.highlight) {
+ gzmap->gzmap_context.highlight->state &= ~WM_GIZMO_STATE_HIGHLIGHT;
+ gzmap->gzmap_context.highlight->highlight_part = -1;
}
- mmap->mmap_context.highlight = mpr;
+ gzmap->gzmap_context.highlight = gz;
- if (mpr) {
- mpr->state |= WM_GIZMO_STATE_HIGHLIGHT;
- mpr->highlight_part = part;
- mmap->mmap_context.last_cursor = -1;
+ if (gz) {
+ gz->state |= WM_GIZMO_STATE_HIGHLIGHT;
+ gz->highlight_part = part;
+ gzmap->gzmap_context.last_cursor = -1;
- if (C && mpr->type->cursor_get) {
+ if (C && gz->type->cursor_get) {
wmWindow *win = CTX_wm_window(C);
- mmap->mmap_context.last_cursor = win->cursor;
- WM_cursor_set(win, mpr->type->cursor_get(mpr));
+ gzmap->gzmap_context.last_cursor = win->cursor;
+ WM_cursor_set(win, gz->type->cursor_get(gz));
}
}
else {
- if (C && mmap->mmap_context.last_cursor != -1) {
+ if (C && gzmap->gzmap_context.last_cursor != -1) {
wmWindow *win = CTX_wm_window(C);
- WM_cursor_set(win, mmap->mmap_context.last_cursor);
+ WM_cursor_set(win, gzmap->gzmap_context.last_cursor);
}
}
@@ -900,123 +925,123 @@ bool wm_gizmomap_highlight_set(
return false;
}
-wmGizmo *wm_gizmomap_highlight_get(wmGizmoMap *mmap)
+wmGizmo *wm_gizmomap_highlight_get(wmGizmoMap *gzmap)
{
- return mmap->mmap_context.highlight;
+ return gzmap->gzmap_context.highlight;
}
/**
* Caller should call exit when (enable == False).
*/
void wm_gizmomap_modal_set(
- wmGizmoMap *mmap, bContext *C, wmGizmo *mpr, const wmEvent *event, bool enable)
+ wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, const wmEvent *event, bool enable)
{
if (enable) {
- BLI_assert(mmap->mmap_context.modal == NULL);
+ BLI_assert(gzmap->gzmap_context.modal == NULL);
wmWindow *win = CTX_wm_window(C);
WM_tooltip_clear(C, win);
- if (mpr->type->invoke &&
- (mpr->type->modal || mpr->custom_modal))
+ if (gz->type->invoke &&
+ (gz->type->modal || gz->custom_modal))
{
- const int retval = mpr->type->invoke(C, mpr, event);
+ const int retval = gz->type->invoke(C, gz, event);
if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
return;
}
}
- mpr->state |= WM_GIZMO_STATE_MODAL;
- mmap->mmap_context.modal = mpr;
+ gz->state |= WM_GIZMO_STATE_MODAL;
+ gzmap->gzmap_context.modal = gz;
- if ((mpr->flag & WM_GIZMO_GRAB_CURSOR) &&
+ if ((gz->flag & WM_GIZMO_GRAB_CURSOR) &&
(event->is_motion_absolute == false))
{
WM_cursor_grab_enable(win, true, true, NULL);
- copy_v2_v2_int(mmap->mmap_context.event_xy, &event->x);
- mmap->mmap_context.event_grabcursor = win->grabcursor;
+ copy_v2_v2_int(gzmap->gzmap_context.event_xy, &event->x);
+ gzmap->gzmap_context.event_grabcursor = win->grabcursor;
}
else {
- mmap->mmap_context.event_xy[0] = INT_MAX;
+ gzmap->gzmap_context.event_xy[0] = INT_MAX;
}
- struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, mpr->highlight_part);
+ struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, gz->highlight_part);
if (mpop && mpop->type) {
const int retval = WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
- wm_gizmomap_modal_set(mmap, C, mpr, event, false);
+ wm_gizmomap_modal_set(gzmap, C, gz, event, false);
}
/* we failed to hook the gizmo to the operator handler or operator was cancelled, return */
- if (!mmap->mmap_context.modal) {
- mpr->state &= ~WM_GIZMO_STATE_MODAL;
- MEM_SAFE_FREE(mpr->interaction_data);
+ if (!gzmap->gzmap_context.modal) {
+ gz->state &= ~WM_GIZMO_STATE_MODAL;
+ MEM_SAFE_FREE(gz->interaction_data);
}
return;
}
}
else {
- BLI_assert(ELEM(mmap->mmap_context.modal, NULL, mpr));
+ BLI_assert(ELEM(gzmap->gzmap_context.modal, NULL, gz));
/* deactivate, gizmo but first take care of some stuff */
- if (mpr) {
- mpr->state &= ~WM_GIZMO_STATE_MODAL;
- MEM_SAFE_FREE(mpr->interaction_data);
+ if (gz) {
+ gz->state &= ~WM_GIZMO_STATE_MODAL;
+ MEM_SAFE_FREE(gz->interaction_data);
}
- mmap->mmap_context.modal = NULL;
+ gzmap->gzmap_context.modal = NULL;
if (C) {
wmWindow *win = CTX_wm_window(C);
- if (mmap->mmap_context.event_xy[0] != INT_MAX) {
+ if (gzmap->gzmap_context.event_xy[0] != INT_MAX) {
/* Check if some other part of Blender (typically operators)
* have adjusted the grab mode since it was set.
* If so: warp, so we have a predictable outcome. */
- if (mmap->mmap_context.event_grabcursor == win->grabcursor) {
- WM_cursor_grab_disable(win, mmap->mmap_context.event_xy);
+ if (gzmap->gzmap_context.event_grabcursor == win->grabcursor) {
+ WM_cursor_grab_disable(win, gzmap->gzmap_context.event_xy);
}
else {
- WM_cursor_warp(win, UNPACK2(mmap->mmap_context.event_xy));
+ WM_cursor_warp(win, UNPACK2(gzmap->gzmap_context.event_xy));
}
}
ED_region_tag_redraw(CTX_wm_region(C));
WM_event_add_mousemove(C);
}
- mmap->mmap_context.event_xy[0] = INT_MAX;
+ gzmap->gzmap_context.event_xy[0] = INT_MAX;
}
}
-wmGizmo *wm_gizmomap_modal_get(wmGizmoMap *mmap)
+wmGizmo *wm_gizmomap_modal_get(wmGizmoMap *gzmap)
{
- return mmap->mmap_context.modal;
+ return gzmap->gzmap_context.modal;
}
-wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *mmap, int *r_selected_len)
+wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len)
{
- *r_selected_len = mmap->mmap_context.select.len;
- return mmap->mmap_context.select.items;
+ *r_selected_len = gzmap->gzmap_context.select.len;
+ return gzmap->gzmap_context.select.items;
}
-ListBase *wm_gizmomap_groups_get(wmGizmoMap *mmap)
+ListBase *wm_gizmomap_groups_get(wmGizmoMap *gzmap)
{
- return &mmap->groups;
+ return &gzmap->groups;
}
void WM_gizmomap_message_subscribe(
- bContext *C, wmGizmoMap *mmap, ARegion *ar, struct wmMsgBus *mbus)
+ bContext *C, wmGizmoMap *gzmap, ARegion *ar, struct wmMsgBus *mbus)
{
- for (wmGizmoGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- if (!WM_gizmo_group_type_poll(C, mgroup->type)) {
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
+ if (!WM_gizmo_group_type_poll(C, gzgroup->type)) {
continue;
}
- for (wmGizmo *mpr = mgroup->gizmos.first; mpr; mpr = mpr->next) {
- if (mpr->flag & WM_GIZMO_HIDDEN) {
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if (gz->flag & WM_GIZMO_HIDDEN) {
continue;
}
- WM_gizmo_target_property_subscribe_all(mpr, mbus, ar);
+ WM_gizmo_target_property_subscribe_all(gz, mbus, ar);
}
- if (mgroup->type->message_subscribe != NULL) {
- mgroup->type->message_subscribe(C, mgroup, mbus);
+ if (gzgroup->type->message_subscribe != NULL) {
+ gzgroup->type->message_subscribe(C, gzgroup, mbus);
}
}
}
@@ -1032,12 +1057,12 @@ void WM_gizmomap_message_subscribe(
struct ARegion *WM_gizmomap_tooltip_init(
struct bContext *C, struct ARegion *ar, bool *r_exit_on_event)
{
- wmGizmoMap *mmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = ar->gizmo_map;
*r_exit_on_event = true;
- if (mmap) {
- wmGizmo *mpr = mmap->mmap_context.highlight;
- if (mpr) {
- return UI_tooltip_create_from_gizmo(C, mpr);
+ if (gzmap) {
+ wmGizmo *gz = gzmap->gzmap_context.highlight;
+ if (gz) {
+ return UI_tooltip_create_from_gizmo(C, gz);
}
}
return NULL;
@@ -1051,13 +1076,13 @@ struct ARegion *WM_gizmomap_tooltip_init(
* \{ */
wmGizmoMapType *WM_gizmomaptype_find(
- const struct wmGizmoMapType_Params *mmap_params)
+ const struct wmGizmoMapType_Params *gzmap_params)
{
- for (wmGizmoMapType *mmap_type = gizmomaptypes.first; mmap_type; mmap_type = mmap_type->next) {
- if (mmap_type->spaceid == mmap_params->spaceid &&
- mmap_type->regionid == mmap_params->regionid)
+ for (wmGizmoMapType *gzmap_type = gizmomaptypes.first; gzmap_type; gzmap_type = gzmap_type->next) {
+ if (gzmap_type->spaceid == gzmap_params->spaceid &&
+ gzmap_type->regionid == gzmap_params->regionid)
{
- return mmap_type;
+ return gzmap_type;
}
}
@@ -1065,37 +1090,37 @@ wmGizmoMapType *WM_gizmomaptype_find(
}
wmGizmoMapType *WM_gizmomaptype_ensure(
- const struct wmGizmoMapType_Params *mmap_params)
+ const struct wmGizmoMapType_Params *gzmap_params)
{
- wmGizmoMapType *mmap_type = WM_gizmomaptype_find(mmap_params);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_find(gzmap_params);
- if (mmap_type) {
- return mmap_type;
+ if (gzmap_type) {
+ return gzmap_type;
}
- mmap_type = MEM_callocN(sizeof(wmGizmoMapType), "gizmotype list");
- mmap_type->spaceid = mmap_params->spaceid;
- mmap_type->regionid = mmap_params->regionid;
- BLI_addhead(&gizmomaptypes, mmap_type);
+ gzmap_type = MEM_callocN(sizeof(wmGizmoMapType), "gizmotype list");
+ gzmap_type->spaceid = gzmap_params->spaceid;
+ gzmap_type->regionid = gzmap_params->regionid;
+ BLI_addhead(&gizmomaptypes, gzmap_type);
- return mmap_type;
+ return gzmap_type;
}
void wm_gizmomaptypes_free(void)
{
- for (wmGizmoMapType *mmap_type = gizmomaptypes.first, *mmap_type_next;
- mmap_type;
- mmap_type = mmap_type_next)
+ for (wmGizmoMapType *gzmap_type = gizmomaptypes.first, *gzmap_type_next;
+ gzmap_type;
+ gzmap_type = gzmap_type_next)
{
- mmap_type_next = mmap_type->next;
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first, *wgt_next;
- wgt_ref;
- wgt_ref = wgt_next)
+ gzmap_type_next = gzmap_type->next;
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first, *gzgt_next;
+ gzgt_ref;
+ gzgt_ref = gzgt_next)
{
- wgt_next = wgt_ref->next;
- WM_gizmomaptype_group_free(wgt_ref);
+ gzgt_next = gzgt_ref->next;
+ WM_gizmomaptype_group_free(gzgt_ref);
}
- MEM_freeN(mmap_type);
+ MEM_freeN(gzmap_type);
}
}
@@ -1107,9 +1132,9 @@ void wm_gizmos_keymap(wmKeyConfig *keyconf)
/* we add this item-less keymap once and use it to group gizmo-group keymaps into it */
WM_keymap_find(keyconf, "Gizmos", 0, 0);
- for (wmGizmoMapType *mmap_type = gizmomaptypes.first; mmap_type; mmap_type = mmap_type->next) {
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first; wgt_ref; wgt_ref = wgt_ref->next) {
- wm_gizmogrouptype_setup_keymap(wgt_ref->type, keyconf);
+ for (wmGizmoMapType *gzmap_type = gizmomaptypes.first; gzmap_type; gzmap_type = gzmap_type->next) {
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first; gzgt_ref; gzgt_ref = gzgt_ref->next) {
+ wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf);
}
}
}
@@ -1123,23 +1148,23 @@ void wm_gizmos_keymap(wmKeyConfig *keyconf)
void WM_gizmoconfig_update_tag_init(
- wmGizmoMapType *mmap_type, wmGizmoGroupType *wgt)
+ wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
{
/* tag for update on next use */
- mmap_type->type_update_flag |= (WM_GIZMOMAPTYPE_UPDATE_INIT | WM_GIZMOMAPTYPE_KEYMAP_INIT);
- wgt->type_update_flag |= (WM_GIZMOMAPTYPE_UPDATE_INIT | WM_GIZMOMAPTYPE_KEYMAP_INIT);
+ gzmap_type->type_update_flag |= (WM_GIZMOMAPTYPE_UPDATE_INIT | WM_GIZMOMAPTYPE_KEYMAP_INIT);
+ gzgt->type_update_flag |= (WM_GIZMOMAPTYPE_UPDATE_INIT | WM_GIZMOMAPTYPE_KEYMAP_INIT);
- wm_mmap_type_update_flag |= WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
+ wm_gzmap_type_update_flag |= WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
}
void WM_gizmoconfig_update_tag_remove(
- wmGizmoMapType *mmap_type, wmGizmoGroupType *wgt)
+ wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
{
/* tag for update on next use */
- mmap_type->type_update_flag |= WM_GIZMOMAPTYPE_UPDATE_REMOVE;
- wgt->type_update_flag |= WM_GIZMOMAPTYPE_UPDATE_REMOVE;
+ gzmap_type->type_update_flag |= WM_GIZMOMAPTYPE_UPDATE_REMOVE;
+ gzgt->type_update_flag |= WM_GIZMOMAPTYPE_UPDATE_REMOVE;
- wm_mmap_type_update_flag |= WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
+ wm_gzmap_type_update_flag |= WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
}
/**
@@ -1151,58 +1176,58 @@ void WM_gizmoconfig_update(struct Main *bmain)
if (G.background)
return;
- if (wm_mmap_type_update_flag == 0)
+ if (wm_gzmap_type_update_flag == 0)
return;
- if (wm_mmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
- for (wmGizmoMapType *mmap_type = gizmomaptypes.first;
- mmap_type;
- mmap_type = mmap_type->next)
+ if (wm_gzmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
+ for (wmGizmoMapType *gzmap_type = gizmomaptypes.first;
+ gzmap_type;
+ gzmap_type = gzmap_type->next)
{
- if (mmap_type->type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
- mmap_type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first, *wgt_ref_next;
- wgt_ref;
- wgt_ref = wgt_ref_next)
+ if (gzmap_type->type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
+ gzmap_type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first, *gzgt_ref_next;
+ gzgt_ref;
+ gzgt_ref = gzgt_ref_next)
{
- wgt_ref_next = wgt_ref->next;
- if (wgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_REMOVE) {
- wgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
- WM_gizmomaptype_group_unlink(NULL, bmain, mmap_type, wgt_ref->type);
+ gzgt_ref_next = gzgt_ref->next;
+ if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_REMOVE) {
+ gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_REMOVE;
+ WM_gizmomaptype_group_unlink(NULL, bmain, gzmap_type, gzgt_ref->type);
}
}
}
}
- wm_mmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
+ wm_gzmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
}
- if (wm_mmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT) {
- for (wmGizmoMapType *mmap_type = gizmomaptypes.first;
- mmap_type;
- mmap_type = mmap_type->next)
+ if (wm_gzmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT) {
+ for (wmGizmoMapType *gzmap_type = gizmomaptypes.first;
+ gzmap_type;
+ gzmap_type = gzmap_type->next)
{
const uchar type_update_all = WM_GIZMOMAPTYPE_UPDATE_INIT | WM_GIZMOMAPTYPE_KEYMAP_INIT;
- if (mmap_type->type_update_flag & type_update_all) {
- mmap_type->type_update_flag &= ~type_update_all;
- for (wmGizmoGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
- wgt_ref;
- wgt_ref = wgt_ref->next)
+ if (gzmap_type->type_update_flag & type_update_all) {
+ gzmap_type->type_update_flag &= ~type_update_all;
+ for (wmGizmoGroupTypeRef *gzgt_ref = gzmap_type->grouptype_refs.first;
+ gzgt_ref;
+ gzgt_ref = gzgt_ref->next)
{
- if (wgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
- WM_gizmomaptype_group_init_runtime_keymap(bmain, wgt_ref->type);
- wgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
+ if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_KEYMAP_INIT) {
+ WM_gizmomaptype_group_init_runtime_keymap(bmain, gzgt_ref->type);
+ gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_KEYMAP_INIT;
}
- if (wgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_INIT) {
- WM_gizmomaptype_group_init_runtime(bmain, mmap_type, wgt_ref->type);
- wgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_INIT;
+ if (gzgt_ref->type->type_update_flag & WM_GIZMOMAPTYPE_UPDATE_INIT) {
+ WM_gizmomaptype_group_init_runtime(bmain, gzmap_type, gzgt_ref->type);
+ gzgt_ref->type->type_update_flag &= ~WM_GIZMOMAPTYPE_UPDATE_INIT;
}
}
}
}
- wm_mmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
+ wm_gzmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
}
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
index f3df001af55..601c54b8be5 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
@@ -51,30 +51,30 @@
/** \name Property Definition
* \{ */
-BLI_INLINE wmGizmoProperty *wm_gizmo_target_property_array(wmGizmo *mpr)
+BLI_INLINE wmGizmoProperty *wm_gizmo_target_property_array(wmGizmo *gz)
{
- return (wmGizmoProperty *)(POINTER_OFFSET(mpr, mpr->type->struct_size));
+ return (wmGizmoProperty *)(POINTER_OFFSET(gz, gz->type->struct_size));
}
-wmGizmoProperty *WM_gizmo_target_property_array(wmGizmo *mpr)
+wmGizmoProperty *WM_gizmo_target_property_array(wmGizmo *gz)
{
- return wm_gizmo_target_property_array(mpr);
+ return wm_gizmo_target_property_array(gz);
}
-wmGizmoProperty *WM_gizmo_target_property_at_index(wmGizmo *mpr, int index)
+wmGizmoProperty *WM_gizmo_target_property_at_index(wmGizmo *gz, int index)
{
- BLI_assert(index < mpr->type->target_property_defs_len);
+ BLI_assert(index < gz->type->target_property_defs_len);
BLI_assert(index != -1);
- wmGizmoProperty *mpr_prop_array = wm_gizmo_target_property_array(mpr);
- return &mpr_prop_array[index];
+ wmGizmoProperty *gz_prop_array = wm_gizmo_target_property_array(gz);
+ return &gz_prop_array[index];
}
-wmGizmoProperty *WM_gizmo_target_property_find(wmGizmo *mpr, const char *idname)
+wmGizmoProperty *WM_gizmo_target_property_find(wmGizmo *gz, const char *idname)
{
int index = BLI_findstringindex(
- &mpr->type->target_property_defs, idname, offsetof(wmGizmoPropertyType, idname));
+ &gz->type->target_property_defs, idname, offsetof(wmGizmoPropertyType, idname));
if (index != -1) {
- return WM_gizmo_target_property_at_index(mpr, index);
+ return WM_gizmo_target_property_at_index(gz, index);
}
else {
return NULL;
@@ -82,84 +82,84 @@ wmGizmoProperty *WM_gizmo_target_property_find(wmGizmo *mpr, const char *idname)
}
void WM_gizmo_target_property_def_rna_ptr(
- wmGizmo *mpr, const wmGizmoPropertyType *mpr_prop_type,
+ wmGizmo *gz, const wmGizmoPropertyType *gz_prop_type,
PointerRNA *ptr, PropertyRNA *prop, int index)
{
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_at_index(gz, gz_prop_type->index_in_type);
/* if gizmo evokes an operator we cannot use it for property manipulation */
- BLI_assert(mpr->op_data == NULL);
+ BLI_assert(gz->op_data == NULL);
- mpr_prop->type = mpr_prop_type;
+ gz_prop->type = gz_prop_type;
- mpr_prop->ptr = *ptr;
- mpr_prop->prop = prop;
- mpr_prop->index = index;
+ gz_prop->ptr = *ptr;
+ gz_prop->prop = prop;
+ gz_prop->index = index;
- if (mpr->type->property_update) {
- mpr->type->property_update(mpr, mpr_prop);
+ if (gz->type->property_update) {
+ gz->type->property_update(gz, gz_prop);
}
}
void WM_gizmo_target_property_def_rna(
- wmGizmo *mpr, const char *idname,
+ wmGizmo *gz, const char *idname,
PointerRNA *ptr, const char *propname, int index)
{
- const wmGizmoPropertyType *mpr_prop_type = WM_gizmotype_target_property_find(mpr->type, idname);
+ const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, idname);
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
- WM_gizmo_target_property_def_rna_ptr(mpr, mpr_prop_type, ptr, prop, index);
+ WM_gizmo_target_property_def_rna_ptr(gz, gz_prop_type, ptr, prop, index);
}
void WM_gizmo_target_property_def_func_ptr(
- wmGizmo *mpr, const wmGizmoPropertyType *mpr_prop_type,
+ wmGizmo *gz, const wmGizmoPropertyType *gz_prop_type,
const wmGizmoPropertyFnParams *params)
{
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_at_index(gz, gz_prop_type->index_in_type);
/* if gizmo evokes an operator we cannot use it for property manipulation */
- BLI_assert(mpr->op_data == NULL);
+ BLI_assert(gz->op_data == NULL);
- mpr_prop->type = mpr_prop_type;
+ gz_prop->type = gz_prop_type;
- mpr_prop->custom_func.value_get_fn = params->value_get_fn;
- mpr_prop->custom_func.value_set_fn = params->value_set_fn;
- mpr_prop->custom_func.range_get_fn = params->range_get_fn;
- mpr_prop->custom_func.free_fn = params->free_fn;
- mpr_prop->custom_func.user_data = params->user_data;
+ gz_prop->custom_func.value_get_fn = params->value_get_fn;
+ gz_prop->custom_func.value_set_fn = params->value_set_fn;
+ gz_prop->custom_func.range_get_fn = params->range_get_fn;
+ gz_prop->custom_func.free_fn = params->free_fn;
+ gz_prop->custom_func.user_data = params->user_data;
- if (mpr->type->property_update) {
- mpr->type->property_update(mpr, mpr_prop);
+ if (gz->type->property_update) {
+ gz->type->property_update(gz, gz_prop);
}
}
void WM_gizmo_target_property_def_func(
- wmGizmo *mpr, const char *idname,
+ wmGizmo *gz, const char *idname,
const wmGizmoPropertyFnParams *params)
{
- const wmGizmoPropertyType *mpr_prop_type = WM_gizmotype_target_property_find(mpr->type, idname);
- WM_gizmo_target_property_def_func_ptr(mpr, mpr_prop_type, params);
+ const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, idname);
+ WM_gizmo_target_property_def_func_ptr(gz, gz_prop_type, params);
}
void WM_gizmo_target_property_clear_rna_ptr(
- wmGizmo *mpr, const wmGizmoPropertyType *mpr_prop_type)
+ wmGizmo *gz, const wmGizmoPropertyType *gz_prop_type)
{
- wmGizmoProperty *mpr_prop = WM_gizmo_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_at_index(gz, gz_prop_type->index_in_type);
/* if gizmo evokes an operator we cannot use it for property manipulation */
- BLI_assert(mpr->op_data == NULL);
+ BLI_assert(gz->op_data == NULL);
- mpr_prop->type = NULL;
+ gz_prop->type = NULL;
- mpr_prop->ptr = PointerRNA_NULL;
- mpr_prop->prop = NULL;
- mpr_prop->index = -1;
+ gz_prop->ptr = PointerRNA_NULL;
+ gz_prop->prop = NULL;
+ gz_prop->index = -1;
}
void WM_gizmo_target_property_clear_rna(
- wmGizmo *mpr, const char *idname)
+ wmGizmo *gz, const char *idname)
{
- const wmGizmoPropertyType *mpr_prop_type = WM_gizmotype_target_property_find(mpr->type, idname);
- WM_gizmo_target_property_clear_rna_ptr(mpr, mpr_prop_type);
+ const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, idname);
+ WM_gizmo_target_property_clear_rna_ptr(gz, gz_prop_type);
}
@@ -171,93 +171,93 @@ void WM_gizmo_target_property_clear_rna(
/** \name Property Access
* \{ */
-bool WM_gizmo_target_property_is_valid_any(wmGizmo *mpr)
+bool WM_gizmo_target_property_is_valid_any(wmGizmo *gz)
{
- wmGizmoProperty *mpr_prop_array = wm_gizmo_target_property_array(mpr);
- for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
- wmGizmoProperty *mpr_prop = &mpr_prop_array[i];
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
+ wmGizmoProperty *gz_prop_array = wm_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
return true;
}
}
return false;
}
-bool WM_gizmo_target_property_is_valid(const wmGizmoProperty *mpr_prop)
+bool WM_gizmo_target_property_is_valid(const wmGizmoProperty *gz_prop)
{
- return ((mpr_prop->prop != NULL) ||
- (mpr_prop->custom_func.value_get_fn && mpr_prop->custom_func.value_set_fn));
+ return ((gz_prop->prop != NULL) ||
+ (gz_prop->custom_func.value_get_fn && gz_prop->custom_func.value_set_fn));
}
float WM_gizmo_target_property_value_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop)
+ const wmGizmo *gz, wmGizmoProperty *gz_prop)
{
- if (mpr_prop->custom_func.value_get_fn) {
+ if (gz_prop->custom_func.value_get_fn) {
float value = 0.0f;
- BLI_assert(mpr_prop->type->array_length == 1);
- mpr_prop->custom_func.value_get_fn(mpr, mpr_prop, &value);
+ BLI_assert(gz_prop->type->array_length == 1);
+ gz_prop->custom_func.value_get_fn(gz, gz_prop, &value);
return value;
}
- if (mpr_prop->index == -1) {
- return RNA_property_float_get(&mpr_prop->ptr, mpr_prop->prop);
+ if (gz_prop->index == -1) {
+ return RNA_property_float_get(&gz_prop->ptr, gz_prop->prop);
}
else {
- return RNA_property_float_get_index(&mpr_prop->ptr, mpr_prop->prop, mpr_prop->index);
+ return RNA_property_float_get_index(&gz_prop->ptr, gz_prop->prop, gz_prop->index);
}
}
void WM_gizmo_target_property_value_set(
- bContext *C, const wmGizmo *mpr,
- wmGizmoProperty *mpr_prop, const float value)
+ bContext *C, const wmGizmo *gz,
+ wmGizmoProperty *gz_prop, const float value)
{
- if (mpr_prop->custom_func.value_set_fn) {
- BLI_assert(mpr_prop->type->array_length == 1);
- mpr_prop->custom_func.value_set_fn(mpr, mpr_prop, &value);
+ if (gz_prop->custom_func.value_set_fn) {
+ BLI_assert(gz_prop->type->array_length == 1);
+ gz_prop->custom_func.value_set_fn(gz, gz_prop, &value);
return;
}
/* reset property */
- if (mpr_prop->index == -1) {
- RNA_property_float_set(&mpr_prop->ptr, mpr_prop->prop, value);
+ if (gz_prop->index == -1) {
+ RNA_property_float_set(&gz_prop->ptr, gz_prop->prop, value);
}
else {
- RNA_property_float_set_index(&mpr_prop->ptr, mpr_prop->prop, mpr_prop->index, value);
+ RNA_property_float_set_index(&gz_prop->ptr, gz_prop->prop, gz_prop->index, value);
}
- RNA_property_update(C, &mpr_prop->ptr, mpr_prop->prop);
+ RNA_property_update(C, &gz_prop->ptr, gz_prop->prop);
}
void WM_gizmo_target_property_value_get_array(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
float *value)
{
- if (mpr_prop->custom_func.value_get_fn) {
- mpr_prop->custom_func.value_get_fn(mpr, mpr_prop, value);
+ if (gz_prop->custom_func.value_get_fn) {
+ gz_prop->custom_func.value_get_fn(gz, gz_prop, value);
return;
}
- RNA_property_float_get_array(&mpr_prop->ptr, mpr_prop->prop, value);
+ RNA_property_float_get_array(&gz_prop->ptr, gz_prop->prop, value);
}
void WM_gizmo_target_property_value_set_array(
- bContext *C, const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ bContext *C, const wmGizmo *gz, wmGizmoProperty *gz_prop,
const float *value)
{
- if (mpr_prop->custom_func.value_set_fn) {
- mpr_prop->custom_func.value_set_fn(mpr, mpr_prop, value);
+ if (gz_prop->custom_func.value_set_fn) {
+ gz_prop->custom_func.value_set_fn(gz, gz_prop, value);
return;
}
- RNA_property_float_set_array(&mpr_prop->ptr, mpr_prop->prop, value);
+ RNA_property_float_set_array(&gz_prop->ptr, gz_prop->prop, value);
- RNA_property_update(C, &mpr_prop->ptr, mpr_prop->prop);
+ RNA_property_update(C, &gz_prop->ptr, gz_prop->prop);
}
bool WM_gizmo_target_property_range_get(
- const wmGizmo *mpr, wmGizmoProperty *mpr_prop,
+ const wmGizmo *gz, wmGizmoProperty *gz_prop,
float range[2])
{
- if (mpr_prop->custom_func.value_get_fn) {
- if (mpr_prop->custom_func.range_get_fn) {
- mpr_prop->custom_func.range_get_fn(mpr, mpr_prop, range);
+ if (gz_prop->custom_func.value_get_fn) {
+ if (gz_prop->custom_func.range_get_fn) {
+ gz_prop->custom_func.range_get_fn(gz, gz_prop, range);
return true;
}
else {
@@ -267,17 +267,17 @@ bool WM_gizmo_target_property_range_get(
}
float step, precision;
- RNA_property_float_ui_range(&mpr_prop->ptr, mpr_prop->prop, &range[0], &range[1], &step, &precision);
+ RNA_property_float_ui_range(&gz_prop->ptr, gz_prop->prop, &range[0], &range[1], &step, &precision);
return true;
}
int WM_gizmo_target_property_array_length(
- const wmGizmo *UNUSED(mpr), wmGizmoProperty *mpr_prop)
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop)
{
- if (mpr_prop->custom_func.value_get_fn) {
- return mpr_prop->type->array_length;
+ if (gz_prop->custom_func.value_get_fn) {
+ return gz_prop->type->array_length;
}
- return RNA_property_array_length(&mpr_prop->ptr, mpr_prop->prop);
+ return RNA_property_array_length(&gz_prop->ptr, gz_prop->prop);
}
/** \} */
@@ -289,26 +289,26 @@ int WM_gizmo_target_property_array_length(
* \{ */
const wmGizmoPropertyType *WM_gizmotype_target_property_find(
- const wmGizmoType *wt, const char *idname)
+ const wmGizmoType *gzt, const char *idname)
{
- return BLI_findstring(&wt->target_property_defs, idname, offsetof(wmGizmoPropertyType, idname));
+ return BLI_findstring(&gzt->target_property_defs, idname, offsetof(wmGizmoPropertyType, idname));
}
void WM_gizmotype_target_property_def(
- wmGizmoType *wt, const char *idname, int data_type, int array_length)
+ wmGizmoType *gzt, const char *idname, int data_type, int array_length)
{
wmGizmoPropertyType *mpt;
- BLI_assert(WM_gizmotype_target_property_find(wt, idname) == NULL);
+ BLI_assert(WM_gizmotype_target_property_find(gzt, idname) == NULL);
const uint idname_size = strlen(idname) + 1;
mpt = MEM_callocN(sizeof(wmGizmoPropertyType) + idname_size, __func__);
memcpy(mpt->idname, idname, idname_size);
mpt->data_type = data_type;
mpt->array_length = array_length;
- mpt->index_in_type = wt->target_property_defs_len;
- wt->target_property_defs_len += 1;
- BLI_addtail(&wt->target_property_defs, mpt);
+ mpt->index_in_type = gzt->target_property_defs_len;
+ gzt->target_property_defs_len += 1;
+ BLI_addtail(&gzt->target_property_defs, mpt);
}
/** \} */
@@ -322,10 +322,10 @@ void WM_gizmo_do_msg_notify_tag_refresh(
bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
{
ARegion *ar = msg_val->owner;
- wmGizmoMap *mmap = msg_val->user_data;
+ wmGizmoMap *gzmap = msg_val->user_data;
ED_region_tag_redraw(ar);
- WM_gizmomap_tag_refresh(mmap);
+ WM_gizmomap_tag_refresh(gzmap);
}
/**
@@ -333,26 +333,26 @@ void WM_gizmo_do_msg_notify_tag_refresh(
* drawing the region clears.
*/
void WM_gizmo_target_property_subscribe_all(
- wmGizmo *mpr, struct wmMsgBus *mbus, ARegion *ar)
+ wmGizmo *gz, struct wmMsgBus *mbus, ARegion *ar)
{
- if (mpr->type->target_property_defs_len) {
- wmGizmoProperty *mpr_prop_array = WM_gizmo_target_property_array(mpr);
- for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
- wmGizmoProperty *mpr_prop = &mpr_prop_array[i];
- if (WM_gizmo_target_property_is_valid(mpr_prop)) {
- if (mpr_prop->prop) {
+ if (gz->type->target_property_defs_len) {
+ wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
+ for (int i = 0; i < gz->type->target_property_defs_len; i++) {
+ wmGizmoProperty *gz_prop = &gz_prop_array[i];
+ if (WM_gizmo_target_property_is_valid(gz_prop)) {
+ if (gz_prop->prop) {
WM_msg_subscribe_rna(
- mbus, &mpr_prop->ptr, mpr_prop->prop,
+ mbus, &gz_prop->ptr, gz_prop->prop,
&(const wmMsgSubscribeValue){
.owner = ar,
.user_data = ar,
.notify = ED_region_do_msg_notify_tag_redraw,
}, __func__);
WM_msg_subscribe_rna(
- mbus, &mpr_prop->ptr, mpr_prop->prop,
+ mbus, &gz_prop->ptr, gz_prop->prop,
&(const wmMsgSubscribeValue){
.owner = ar,
- .user_data = mpr->parent_mgroup->parent_mmap,
+ .user_data = gz->parent_gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
}, __func__);
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
index ba145af9582..2ff0148044c 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_type.c
@@ -62,11 +62,11 @@ static GHash *global_gizmotype_hash = NULL;
const wmGizmoType *WM_gizmotype_find(const char *idname, bool quiet)
{
if (idname[0]) {
- wmGizmoType *wt;
+ wmGizmoType *gzt;
- wt = BLI_ghash_lookup(global_gizmotype_hash, idname);
- if (wt) {
- return wt;
+ gzt = BLI_ghash_lookup(global_gizmotype_hash, idname);
+ if (gzt) {
+ return gzt;
}
if (!quiet) {
@@ -90,56 +90,56 @@ void WM_gizmotype_iter(GHashIterator *ghi)
static wmGizmoType *wm_gizmotype_append__begin(void)
{
- wmGizmoType *wt = MEM_callocN(sizeof(wmGizmoType), "gizmotype");
- wt->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_GizmoProperties);
+ wmGizmoType *gzt = MEM_callocN(sizeof(wmGizmoType), "gizmotype");
+ gzt->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_GizmoProperties);
#if 0
/* Set the default i18n context now, so that opfunc can redefine it if needed! */
RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
#endif
- return wt;
+ return gzt;
}
-static void wm_gizmotype_append__end(wmGizmoType *wt)
+static void wm_gizmotype_append__end(wmGizmoType *gzt)
{
- BLI_assert(wt->struct_size >= sizeof(wmGizmo));
+ BLI_assert(gzt->struct_size >= sizeof(wmGizmo));
- RNA_def_struct_identifier(&BLENDER_RNA, wt->srna, wt->idname);
+ RNA_def_struct_identifier(&BLENDER_RNA, gzt->srna, gzt->idname);
- BLI_ghash_insert(global_gizmotype_hash, (void *)wt->idname, wt);
+ BLI_ghash_insert(global_gizmotype_hash, (void *)gzt->idname, gzt);
}
-void WM_gizmotype_append(void (*wtfunc)(struct wmGizmoType *))
+void WM_gizmotype_append(void (*gtfunc)(struct wmGizmoType *))
{
- wmGizmoType *wt = wm_gizmotype_append__begin();
- wtfunc(wt);
- wm_gizmotype_append__end(wt);
+ wmGizmoType *gzt = wm_gizmotype_append__begin();
+ gtfunc(gzt);
+ wm_gizmotype_append__end(gzt);
}
-void WM_gizmotype_append_ptr(void (*wtfunc)(struct wmGizmoType *, void *), void *userdata)
+void WM_gizmotype_append_ptr(void (*gtfunc)(struct wmGizmoType *, void *), void *userdata)
{
wmGizmoType *mt = wm_gizmotype_append__begin();
- wtfunc(mt, userdata);
+ gtfunc(mt, userdata);
wm_gizmotype_append__end(mt);
}
/**
* Free but don't remove from ghash.
*/
-static void gizmotype_free(wmGizmoType *wt)
+static void gizmotype_free(wmGizmoType *gzt)
{
- if (wt->ext.srna) { /* python gizmo, allocs own string */
- MEM_freeN((void *)wt->idname);
+ if (gzt->ext.srna) { /* python gizmo, allocs own string */
+ MEM_freeN((void *)gzt->idname);
}
- BLI_freelistN(&wt->target_property_defs);
- MEM_freeN(wt);
+ BLI_freelistN(&gzt->target_property_defs);
+ MEM_freeN(gzt);
}
/**
* \param C: May be NULL.
*/
static void gizmotype_unlink(
- bContext *C, Main *bmain, wmGizmoType *wt)
+ bContext *C, Main *bmain, wmGizmoType *gzt)
{
/* Free instances. */
for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
@@ -147,15 +147,15 @@ static void gizmotype_unlink(
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
for (ARegion *ar = lb->first; ar; ar = ar->next) {
- wmGizmoMap *mmap = ar->gizmo_map;
- if (mmap) {
- wmGizmoGroup *mgroup;
- for (mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
- for (wmGizmo *mpr = mgroup->gizmos.first, *mpr_next; mpr; mpr = mpr_next) {
- mpr_next = mpr->next;
- BLI_assert(mgroup->parent_mmap == mmap);
- if (mpr->type == wt) {
- WM_gizmo_unlink(&mgroup->gizmos, mgroup->parent_mmap, mpr, C);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap) {
+ wmGizmoGroup *gzgroup;
+ for (gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
+ for (wmGizmo *gz = gzgroup->gizmos.first, *gz_next; gz; gz = gz_next) {
+ gz_next = gz->next;
+ BLI_assert(gzgroup->parent_gzmap == gzmap);
+ if (gz->type == gzt) {
+ WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, gz, C);
ED_region_tag_redraw(ar);
}
}
@@ -167,26 +167,26 @@ static void gizmotype_unlink(
}
}
-void WM_gizmotype_remove_ptr(bContext *C, Main *bmain, wmGizmoType *wt)
+void WM_gizmotype_remove_ptr(bContext *C, Main *bmain, wmGizmoType *gzt)
{
- BLI_assert(wt == WM_gizmotype_find(wt->idname, false));
+ BLI_assert(gzt == WM_gizmotype_find(gzt->idname, false));
- BLI_ghash_remove(global_gizmotype_hash, wt->idname, NULL, NULL);
+ BLI_ghash_remove(global_gizmotype_hash, gzt->idname, NULL, NULL);
- gizmotype_unlink(C, bmain, wt);
+ gizmotype_unlink(C, bmain, gzt);
- gizmotype_free(wt);
+ gizmotype_free(gzt);
}
bool WM_gizmotype_remove(bContext *C, Main *bmain, const char *idname)
{
- wmGizmoType *wt = BLI_ghash_lookup(global_gizmotype_hash, idname);
+ wmGizmoType *gzt = BLI_ghash_lookup(global_gizmotype_hash, idname);
- if (wt == NULL) {
+ if (gzt == NULL) {
return false;
}
- WM_gizmotype_remove_ptr(C, bmain, wt);
+ WM_gizmotype_remove_ptr(C, bmain, gzt);
return true;
}
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
index a94f1e994e9..88065a0fcd5 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
@@ -51,7 +51,7 @@ typedef void (*wmGizmoGroupFnMsgBusSubscribe)(
typedef void (*wmGizmoFnSetup)(struct wmGizmo *);
typedef void (*wmGizmoFnDraw)(const struct bContext *, struct wmGizmo *);
typedef void (*wmGizmoFnDrawSelect)(const struct bContext *, struct wmGizmo *, int);
-typedef int (*wmGizmoFnTestSelect)(struct bContext *, struct wmGizmo *, const struct wmEvent *);
+typedef int (*wmGizmoFnTestSelect)(struct bContext *, struct wmGizmo *, const int mval[2]);
typedef int (*wmGizmoFnModal)(struct bContext *, struct wmGizmo *, const struct wmEvent *, eWM_GizmoFlagTweak);
typedef void (*wmGizmoFnPropertyUpdate)(struct wmGizmo *, struct wmGizmoProperty *);
typedef void (*wmGizmoFnMatrixBasisGet)(const struct wmGizmo *, float[4][4]);
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
index 5b1085db4a1..414109e89e5 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
@@ -61,12 +61,12 @@ void wm_gizmogrouptype_init(void);
void GIZMOGROUP_OT_gizmo_select(struct wmOperatorType *ot);
void GIZMOGROUP_OT_gizmo_tweak(struct wmOperatorType *ot);
-bool wm_gizmogroup_is_any_selected(const struct wmGizmoGroup *mgroup);
+bool wm_gizmogroup_is_any_selected(const struct wmGizmoGroup *gzgroup);
/* -------------------------------------------------------------------- */
/* wmGizmoMap */
-void wm_gizmomap_remove(struct wmGizmoMap *mmap);
+void wm_gizmomap_remove(struct wmGizmoMap *gzmap);
void wm_gizmos_keymap(struct wmKeyConfig *keyconf);
@@ -75,19 +75,19 @@ void wm_gizmomaps_handled_modal_update(
void wm_gizmomap_handler_context(bContext *C, struct wmEventHandler *handler);
struct wmGizmo *wm_gizmomap_highlight_find(
- struct wmGizmoMap *mmap, bContext *C, const struct wmEvent *event,
+ struct wmGizmoMap *gzmap, bContext *C, const struct wmEvent *event,
int *r_part);
bool wm_gizmomap_highlight_set(
- struct wmGizmoMap *mmap, const bContext *C,
- struct wmGizmo *mpr, int part);
-struct wmGizmo *wm_gizmomap_highlight_get(struct wmGizmoMap *mmap);
+ struct wmGizmoMap *gzmap, const bContext *C,
+ struct wmGizmo *gz, int part);
+struct wmGizmo *wm_gizmomap_highlight_get(struct wmGizmoMap *gzmap);
void wm_gizmomap_modal_set(
- struct wmGizmoMap *mmap, bContext *C, struct wmGizmo *mpr,
+ struct wmGizmoMap *gzmap, bContext *C, struct wmGizmo *gz,
const struct wmEvent *event, bool enable);
-struct wmGizmo *wm_gizmomap_modal_get(struct wmGizmoMap *mmap);
-struct wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *mmap, int *r_selected_len);
-struct ListBase *wm_gizmomap_groups_get(wmGizmoMap *mmap);
+struct wmGizmo *wm_gizmomap_modal_get(struct wmGizmoMap *gzmap);
+struct wmGizmo **wm_gizmomap_selected_get(wmGizmoMap *gzmap, int *r_selected_len);
+struct ListBase *wm_gizmomap_groups_get(wmGizmoMap *gzmap);
/* -------------------------------------------------------------------- */
/* wmGizmoMapType */
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index f92cc511449..7247529d02d 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -223,65 +223,6 @@ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot)
}
}
-/* ************ uiListType handling ************** */
-
-static GHash *uilisttypes_hash = NULL;
-
-uiListType *WM_uilisttype_find(const char *idname, bool quiet)
-{
- uiListType *ult;
-
- if (idname[0]) {
- ult = BLI_ghash_lookup(uilisttypes_hash, idname);
- if (ult) {
- return ult;
- }
- }
-
- if (!quiet) {
- printf("search for unknown uilisttype %s\n", idname);
- }
-
- return NULL;
-}
-
-bool WM_uilisttype_add(uiListType *ult)
-{
- BLI_ghash_insert(uilisttypes_hash, ult->idname, ult);
- return 1;
-}
-
-void WM_uilisttype_freelink(uiListType *ult)
-{
- bool ok;
-
- ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN);
-
- BLI_assert(ok);
- (void)ok;
-}
-
-/* called on initialize WM_init() */
-void WM_uilisttype_init(void)
-{
- uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16);
-}
-
-void WM_uilisttype_free(void)
-{
- GHashIterator gh_iter;
-
- GHASH_ITER (gh_iter, uilisttypes_hash) {
- uiListType *ult = BLI_ghashIterator_getValue(&gh_iter);
- if (ult->ext.free) {
- ult->ext.free(ult->ext.data);
- }
- }
-
- BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
- uilisttypes_hash = NULL;
-}
-
/* ****************************************** */
void WM_keymap_init(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index eca3a838c0f..73748ba6322 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -45,6 +45,7 @@
#include "BIF_glutil.h"
#include "BKE_context.h"
+#include "BKE_idcode.h"
#include "GPU_shader.h"
@@ -98,7 +99,8 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
wmDropBox *WM_dropbox_add(
- ListBase *lb, const char *idname, bool (*poll)(bContext *, wmDrag *, const wmEvent *),
+ ListBase *lb, const char *idname,
+ bool (*poll)(bContext *, wmDrag *, const wmEvent *, const char **),
void (*copy)(wmDrag *, wmDropBox *))
{
wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox");
@@ -154,10 +156,17 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin,
drag->flags = flags;
drag->icon = icon;
drag->type = type;
- if (type == WM_DRAG_PATH)
+ if (type == WM_DRAG_PATH) {
BLI_strncpy(drag->path, poin, FILE_MAX);
- else
+ }
+ else if (type == WM_DRAG_ID) {
+ if (poin) {
+ WM_drag_add_ID(drag, poin, NULL);
+ }
+ }
+ else {
drag->poin = poin;
+ }
drag->value = value;
return drag;
@@ -177,6 +186,7 @@ void WM_drag_free(wmDrag *drag)
MEM_freeN(drag->poin);
}
+ BLI_freelistN(&drag->ids);
MEM_freeN(drag);
}
@@ -188,6 +198,7 @@ void WM_drag_free_list(struct ListBase *lb)
}
}
+
static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, const wmEvent *event)
{
wmEventHandler *handler = handlers->first;
@@ -195,10 +206,12 @@ static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag,
if (handler->dropboxes) {
wmDropBox *drop = handler->dropboxes->first;
for (; drop; drop = drop->next) {
- if (drop->poll(C, drag, event))
+ const char *tooltip = NULL;
+ if (drop->poll(C, drag, event, &tooltip)) {
/* XXX Doing translation here might not be ideal, but later we have no more
* access to ot (and hence op context)... */
- return RNA_struct_ui_name(drop->ot->srna);
+ return (tooltip) ? tooltip : RNA_struct_ui_name(drop->ot->srna);
+ }
}
}
}
@@ -266,6 +279,57 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event)
}
}
+/* ************** IDs ***************** */
+
+void WM_drag_add_ID(wmDrag *drag, ID *id, ID *from_parent)
+{
+ /* Don't drag the same ID twice. */
+ for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ if (drag_id->id == id) {
+ if (drag_id->from_parent == NULL) {
+ drag_id->from_parent = from_parent;
+ }
+ return;
+ }
+ else if (GS(drag_id->id->name) != GS(id->name)) {
+ BLI_assert(!"All dragged IDs must have the same type");
+ return;
+ }
+ }
+
+ /* Add to list. */
+ wmDragID *drag_id = MEM_callocN(sizeof(wmDragID), __func__);
+ drag_id->id = id;
+ drag_id->from_parent = from_parent;
+ BLI_addtail(&drag->ids, drag_id);
+}
+
+ID *WM_drag_ID(const wmDrag *drag, short idcode)
+{
+ if (drag->type != WM_DRAG_ID) {
+ return NULL;
+ }
+
+ wmDragID *drag_id = drag->ids.first;
+ if (!drag_id) {
+ return NULL;
+ }
+
+ ID *id = drag_id->id;
+ return (idcode == 0 || GS(id->name) == idcode) ? id : NULL;
+
+}
+
+ID *WM_drag_ID_from_event(const wmEvent *event, short idcode)
+{
+ if (event->custom != EVT_DATA_DRAGDROP) {
+ return NULL;
+ }
+
+ ListBase *lb = event->customdata;
+ return WM_drag_ID(lb->first, idcode);
+}
+
/* ************** draw ***************** */
static void wm_drop_operator_draw(const char *name, int x, int y)
@@ -282,8 +346,16 @@ static const char *wm_drag_name(wmDrag *drag)
switch (drag->type) {
case WM_DRAG_ID:
{
- ID *id = drag->poin;
- return id->name + 2;
+ ID *id = WM_drag_ID(drag, 0);
+ bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1);
+
+ if (single) {
+ return id->name + 2;
+ }
+ else if (id) {
+ return BKE_idcode_to_name_plural(GS(id->name));
+ }
+ break;
}
case WM_DRAG_PATH:
case WM_DRAG_NAME:
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 5314c434c4c..160aeb6671b 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -456,9 +456,9 @@ void wm_draw_region_blend(ARegion *ar, int view, bool blend)
glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy);
glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), ar->winrct.xmin, ar->winrct.ymin, ar->winrct.xmax + 1, ar->winrct.ymax + 1);
- glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
- GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
+ GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
glBindTexture(GL_TEXTURE_2D, 0);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index bc24b7698e2..0581d41ea04 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -98,7 +98,7 @@ static void wm_notifier_clear(wmNotifier *note);
static void update_tablet_data(wmWindow *win, wmEvent *event);
static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- const short context, const bool poll_only);
+ const short context, const bool poll_only, wmEvent *event);
/* ************ event management ************** */
@@ -638,7 +638,7 @@ bool WM_operator_poll(bContext *C, wmOperatorType *ot)
/* sets up the new context and calls 'wm_operator_invoke()' with poll_only */
bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
{
- return wm_operator_call_internal(C, ot, NULL, NULL, context, true);
+ return wm_operator_call_internal(C, ot, NULL, NULL, context, true, NULL);
}
bool WM_operator_check_ui_empty(wmOperatorType *ot)
@@ -1431,10 +1431,8 @@ static int wm_operator_invoke(
*/
static int wm_operator_call_internal(
bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- const short context, const bool poll_only)
+ const short context, const bool poll_only, wmEvent *event)
{
- wmEvent *event;
-
int retval;
CTX_wm_operator_poll_msg_set(C, NULL);
@@ -1443,27 +1441,29 @@ static int wm_operator_call_internal(
if (ot) {
wmWindow *window = CTX_wm_window(C);
- switch (context) {
- case WM_OP_INVOKE_DEFAULT:
- case WM_OP_INVOKE_REGION_WIN:
- case WM_OP_INVOKE_REGION_PREVIEW:
- case WM_OP_INVOKE_REGION_CHANNELS:
- case WM_OP_INVOKE_AREA:
- case WM_OP_INVOKE_SCREEN:
- /* window is needed for invoke, cancel operator */
- if (window == NULL) {
- if (poll_only) {
- CTX_wm_operator_poll_msg_set(C, "Missing 'window' in context");
+ if (event == NULL) {
+ switch (context) {
+ case WM_OP_INVOKE_DEFAULT:
+ case WM_OP_INVOKE_REGION_WIN:
+ case WM_OP_INVOKE_REGION_PREVIEW:
+ case WM_OP_INVOKE_REGION_CHANNELS:
+ case WM_OP_INVOKE_AREA:
+ case WM_OP_INVOKE_SCREEN:
+ /* window is needed for invoke, cancel operator */
+ if (window == NULL) {
+ if (poll_only) {
+ CTX_wm_operator_poll_msg_set(C, "Missing 'window' in context");
+ }
+ return 0;
}
- return 0;
- }
- else {
- event = window->eventstate;
- }
- break;
- default:
- event = NULL;
- break;
+ else {
+ event = window->eventstate;
+ }
+ break;
+ default:
+ event = NULL;
+ break;
+ }
}
switch (context) {
@@ -1561,7 +1561,7 @@ static int wm_operator_call_internal(
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties)
{
BLI_assert(ot == WM_operatortype_find(ot->idname, true));
- return wm_operator_call_internal(C, ot, properties, NULL, context, false);
+ return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL);
}
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
{
@@ -1627,7 +1627,7 @@ int WM_operator_call_py(
wmWindowManager *wm = CTX_wm_manager(C);
if (!is_undo && wm) wm->op_undo_depth++;
- retval = wm_operator_call_internal(C, ot, properties, reports, context, false);
+ retval = wm_operator_call_internal(C, ot, properties, reports, context, false, NULL);
if (!is_undo && wm && (wm == CTX_wm_manager(C))) wm->op_undo_depth--;
@@ -2368,18 +2368,28 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wmDrag *drag;
for (drag = lb->first; drag; drag = drag->next) {
- if (drop->poll(C, drag, event)) {
- drop->copy(drag, drop);
+ const char *tooltip = NULL;
+ if (drop->poll(C, drag, event, &tooltip)) {
+ /* Optionally copy drag information to operator properties. */
+ if (drop->copy) {
+ drop->copy(drag, drop);
+ }
- /* free the drags before calling operator */
+ /* Pass single matched wmDrag onto the operator. */
+ BLI_remlink(lb, drag);
+ ListBase single_lb = {drag, drag};
+ event->customdata = &single_lb;
+
+ wm_operator_call_internal(C, drop->ot, drop->ptr, NULL, drop->opcontext, false, event);
+ action |= WM_HANDLER_BREAK;
+
+ /* free the drags */
WM_drag_free_list(lb);
+ WM_drag_free_list(&single_lb);
event->customdata = NULL;
event->custom = 0;
- WM_operator_name_call_ptr(C, drop->ot, drop->opcontext, drop->ptr);
- action |= WM_HANDLER_BREAK;
-
/* XXX fileread case */
if (CTX_wm_window(C) == NULL)
return action;
@@ -2395,8 +2405,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
else if (handler->gizmo_map) {
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- wmGizmoMap *mmap = handler->gizmo_map;
- wmGizmo *mpr = wm_gizmomap_highlight_get(mmap);
+ wmGizmoMap *gzmap = handler->gizmo_map;
+ wmGizmo *gz = wm_gizmomap_highlight_get(gzmap);
if (region->gizmo_map != handler->gizmo_map) {
WM_gizmomap_tag_refresh(handler->gizmo_map);
@@ -2406,10 +2416,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_region_mouse_co(C, event);
/* handle gizmo highlighting */
- if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(mmap)) {
+ if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(gzmap)) {
int part;
- mpr = wm_gizmomap_highlight_find(mmap, C, event, &part);
- if (wm_gizmomap_highlight_set(mmap, C, mpr, part) && mpr != NULL) {
+ gz = wm_gizmomap_highlight_find(gzmap, C, event, &part);
+ if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) {
WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init);
}
}
@@ -2417,45 +2427,45 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
/* Either we operate on a single highlighted item
* or groups attached to the selected gizmos.
* To simplify things both cases loop over an array of items. */
- wmGizmoGroup *mgroup_first;
- bool is_mgroup_single;
+ wmGizmoGroup *gzgroup_first;
+ bool is_gzgroup_single;
if (ISMOUSE(event->type)) {
- /* Keep mpr set as-is, just fake single selection. */
- if (mpr) {
- mgroup_first = mpr->parent_mgroup;
+ /* Keep gz set as-is, just fake single selection. */
+ if (gz) {
+ gzgroup_first = gz->parent_gzgroup;
}
else {
- mgroup_first = NULL;
+ gzgroup_first = NULL;
}
- is_mgroup_single = true;
+ is_gzgroup_single = true;
}
else {
- if (WM_gizmomap_is_any_selected(mmap)) {
- const ListBase *groups = WM_gizmomap_group_list(mmap);
- mgroup_first = groups->first;
+ if (WM_gizmomap_is_any_selected(gzmap)) {
+ const ListBase *groups = WM_gizmomap_group_list(gzmap);
+ gzgroup_first = groups->first;
}
else {
- mgroup_first = NULL;
+ gzgroup_first = NULL;
}
- is_mgroup_single = false;
+ is_gzgroup_single = false;
}
/* Don't use from now on. */
- mpr = NULL;
+ gz = NULL;
- for (wmGizmoGroup *mgroup = mgroup_first; mgroup; mgroup = mgroup->next) {
+ for (wmGizmoGroup *gzgroup = gzgroup_first; gzgroup; gzgroup = gzgroup->next) {
/* get user customized keymap from default one */
- if ((is_mgroup_single == false) &&
+ if ((is_gzgroup_single == false) &&
/* We might want to change the logic here and use some kind of gizmo edit-mode.
* For now just use keymap when a selection exists. */
- wm_gizmogroup_is_any_selected(mgroup) == false)
+ wm_gizmogroup_is_any_selected(gzgroup) == false)
{
continue;
}
- wmKeyMap *keymap = WM_keymap_active(wm, mgroup->type->keymap);
+ wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap);
wmKeyMapItem *kmi;
PRINT("%s: checking '%s' ...", __func__, keymap->idname);
@@ -2472,7 +2482,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
/* weak, but allows interactive callback to not use rawkey */
event->keymap_idname = kmi->idname;
- CTX_wm_gizmo_group_set(C, mgroup);
+ CTX_wm_gizmo_group_set(C, gzgroup);
/* handler->op is called later, we want keymap op to be triggered here */
handler->op = NULL;
@@ -2515,7 +2525,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
break;
}
- if (is_mgroup_single) {
+ if (is_gzgroup_single) {
break;
}
}
@@ -4569,7 +4579,11 @@ bool WM_window_modal_keymap_status_draw(
continue;
}
int icon_mod[4];
+#ifdef WITH_HEADLESS
+ int icon = 0;
+#else
int icon = UI_icon_from_keymap_item(kmi, icon_mod);
+#endif
if (icon != 0) {
for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) {
uiItemL(row, "", icon_mod[j]);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 84dcf30e63c..e44081bef54 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -188,7 +188,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
static void wm_window_substitute_old(wmWindowManager *oldwm, wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
{
win->ghostwin = oldwin->ghostwin;
- win->gwnctx = oldwin->gwnctx;
+ win->gpuctx = oldwin->gpuctx;
win->active = oldwin->active;
if (win->active) {
wm->winactive = win;
@@ -202,7 +202,7 @@ static void wm_window_substitute_old(wmWindowManager *oldwm, wmWindowManager *wm
GHOST_SetWindowUserData(win->ghostwin, win); /* pointer back */
oldwin->ghostwin = NULL;
- oldwin->gwnctx = NULL;
+ oldwin->gpuctx = NULL;
win->eventstate = oldwin->eventstate;
oldwin->eventstate = NULL;
@@ -279,6 +279,10 @@ static void wm_window_match_replace_by_file_wm(
wm->initialized = 0;
wm->winactive = NULL;
+ /* Clearing drawable of before deleting any context
+ * to avoid clearing the wrong wm. */
+ wm_window_clear_drawable(oldwm);
+
/* only first wm in list has ghostwins */
for (wmWindow *win = wm->windows.first; win; win = win->next) {
for (wmWindow *oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) {
@@ -365,8 +369,6 @@ static void wm_init_userdef(Main *bmain, const bool read_userdef_from_memory)
/* update tempdir from user preferences */
BKE_tempdir_init(U.tempdir);
-
- BLF_antialias_set((U.text_render & USER_TEXT_DISABLE_AA) == 0);
}
@@ -488,13 +490,7 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
Main *bmain = CTX_data_main(C);
DEG_on_visible_update(bmain, true);
-
- if (!is_startup_file) {
- /* When starting up, the UI hasn't been fully initialised yet, and
- * this call can trigger icon updates, causing a segfault due to a
- * not-yet-initialised ghash for the icons. */
- wm_event_do_depsgraph(C);
- }
+ wm_event_do_depsgraph(C);
ED_editors_init(C);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 4366013084c..06a7f3528c5 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -166,7 +166,7 @@ static void wm_gesture_draw_line(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -181,7 +181,7 @@ static void wm_gesture_draw_line(wmGesture *gt)
float xmin = (float)rect->xmin;
float ymin = (float)rect->ymin;
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(shdr_pos, xmin, ymin);
immVertex2f(shdr_pos, (float)rect->xmax, (float)rect->ymax);
immEnd();
@@ -193,7 +193,7 @@ static void wm_gesture_draw_rect(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
- uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
glEnable(GL_BLEND);
@@ -206,7 +206,7 @@ static void wm_gesture_draw_rect(wmGesture *gt)
glDisable(GL_BLEND);
- shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -231,7 +231,7 @@ static void wm_gesture_draw_circle(wmGesture *gt)
glEnable(GL_BLEND);
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -346,7 +346,7 @@ static void wm_gesture_draw_lasso(wmGesture *gt, bool filled)
return;
}
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -358,7 +358,7 @@ static void wm_gesture_draw_lasso(wmGesture *gt, bool filled)
immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
immUniform1f("dash_width", 2.0f);
- immBegin((gt->type == WM_GESTURE_LASSO) ? GWN_PRIM_LINE_LOOP : GWN_PRIM_LINE_STRIP, numverts);
+ immBegin((gt->type == WM_GESTURE_LASSO) ? GPU_PRIM_LINE_LOOP : GPU_PRIM_LINE_STRIP, numverts);
for (i = 0; i < gt->points; i++, lasso += 2) {
immVertex2f(shdr_pos, (float)lasso[0], (float)lasso[1]);
@@ -377,7 +377,7 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
float x1, x2, y1, y2;
- const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
@@ -389,7 +389,7 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
immUniform1f("dash_width", 8.0f);
- immBegin(GWN_PRIM_LINES, 4);
+ immBegin(GPU_PRIM_LINES, 4);
x1 = (float)(rect->xmin - winsize_x);
y1 = (float)rect->ymin;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 0c7c85e0d94..4b0d751a7ce 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -35,6 +35,7 @@
#include <string.h>
#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
@@ -114,11 +115,13 @@
#include "ED_undo.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "BLF_api.h"
#include "BLT_lang.h"
#include "GPU_material.h"
#include "GPU_draw.h"
+#include "GPU_immediate.h"
#include "GPU_init_exit.h"
#include "BKE_sound.h"
@@ -235,6 +238,11 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_init();
BLT_lang_init();
+ /* Init icons before reading .blend files for preview icons, which can
+ * get triggered by the depsgraph. This is also done in background mode
+ * for scripts that do background processing with preview icons. */
+ BKE_icons_init(BIFICONID_LAST);
+
/* reports cant be initialized before the wm,
* but keep before file reading, since that may report errors */
wm_init_reports(C);
@@ -257,13 +265,6 @@ void WM_init(bContext *C, int argc, const char **argv)
UI_init();
BKE_studiolight_init();
}
- else {
- /* Note: Currently only inits icons, which we now want in background mode too
- * (scripts could use those in background processing...).
- * In case we do more later, we may need to pass a 'background' flag.
- * Called from 'UI_init' above */
- BKE_icons_init(1);
- }
ED_spacemacros_init();
@@ -515,9 +516,11 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLF_exit();
if (opengl_is_init) {
+ DRW_opengl_context_enable_ex(false);
GPU_pass_cache_free();
- DRW_opengl_context_destroy();
GPU_exit();
+ DRW_opengl_context_disable_ex(false);
+ DRW_opengl_context_destroy();
}
#ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index a95ccf36fdb..6815ff4413a 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -526,6 +526,25 @@ wmKeyMapItem *WM_keymap_add_tool(wmKeyMap *keymap, const char *idname, int type,
return kmi;
}
+/** Useful for mapping numbers to an enum. */
+void WM_keymap_add_context_enum_set_items(
+ wmKeyMap *keymap, const EnumPropertyItem *items, const char *data_path,
+ int type_start, int val, int modifier, int keymodifier)
+{
+ for (int i = 0, type_offset = 0; items[i].identifier; i++) {
+ if (items[i].identifier[0] == '\0') {
+ continue;
+ }
+ wmKeyMapItem *kmi = WM_keymap_add_item(
+ keymap, "WM_OT_context_set_enum",
+ type_start + type_offset, val, modifier, keymodifier);
+ RNA_string_set(kmi->ptr, "data_path", data_path);
+ RNA_string_set(kmi->ptr, "value", items[i].identifier);
+ type_offset += 1;
+ }
+}
+
+
bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
{
if (BLI_findindex(&keymap->items, kmi) != -1) {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 5cf9ac625c3..76a1482ac7c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -440,7 +440,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
switch (GS(((ID *)ptr->id.data)->name)) {
case ID_SCE:
{
- CTX_TEST_PTR_DATA_TYPE(C, "active_gpencil_brush", RNA_GPencilBrush, ptr, CTX_data_active_gpencil_brush(C));
+ CTX_TEST_PTR_DATA_TYPE(C, "active_gpencil_brush", RNA_Brush, ptr, CTX_data_active_gpencil_brush(C));
CTX_TEST_PTR_ID(C, "scene", ptr->id.data);
break;
}
@@ -1043,15 +1043,17 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
if (op->type->flag & OPTYPE_MACRO) {
for (op = op->macro.first; op; op = op->next) {
- uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
- UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
+ uiTemplateOperatorPropertyButs(
+ C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
+ UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
if (op->next)
uiItemS(layout);
}
}
else {
- uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
- UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
+ uiTemplateOperatorPropertyButs(
+ C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
+ UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
}
UI_block_bounds_set_popup(block, 4, 0, 0);
@@ -1120,8 +1122,9 @@ 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);
- uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
- UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
+ uiTemplateOperatorPropertyButs(
+ C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN,
+ UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
/* clear so the OK button is left alone */
UI_block_func_set(block, NULL, NULL, NULL);
@@ -1160,7 +1163,7 @@ 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);
/* since ui is defined the auto-layout args are not used */
- uiTemplateOperatorPropertyButs(C, layout, op, NULL, UI_BUT_LABEL_ALIGN_COLUMN, 0);
+ uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_COLUMN, 0);
UI_block_func_set(block, NULL, NULL, NULL);
@@ -2094,12 +2097,12 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
RNA_property_float_get_array(fill_ptr, fill_prop, col);
}
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (rc->gltex) {
- uint texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rc->gltex);
@@ -2118,12 +2121,12 @@ 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);
- gpuPushMatrix();
- gpuRotate2D(RAD2DEGF(rot));
+ GPU_matrix_push();
+ GPU_matrix_rotate_2d(RAD2DEGF(rot));
}
/* draw textured quad */
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texCoord, 0, 0);
immVertex2f(pos, -radius, -radius);
@@ -2141,7 +2144,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
/* undo rotation */
if (rc->rot_prop)
- gpuPopMatrix();
+ GPU_matrix_pop();
}
else {
/* flat color if no texture available */
@@ -2208,7 +2211,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
/* Keep cursor in the original place */
x = rc->initial_mouse[0];
y = rc->initial_mouse[1];
- gpuTranslate2f((float)x, (float)y);
+ GPU_matrix_translate_2f((float)x, (float)y);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -2216,7 +2219,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
/* apply zoom if available */
if (rc->zoom_prop) {
RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- gpuScale2fv(zoom);
+ GPU_matrix_scale_2fv(zoom);
}
/* draw rotated texture */
@@ -2226,30 +2229,30 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
if (rc->col_prop)
RNA_property_float_get_array(&rc->col_ptr, rc->col_prop, col);
- Gwn_VertFormat *format = immVertexFormat();
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fvAlpha(col, 0.5f);
if (rc->subtype == PROP_ANGLE) {
- gpuPushMatrix();
+ GPU_matrix_push();
/* draw original angle line */
- gpuRotate2D(RAD2DEGF(rc->initial_value));
- immBegin(GWN_PRIM_LINES, 2);
+ GPU_matrix_rotate_2d(RAD2DEGF(rc->initial_value));
+ immBegin(GPU_PRIM_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 */
- gpuRotate2D(RAD2DEGF(rc->current_value - rc->initial_value));
- immBegin(GWN_PRIM_LINES, 2);
+ GPU_matrix_rotate_2d(RAD2DEGF(rc->current_value - rc->initial_value));
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
immEnd();
- gpuPopMatrix();
+ GPU_matrix_pop();
}
/* draw circles on top */
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 003932930ed..6317cca8094 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -28,8 +28,11 @@
/** \file blender/windowmanager/intern/wm_playanim.c
* \ingroup wm
*
+ * Animation player for image sequences & video's with sound support.
+ * Launched in a separate process from Blender's #RENDER_OT_play_rendered_anim
+ *
* \note This file uses ghost directly and none of the WM definitions.
- * this could be made into its own module, alongside creator/
+ * this could be made into its own module, alongside creator.
*/
#include <sys/types.h>
@@ -66,7 +69,7 @@
#include "GPU_matrix.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
-#include "GPU_batch.h"
+#include "GPU_context.h"
#include "GPU_init_exit.h"
#include "DNA_scene_types.h"
@@ -184,7 +187,7 @@ typedef enum eWS_Qual {
static struct WindowStateGlobal {
GHOST_SystemHandle ghost_system;
void *ghost_window;
- Gwn_Context *gwn_context;
+ GPUContext *gpu_context;
/* events */
eWS_Qual qual;
@@ -201,8 +204,8 @@ 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 */
- /* note! cannot use gpuOrtho2D here because shader ignores. */
- gpuOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
+ /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */
+ GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
}
/* implementation */
@@ -366,25 +369,25 @@ 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;
- gpuPushProjectionMatrix();
- gpuLoadIdentityProjectionMatrix();
- gpuPushMatrix();
- gpuLoadIdentity();
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_projection_set();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
- uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ub(0, 255, 0);
- immBegin(GWN_PRIM_LINES, 2);
+ immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, fac, -1.0f);
immVertex2f(pos, fac, 1.0f);
immEnd();
immUnbindProgram();
- gpuPopMatrix();
- gpuPopProjectionMatrix();
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
}
GHOST_SwapWindowBuffers(g_WS.ghost_window);
@@ -1281,7 +1284,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
//GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
/* initialize OpenGL immediate mode */
- g_WS.gwn_context = GWN_context_create();
+ g_WS.gpu_context = GPU_context_create();
GPU_init();
immActivate();
@@ -1552,10 +1555,10 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
GPU_shader_free_builtin_shaders();
- if (g_WS.gwn_context) {
- GWN_context_active_set(g_WS.gwn_context);
- GWN_context_discard(g_WS.gwn_context);
- g_WS.gwn_context = NULL;
+ if (g_WS.gpu_context) {
+ GPU_context_active_set(g_WS.gpu_context);
+ GPU_context_discard(g_WS.gpu_context);
+ g_WS.gpu_context = NULL;
}
BLF_exit();
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 1e9f6d6231b..577145aff95 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -87,9 +87,9 @@ void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *ar)
float halfx = GLA_PIXEL_OFS / ar->winx;
float halfy = GLA_PIXEL_OFS / ar->winy;
- Gwn_VertFormat *format = immVertexFormat();
- uint texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* leave GL_TEXTURE0 as the latest active texture */
for (int view = 1; view >= 0; view--) {
@@ -104,7 +104,7 @@ void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *ar)
immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type));
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texcoord, halfx, halfy);
immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymin);
@@ -163,9 +163,9 @@ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
{
bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
- Gwn_VertFormat *format = immVertexFormat();
- uint texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE);
@@ -188,7 +188,7 @@ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texcoord, halfx, halfy);
immVertex2f(pos, soffx, 0.0f);
@@ -209,9 +209,9 @@ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
void wm_stereo3d_draw_topbottom(wmWindow *win, int view)
{
- Gwn_VertFormat *format = immVertexFormat();
- uint texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ GPUVertFormat *format = immVertexFormat();
+ uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE);
@@ -232,7 +232,7 @@ void wm_stereo3d_draw_topbottom(wmWindow *win, int view)
immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
- immBegin(GWN_PRIM_TRI_FAN, 4);
+ immBegin(GPU_PRIM_TRI_FAN, 4);
immAttrib2f(texcoord, halfx, halfy);
immVertex2f(pos, 0.0f, soffy);
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index f55eee69f71..ff3c712dae0 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -50,7 +50,7 @@ void wmViewport(const rcti *winrct)
glScissor(winrct->xmin, winrct->ymin, width, height);
wmOrtho2_pixelspace(width, height);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
}
void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct)
@@ -89,7 +89,7 @@ void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct
glScissor(x, y, scissor_width, scissor_height);
wmOrtho2_pixelspace(width, height);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
}
void wmWindowViewport(wmWindow *win)
@@ -101,7 +101,7 @@ void wmWindowViewport(wmWindow *win)
glScissor(0, 0, width, height);
wmOrtho2_pixelspace(width, height);
- gpuLoadIdentity();
+ GPU_matrix_identity_set();
}
void wmOrtho2(float x1, float x2, float y1, float y2)
@@ -110,7 +110,7 @@ void wmOrtho2(float x1, float x2, float y1, float y2)
if (x1 == x2) x2 += 1.0f;
if (y1 == y2) y2 += 1.0f;
- gpuOrtho(x1, x2, y1, y2, -100, 100);
+ GPU_matrix_ortho_set(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_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index 350327e8590..0aa5e16a519 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -49,6 +49,7 @@
#include "BKE_workspace.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -132,8 +133,8 @@ static void toolsystem_unlink_ref(bContext *C, WorkSpace *workspace, bToolRef *t
bToolRef_Runtime *tref_rt = tref->runtime;
if (tref_rt->gizmo_group[0]) {
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
- if (wgt != NULL) {
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
+ if (gzgt != NULL) {
bool found = false;
/* TODO(campbell) */
@@ -154,8 +155,8 @@ static void toolsystem_unlink_ref(bContext *C, WorkSpace *workspace, bToolRef *t
UNUSED_VARS(workspace);
#endif
if (!found) {
- wmGizmoMapType *mmap_type = WM_gizmomaptype_ensure(&wgt->mmap_params);
- WM_gizmomaptype_group_unlink(C, bmain, mmap_type, wgt);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmomaptype_group_unlink(C, bmain, gzmap_type, gzgt);
}
}
}
@@ -173,9 +174,9 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre
bToolRef_Runtime *tref_rt = tref->runtime;
if (tref_rt->gizmo_group[0]) {
const char *idname = tref_rt->gizmo_group;
- wmGizmoGroupType *wgt = WM_gizmogrouptype_find(idname, false);
- if (wgt != NULL) {
- WM_gizmo_group_type_ensure_ptr(wgt);
+ wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
+ if (gzgt != NULL) {
+ WM_gizmo_group_type_ensure_ptr(gzgt);
}
else {
CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname);
@@ -184,20 +185,37 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre
if (tref_rt->data_block[0]) {
Main *bmain = CTX_data_main(C);
+ if ((tref->space_type == SPACE_VIEW3D) &&
+ (tref->mode == CTX_MODE_PARTICLE))
- /* Currently only brush data-blocks supported. */
- struct Brush *brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, tref_rt->data_block);
-
- if (brush) {
- wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- if (workspace == WM_window_get_active_workspace(win)) {
- Scene *scene = WM_window_get_active_scene(win);
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Paint *paint = BKE_paint_get_active(scene, view_layer);
- if (paint) {
- if (brush) {
- BKE_paint_brush_set(paint, brush);
+ {
+ const EnumPropertyItem *items = rna_enum_particle_edit_hair_brush_items;
+ const int i = RNA_enum_from_identifier(items, tref_rt->data_block);
+ if (i != -1) {
+ const int value = items[i].value;
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (workspace == WM_window_get_active_workspace(win)) {
+ Scene *scene = WM_window_get_active_scene(win);
+ ToolSettings *ts = scene->toolsettings;
+ ts->particle.brushtype = value;
+ }
+ }
+ }
+ }
+ else {
+ struct Brush *brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, tref_rt->data_block);
+ if (brush) {
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (workspace == WM_window_get_active_workspace(win)) {
+ Scene *scene = WM_window_get_active_scene(win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
+ if (paint) {
+ if (brush) {
+ BKE_paint_brush_set(paint, brush);
+ }
}
}
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index f55fc5703f4..f391c92b4ca 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -90,12 +90,11 @@
#include "GPU_immediate.h"
#include "GPU_material.h"
#include "GPU_texture.h"
+#include "GPU_context.h"
#include "BLF_api.h"
#include "UI_resources.h"
-#include "../../../intern/gawain/gawain/gwn_context.h"
-
/* for assert */
#ifndef NDEBUG
# include "BLI_threads.h"
@@ -124,7 +123,6 @@ static struct WMInitStruct {
/* ******** win open & close ************ */
static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate);
-static void wm_window_clear_drawable(wmWindowManager *wm);
/* XXX this one should correctly check for apple top header...
* done for Cocoa : returns window contents (and not frame) max size*/
@@ -195,15 +193,14 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
/* We need this window's opengl context active to discard it. */
GHOST_ActivateWindowDrawingContext(win->ghostwin);
- GWN_context_active_set(win->gwnctx);
+ GPU_context_active_set(win->gpuctx);
- /* Delete local gawain objects. */
- GWN_context_discard(win->gwnctx);
+ /* Delete local gpu context. */
+ GPU_context_discard(win->gpuctx);
GHOST_DisposeWindow(g_system, win->ghostwin);
win->ghostwin = NULL;
- win->gwnctx = NULL;
-
+ win->gpuctx = NULL;
}
}
@@ -646,7 +643,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
/* Clear drawable so we can set the new window. */
wm_window_clear_drawable(wm);
- win->gwnctx = GWN_context_create();
+ win->gpuctx = GPU_context_create();
/* needed so we can detect the graphics card below */
GPU_init();
@@ -1100,11 +1097,11 @@ static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool acti
if (activate) {
GHOST_ActivateWindowDrawingContext(win->ghostwin);
}
- GWN_context_active_set(win->gwnctx);
+ GPU_context_active_set(win->gpuctx);
immActivate();
}
-static void wm_window_clear_drawable(wmWindowManager *wm)
+void wm_window_clear_drawable(wmWindowManager *wm)
{
if (wm->windrawable) {
BLF_batch_reset();
@@ -1116,7 +1113,7 @@ static void wm_window_clear_drawable(wmWindowManager *wm)
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
{
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
if (win != wm->windrawable && win->ghostwin) {
// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */
@@ -1137,7 +1134,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
void wm_window_reset_drawable(void)
{
BLI_assert(BLI_thread_is_main());
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
wmWindowManager *wm = G_MAIN->wm.first;
if (wm == NULL)
@@ -1922,8 +1919,6 @@ void wm_window_raise(wmWindow *win)
void wm_window_swap_buffers(wmWindow *win)
{
- GPU_texture_orphans_delete(); /* XXX should be done elsewhere. */
- GPU_material_orphans_delete(); /* XXX Amen to that. */
GHOST_SwapWindowBuffers(win->ghostwin);
}
@@ -2172,7 +2167,12 @@ ViewLayer *WM_window_get_active_view_layer(const wmWindow *win)
return view_layer;
}
- return BKE_view_layer_default_view(scene);
+ view_layer = BKE_view_layer_default_view(scene);
+ if (view_layer) {
+ WM_window_set_active_view_layer((wmWindow *)win, view_layer);
+ }
+
+ return view_layer;
}
void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer)
@@ -2280,24 +2280,24 @@ void *WM_opengl_context_create(void)
* So we should call this function only on the main thread.
*/
BLI_assert(BLI_thread_is_main());
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
return GHOST_CreateOpenGLContext(g_system);
}
void WM_opengl_context_dispose(void *context)
{
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context);
}
void WM_opengl_context_activate(void *context)
{
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
GHOST_ActivateOpenGLContext((GHOST_ContextHandle)context);
}
void WM_opengl_context_release(void *context)
{
- BLI_assert(GPU_framebuffer_current_get() == 0);
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context);
}
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 385d61217ad..4fd5d66fb43 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -57,6 +57,7 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm);
void wm_window_process_events (const bContext *C);
void wm_window_process_events_nosleep(void);
+void wm_window_clear_drawable(wmWindowManager *wm);
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win);
void wm_window_reset_drawable(void);
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 18396149342..914211afd56 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -63,7 +63,9 @@
#include "BKE_global.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_node.h"
+#include "BKE_shader_fx.h"
#include "BKE_sound.h"
#include "BKE_image.h"
#include "BKE_particle.h"
@@ -371,6 +373,8 @@ int main(
BKE_cachefiles_init();
BKE_images_init();
BKE_modifier_init();
+ BKE_gpencil_modifier_init();
+ BKE_shaderfx_init();
DEG_register_node_types();
BKE_brush_system_init();
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index da5dcf9ff8b..283585598bf 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -1448,6 +1448,16 @@ static int arg_handle_scene_set(int argc, const char **argv, void *data)
Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
if (scene) {
CTX_data_scene_set(C, scene);
+
+ /* Set the scene of the first window, see: T55991,
+ * otherwise scrips that run later won't get this scene back from the context. */
+ wmWindow *win = CTX_wm_window(C);
+ if (win == NULL) {
+ win = CTX_wm_manager(C)->windows.first;
+ }
+ if (win != NULL) {
+ WM_window_set_active_scene(CTX_data_main(C), C, win, scene);
+ }
}
return 1;
}
diff --git a/tests/python/bl_pyapi_mathutils.py b/tests/python/bl_pyapi_mathutils.py
index 57bbbc7e73e..5aa95f9a5f7 100644
--- a/tests/python/bl_pyapi_mathutils.py
+++ b/tests/python/bl_pyapi_mathutils.py
@@ -104,7 +104,7 @@ class MatrixTesting(unittest.TestCase):
self.assertEqual(mat[1][3], 2)
self.assertEqual(mat[2][3], 3)
- def test_non_square_mult(self):
+ def test_matrix_non_square_matmul(self):
mat1 = Matrix(((1, 2, 3),
(4, 5, 6)))
mat2 = Matrix(((1, 2),
@@ -117,10 +117,10 @@ class MatrixTesting(unittest.TestCase):
(19, 26, 33),
(29, 40, 51)))
- self.assertEqual(mat1 * mat2, prod_mat1)
- self.assertEqual(mat2 * mat1, prod_mat2)
+ self.assertEqual(mat1 @ mat2, prod_mat1)
+ self.assertEqual(mat2 @ mat1, prod_mat2)
- def test_mat4x4_vec3D_mult(self):
+ def test_mat4x4_vec3D_matmul(self):
mat = Matrix(((1, 0, 2, 0),
(0, 6, 0, 0),
(0, 0, 1, 1),
@@ -131,23 +131,58 @@ class MatrixTesting(unittest.TestCase):
prod_mat_vec = Vector((7, 12, 4))
prod_vec_mat = Vector((1, 12, 5))
- self.assertEqual(mat * vec, prod_mat_vec)
- self.assertEqual(vec * mat, prod_vec_mat)
+ self.assertEqual(mat @ vec, prod_mat_vec)
+ self.assertEqual(vec @ mat, prod_vec_mat)
- def test_mat_vec_mult(self):
+ def test_mat_vec_matmul(self):
mat1 = Matrix()
vec = Vector((1, 2))
- self.assertRaises(ValueError, mat1.__mul__, vec)
- self.assertRaises(ValueError, vec.__mul__, mat1)
+ self.assertRaises(ValueError, mat1.__matmul__, vec)
+ self.assertRaises(ValueError, vec.__matmul__, mat1)
mat2 = Matrix(((1, 2),
(-2, 3)))
prod = Vector((5, 4))
- self.assertEqual(mat2 * vec, prod)
+ self.assertEqual(mat2 @ vec, prod)
+
+ def test_matrix_square_matmul(self):
+ mat1 = Matrix(((1, 0),
+ (1, 2)))
+ mat2 = Matrix(((1, 2),
+ (-2, 3)))
+
+ prod1 = Matrix(((1, 2),
+ (-3, 8)))
+ prod2 = Matrix(((3, 4),
+ (1, 6)))
+
+ self.assertEqual(mat1 @ mat2, prod1)
+ self.assertEqual(mat2 @ mat1, prod2)
+
+ """
+ # tests for element-wise multiplication
+
+ def test_matrix_mul(self):
+ mat1 = Matrix(((1, 0),
+ (1, 2)))
+ mat2 = Matrix(((1, 2),
+ (-2, 3)))
+ mat3 = Matrix(((1, 0, 2, 0),
+ (0, 6, 0, 0),
+ (0, 0, 1, 1),
+ (0, 0, 0, 1)))
+
+ prod = Matrix(((1, 0),
+ (-2, 6)))
+
+ self.assertEqual(mat1 * mat2, prod)
+ self.assertEqual(mat2 * mat1, prod)
+ self.assertRaises(ValueError, mat1.__mul__, mat3)
+ """
def test_matrix_inverse(self):
mat = Matrix(((1, 4, 0, -1),
@@ -185,7 +220,7 @@ class MatrixTesting(unittest.TestCase):
self.assertEqual(mat.inverted_safe(), inv_mat_safe)
- def test_matrix_mult(self):
+ def test_matrix_matmult(self):
mat = Matrix(((1, 4, 0, -1),
(2, -1, 2, -2),
(0, 3, 8, 3),
@@ -196,7 +231,7 @@ class MatrixTesting(unittest.TestCase):
(0, 48, 73, 18),
(16, -14, 26, -13)))
- self.assertEqual(mat * mat, prod_mat)
+ self.assertEqual(mat @ mat, prod_mat)
class VectorTesting(unittest.TestCase):
@@ -209,6 +244,49 @@ class VectorTesting(unittest.TestCase):
if v.length_squared != 0.0:
self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
+ def test_vector_matmul(self):
+ # produces dot product for vectors
+ vec1 = Vector((1, 3, 5))
+ vec2 = Vector((1, 2))
+
+ self.assertRaises(ValueError, vec1.__matmul__, vec2)
+ self.assertEqual(vec1 @ vec1, 35)
+ self.assertEqual(vec2 @ vec2, 5)
+
+ def test_vector_imatmul(self):
+ vec = Vector((1, 3, 5))
+
+ with self.assertRaises(TypeError):
+ vec @= vec
+
+ """
+ # tests for element-wise multiplication
+
+ def test_vector_mul(self):
+ # element-wise multiplication
+ vec1 = Vector((1, 3, 5))
+ vec2 = Vector((1, 2))
+
+ prod1 = Vector((1, 9, 25))
+ prod2 = Vector((2, 6, 10))
+
+ self.assertRaises(ValueError, vec1.__mul__, vec2)
+ self.assertEqual(vec1 * vec1, prod1)
+ self.assertEqual(2 * vec1, prod2)
+
+ def test_vector_imul(self):
+ # inplace element-wise multiplication
+ vec = Vector((1, 3, 5))
+ prod1 = Vector((1, 9, 25))
+ prod2 = Vector((2, 18, 50))
+
+ vec *= vec
+ self.assertEqual(vec, prod1)
+
+ vec *= 2
+ self.assertEqual(vec, prod2)
+ """
+
class QuaternionTesting(unittest.TestCase):